fgets () инициализирует переменные самостоятельно - PullRequest
0 голосов
/ 25 августа 2018

Я работаю над фрагментом кода, который хочет прочитать данные из файла, проанализировать эти данные и сохранить каждое слово файла в массиве символов. Затем я хочу использовать этот массив, чтобы сравнить его со строкой, считанной из отдельного файла - эту часть вам не нужно будет видеть ниже.

Что-то очень смешное происходит с моими данными, и я безуспешно искал ответ. Вот сокращенная и упрощенная версия кода (извините, некоторые имена переменных на французском языке):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define maximum 200000

//  CODE

typedef unsigned idx;
typedef char * str;
typedef enum {False, True} bool;

#define max_mots 200000                             
char *mots[max_mots];                               
idx mot_libre = 0;                                  

#define max_refs 16                                 
idx refs[max_mots][max_refs];                       
idx ref_libre[max_mots];                            

void usage(str message) 
{   
    fprintf(stderr, "%s\n", message); 
    exit(1); 
}

str stoplist[max_mots];

void indexe(str ligne, idx ref)                     
{
    printf("stoplist %p: %s\n", &stoplist, *stoplist);
    printf("ligne %p: %s\n", &ligne, ligne);    
}

int main(int argc, const str argv[]) 
{
    int i = 0;
    if (argc < 2) usage("manque le nom du fichier...");
    if (strcmp(argv[2], "-s") == 0){
        FILE * stop = fopen(argv[3], "r");          
        if (! stop) usage("fichier non conforme...");
        char liste[max_mots];
        fgets(liste, maximum, stop);
        str buffer = strtok(liste, " ");
        while (buffer != NULL) {
            printf("%s\n", buffer);
            stoplist[i] = buffer;
            buffer = strtok(NULL, " "); 
            i++;
        }
        fclose(stop);
    } 
    char ligne[maximum];                            
    printf("ligne %p :%s\n", &ligne, ligne);
    FILE * flux = fopen(argv[1], "r");
    if (! flux) { 
        usage("wrong file"); 
    }
    idx x = 0
    while (fgets(ligne, maximum, flux))         
        indexe(ligne, ++x);                             
    fclose(flux);
    return 0;
}

Код должен быть выполнен в следующем формате:

[name of the executable] [name of a text file to read from] -s [name of another text file to read from]

Первый текстовый файл может быть что-то вроде:

hi, I am coding in C.

И второй может быть:

am I in 

Код намеревается сохранить каждое слово в указателе stoplist на массиве char из второго текстового файла и сохранить всю строку первого текстового файла в Массив .

Возврат после выполнения кода:

am
I
in

ligne [whatever address it has] : am // WHY?! I have not initialized you with this at any point in the code!
stoplist [whatever address it has] : Hi, I am coding in C. // Should be "am"

ligne [whatever address it has] : Hi, I am coding in C.

Когда я снова вызываю fgets (), чтобы присвоить строку Привет, я кодирую в C для ligne , оба ligne и stoplist будет обновлено до этого нового значения! Буквально понятия не имею, почему. Обе переменные имеют разные адреса, и, как вы можете видеть из кода, используемый ввод также имеет другое имя; обе сессии чтения закрыты правильно.

Есть идеи? Я знаю, что это связано с тем, что они указывают на что-то похожее, но я не могу понять, почему и где ...

1 Ответ

0 голосов
/ 25 августа 2018

Вот как инициализируется stoplist:

stoplist[i] = buffer;

buffer отсюда:

str buffer = strtok(liste, " ");

liste - локальная переменная в первом блоке:

char liste[max_mots];

Другими словами, stoplist сохраняет указатели в liste, но к тому времени, как вы исследуете содержимое stoplist, liste уже исчезло (локальные переменные уничтожаются в конце их блока). Это известно как «висячие указатели».

Ваш код имеет неопределенное поведение.

...