Имена файлов и linenumbers для соответствий кошки и grep

У вас действительно большой беспорядок в ваших руках. Внесение вклада указателей typedef, но в основном потому, что вы не можете выделить указатели nv, а вместо этого выделите тот же указатель listAdj, а затем сразу же перезаписать указатель с помощью NULL, создав 100 утечек памяти. [1150 ]

Подумайте об этом:

    for (i = 0; i < nv; i++) {
        graph->listAdj = (TypePointer*) malloc(sizeof(TypePointer));
    }

(Нет необходимости разыгрывать возвращение malloc, это не нужно. См .: Я разыгрываю результат malloc? и ... ВСЕГДА проверяйте КАЖДОЕ распределение)

graph->listAdj - это одиночный указатель, который содержит адрес для вновь выделенного блока памяти на каждой итерации, который затем перезаписывается при каждом последующем выделении.

Далее вы пытаетесь разыменовать перезаписанный указатель и установить несуществующие указатели на NULL, например:

    for (i = 0; i < nv; i++) {
        graph->listAdj[i] = NULL;
    }

Вы пытались выделить только один graph->listAdj (хотя и 100 раз) , а не nv указатели, как вы предполагали. Вы должны выделить память для nv указателей сразу.

Теперь давайте начнем с самого начала и очистим все, удалив ВСЕ typedef с, и просто используя int для bool, например

#include 
#include 

typedef struct aux {
    int vDest;
    int weight;
    struct aux *next;
} TypeEdge;

typedef struct {
    TypeEdge **listAdj;
    int numVertices;
    int numEdges;
} TypeGraph;

Теперь всем, кто смотрит на ваш код, совершенно очевидно, что listAdj является указателем на указатель с по TypeEdge. Там нет догадок или необходимости искать позже, задаваясь вопросом, что TypePointer 300 строк спустя, TypeEdge это TypeEdge, не более того.

Когда вы initializeGraph, вам нужно выделить все nv указатели, это один вызов malloc, а не в цикле. Затем вы можете зациклить указатели, установив их все NULL, например

int initializeGraph (TypeGraph *graph, int nv)
{
    if (nv < 0)
        return 0;

    graph->numVertices = nv;
    graph->numEdges = 0;
    int i;

    if ((graph->listAdj = malloc(sizeof *graph->listAdj * nv)) == NULL) {
        perror ("malloc-graph->listAdj");
        return 0;
    }

    for (i = 0; i < nv; i++)
        (graph->listAdj)[i] = NULL;

    return 1;
}

Далее, когда вы insertEdge(), вы должны обработать случай, когда вы вставляете первое ребро для этой вершины, или вам нужно выполнить итерацию до конца списка и вставить туда. Вам также необходимо настроить способ итерации до конца, чтобы не пытаться получить доступ к actual->next, если actual равно NULL. Собрав это вместе, вы можете сделать:

TypeEdge *insertEdge (int v1, int v2, int weight, TypeGraph *graph) 
{
    if (v1 < 0 || v1 > graph->numVertices || 
        v2 < 0 || v2 > graph->numVertices) {
        return NULL;
    }

    TypeEdge *actual = graph->listAdj[v1];
    while (actual && actual->next)
        actual = actual->next;

    TypeEdge *pNew = malloc(sizeof *pNew);
    if (!pNew) {
        perror ("malloc-pNew");
        return NULL;
    }

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = NULL;

    if (!actual)
        graph->listAdj[v1] = pNew;
    else
        actual->next = pNew;

    return (pNew);
}

( примечание: как тип возвращаемого значения функции был изменен на TypeEdge * с void, так что вы получите значимый возврат) это может указывать на Успех / Неудачу вашей попытки вставить ребро. Никогда не выделяйте в функции void без возможности указать вызывающей функции, было ли выделение (и остаток критических шагов) успешным или неудачным)

[ 1161] Пока ваш main() пытается insertEdge(), он не дает никаких указаний на то, что произошло. Если у вас нет какого-либо способа проверки правильности вставленного края, это заставляет задуматься. Просто напишите короткий набор функций print для обработки вывода списка ребер для каждой вершины, которая их имеет, например,

void prnedge (const TypeEdge *e)
{
    do
        printf (" %3d %3d\n", e->vDest, e->weight);
    while ((e = e->next));
}

void print_edge (const TypeEdge *e, int edge)
{
    printf ("\nedge %d\n", edge);
    prnedge (e);
}

void print_graph (const TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            print_edge (g->listAdj[i], i);
}

Если вы выделили память, вы должны иметь возможность также освободить эту память. Аналогичный короткий набор функций может обрабатывать освобождение каждого списка, например

void freelist (TypeEdge *l)
{
    while (l) {
        TypeEdge *victim = l;
        l = l->next;
        free (victim);
    }
}

void free_graphlists (TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            freelist (g->listAdj[i]);

    free (g->listAdj);
}

Который вы можете назвать в main() как:

int main (void) {

    TypeGraph graph;
    int result = initializeGraph (&graph, 100);

    if (result) {
        insertEdge (2, 3, 1, &graph);
        insertEdge (2, 4, 1, &graph);
    }

    print_graph (&graph);
    free_graphlists (&graph);

    return 0;
}

В целом, вы можете сделать:

#include 
#include 

typedef struct aux {
    int vDest;
    int weight;
    struct aux *next;
} TypeEdge;

typedef struct {
    TypeEdge **listAdj;
    int numVertices;
    int numEdges;
} TypeGraph;

int initializeGraph (TypeGraph *graph, int nv)
{
    if (nv < 0)
        return 0;

    graph->numVertices = nv;
    graph->numEdges = 0;
    int i;

    if ((graph->listAdj = malloc(sizeof *graph->listAdj * nv)) == NULL) {
        perror ("malloc-graph->listAdj");
        return 0;
    }

    for (i = 0; i < nv; i++)
        (graph->listAdj)[i] = NULL;

    return 1;
}

TypeEdge *insertEdge (int v1, int v2, int weight, TypeGraph *graph) 
{
    if (v1 < 0 || v1 > graph->numVertices || 
        v2 < 0 || v2 > graph->numVertices) {
        return NULL;
    }

    TypeEdge *actual = graph->listAdj[v1];
    while (actual && actual->next)
        actual = actual->next;

    TypeEdge *pNew = malloc(sizeof *pNew);
    if (!pNew) {
        perror ("malloc-pNew");
        return NULL;
    }

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = NULL;

    if (!actual)
        graph->listAdj[v1] = pNew;
    else
        actual->next = pNew;

    return (pNew);
}

void prnedge (const TypeEdge *e)
{
    do
        printf (" %3d %3d\n", e->vDest, e->weight);
    while ((e = e->next));
}

void print_edge (const TypeEdge *e, int edge)
{
    printf ("\nedge %d\n", edge);
    prnedge (e);
}

void print_graph (const TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            print_edge (g->listAdj[i], i);
}

void freelist (TypeEdge *l)
{
    while (l) {
        TypeEdge *victim = l;
        l = l->next;
        free (victim);
    }
}

void free_graphlists (TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            freelist (g->listAdj[i]);

    free (g->listAdj);
}

int main (void) {

    TypeGraph graph;
    int result = initializeGraph (&graph, 100);

    if (result) {
        insertEdge (2, 3, 1, &graph);
        insertEdge (2, 4, 1, &graph);
    }

    print_graph (&graph);
    free_graphlists (&graph);

    return 0;
}

Пример использования / вывода [ 1173]

$ ./bin/edgetype

edge 2
   3   1
   4   1

Использование памяти / проверка ошибок

В любом написанном вами коде, который динамически выделяет память, у вас есть 2 обязанности в отношении любого выделенный блок памяти: (1) всегда сохраняет указатель на начальный адрес для блока памяти, поэтому (2) его можно освободить , когда он больше не нужен. [ 1167]

Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы убедиться, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, пытаться прочитать или основать условный переход на неинициализированном значении и, наконец, , чтобы подтвердить, что вы освобождаете всю выделенную память.

Для Linux valgrind - нормальный выбор. Для каждой платформы есть похожие проверки памяти. Все они просты в использовании, просто запустите вашу программу через него.

$ valgrind ./bin/edgetype
==21679== Memcheck, a memory error detector
==21679== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21679== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==21679== Command: ./bin/edgetype
==21679==

edge 2
   3   1
   4   1
==21679==
==21679== HEAP SUMMARY:
==21679==     in use at exit: 0 bytes in 0 blocks
==21679==   total heap usage: 3 allocs, 3 frees, 832 bytes allocated
==21679==
==21679== All heap blocks were freed -- no leaks are possible
==21679==
==21679== For counts of detected and suppressed errors, rerun with: -v
==21679== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Всегда подтверждайте, что вы освободили всю выделенную память и что ошибок памяти нет.

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

5
задан Léo Léopold Hertz 준영 26 February 2009 в 20:05
поделиться

7 ответов

grep google *.php

если Вы хотите охватить много каталогов:

find . -name \*.php -print0 | xargs -0 grep -n -H google

(как объяснено в комментариях,-H полезен, если xargs придумывает только один остающийся файл),

17
ответ дан 18 December 2019 в 06:04
поделиться

Вы не должны делать

$ *.php | grep

Это означает, "запускает первую программу PHP, с названием остальных подстановочный знак как параметры, и затем выполняет grep на выводе".

Это должно быть:

$ grep -n -H "google" *.php

-n флаг говорит этому делать номера строки, и -H флаг говорит этому отображать имя файла, даже если существует только файл. Grep примет значение по умолчанию к показу имен файлов, если будет несколько искавших файлов, но Вы, вероятно, хотите удостовериться, что вывод последователен независимо от сколько соответствующих файлов, там.

5
ответ дан 18 December 2019 в 06:04
поделиться

Используйте "человека grep" для наблюдения других функций.

for i in $(ls *.php); do  grep -n --with-filename "google" $i; done;
0
ответ дан 18 December 2019 в 06:04
поделиться
find . -name "*.php" -print | xargs grep -n "searchstring"
0
ответ дан 18 December 2019 в 06:04
поделиться
find ./*.php -exec grep -l 'google' {} \; 
1
ответ дан 18 December 2019 в 06:04
поделиться
grep -RH "google" *.php
2
ответ дан 18 December 2019 в 06:04
поделиться

Пожалуйста, ознакомьтесь с подтверждением на http://betterthangrep.com . Эквивалент того, что вы пытаетесь сделать:

ack google --php
2
ответ дан 18 December 2019 в 06:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: