C: конвертировать строку в длинную без знака длинную ошибку - PullRequest
0 голосов
/ 08 ноября 2018

Я просто пытаюсь преобразовать String (прочитанный из строки в файле) в переменную long long. Моя проблема в том, что я получаю ошибку сегментации, и я не знаю почему ... Вот код: (я добавил комментарий к ошибке в функции «3 ° Call»)

#define CAPACITY (unsigned long long) 11
#define INTEGERS_PATH // the path to the file I wish to read

typedef struct {
    void** array;
    unsigned long long el_num;
    unsigned long long array_capacity;
    int (*compare)(void*,void*);
} GenericArray;

// used for compare elements
struct record{
    char* string_field; // used in case the GenericArray is made of strings items
    long long integer_field; // used in case the GenericArray is made of long long items
};

// END OF STRUCTS ---------------------------------------------------------------------------------
// BEGIN OF FUNCTIONS -----------------------------------------------------------------------------

int main(int argc, char const *argv[]) {
    test_with_comparison_function(compare_record_int_field);
    return (EXIT_SUCCESS);
}

// Compare function passed to generic_array_create() for create the GenericArray
static int compare_record_int_field(void* r1_p,void* r2_p){
    if(r1_p == NULL){
        fprintf(stderr,"compare_record_int_field: the first parameter is a null pointer");
        exit(EXIT_FAILURE);
    }
    if(r2_p == NULL){
        fprintf(stderr,"compare_record_int_field: the second parameter is a null pointer");
        exit(EXIT_FAILURE);
    }

    struct record *rec1_p = (struct record*)r1_p;
    struct record *rec2_p = (struct record*)r2_p;

    if(rec1_p->integer_field < rec2_p->integer_field){
        return(1);
    }
    return(0);
}

// 1° Call
static void test_with_comparison_function(int (*compare)(void*, void*)) {
    GenericArray* array = generic_array_create(compare);
    load_array(array);
    print_array(array); // it prints the array
    free_array(array); // it frees the memory alocated by the array
}

// 2° Call
GenericArray *generic_array_create(int (*compare)(void*,void*)){
    GenericArray *array = malloc(sizeof(GenericArray));
    if(array == NULL){
        fprintf(stderr, "generic_array_create: unable to allocate memory for the generic array");
        exit(EXIT_FAILURE);
    }

    array->array = malloc(CAPACITY * sizeof(void*));
    array->el_num = 0;
    array->array_capacity = CAPACITY;
    array->compare = compare;

    return(array);
}

// 3° Call
static void load_array(GenericArray* array){
    clock_t start = clock(); // for timing

    printf("\nLoading data from file...\n");

    FILE * dataset_p = fopen(INTEGERS_PATH, "r");
    if(dataset_p == NULL){
        fprintf(stderr,"main: unable to open the file");
        exit(EXIT_FAILURE);
    }

    char *read_line_p;
    char buffer[1024];
    int buf_size = 1024;

    while(fgets(buffer, buf_size, dataset_p) != NULL){
        read_line_p = malloc((strlen(buffer) + 1) * sizeof(char));
        strcpy(read_line_p, buffer);
        char *string_field_in_read_line_p = strtok(read_line_p, "\n");
        char *integer_field_in_read_line_p = strtok(NULL, "\n");

        char *string_field_1 = malloc((strlen(string_field_in_read_line_p) + 1) * sizeof(char));
        char *string_field_2 = malloc((strlen(string_field_in_read_line_p) + 1) * sizeof(char));

        strcpy(string_field_1,string_field_in_read_line_p);
        strcpy(string_field_2,string_field_in_read_line_p);

        /* Here begins errors (SEGMENTATION FAULT) */
        int integer_field = atoi(integer_field_in_read_line_p); 
        long long integer_field = strtoll(integer_field_in_read_line_p, (char **) NULL, 10);

        struct record *record_p = malloc(sizeof(struct record));
        record_p->string_field = string_field_1;
        record_p->integer_field = integer_field;

        generic_array_add(array, (void*) record_p);

        free(read_line_p); 
    }

    fclose(dataset_p);
    printf("\nData loaded\n");
}

Вот файл, который я хочу прочитать, это простой .txt файл:

9
8
7
6
5
4
3
2
2
1
10

1 Ответ

0 голосов
/ 08 ноября 2018

Проблема в следующих трех строках:

while(fgets(buffer, buf_size, dataset_p) != NULL){
    // ...
    char *string_field_in_read_line_p = strtok(read_line_p, "\n");
    char *integer_field_in_read_line_p = strtok(NULL, "\n");

Функция fgets читает одну строку и оставляет новую строку '\n' в конце этого. Это означает, что в строке, которую вы пытаетесь токенизировать, есть только один '\n'. Таким образом, второй вызов strtok должен вернуть NULL.

Вы не проверяете это, и поэтому любое разыменование этого указателя NULL (что происходит в функциях преобразования) приведет к неопределенному поведению и возможным сбоям.

...