C:将字符串转换为unsigned long long错误

时间:2018-11-08 09:33:37

标签: c segmentation-fault strtoull

我只是想在String变量中转换long long(从文件的一行读取)。我的问题是我遇到了细分错误,我不知道为什么...这是代码: (我对“ 3°通话”功能的错误发表了评论)

#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 :(得分:3)

问题是以下三行:

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指针的任何取消引用(在转换函数中发生)都将导致undefined behavior并可能导致崩溃。