【发布时间】:2021-12-29 16:48:28
【问题描述】:
我正在尝试读取一个 CSV 文件并编写一个函数来将一行数据解析为一个字符串数组,该函数会动态更改数组的大小并相应地更新 size 和 str_size。我编写了一个名为find_key() 的正常工作函数来定位相关行的fseek() 位置。我遇到了一个我认为与字符串数组的分配有关的问题:我在 while 循环底部的行上遇到了分段错误,它读取为data[data_count][str_pos] = curr。当我尝试访问data[0][0] 时程序中断,尽管据我所知我已经正确分配了内存。任何帮助将不胜感激!
/**
* @brief Get a row from the provided CSV file by first item. Dynamically
* allocated memory to data array
*
* @param file
* @param key First item of row
* @param data Array of strings containing data
* @param size Size of array
* @param str_size Size of strings in array
* @return 0 if successful, -1 if the row cannot be found, or 1 otherwise
*/
int csv_get_row(FILE *file, char *key, char **data, size_t *size, size_t *str_size) {
if(!file || !key) return 1;
/* Get the position of the beginning of the line starting with the key */
long pos = find_key(file, key);
if(pos == -1) return -1;
fseek(file, pos, SEEK_SET);
/* If these parameters aren't useful values, assign default values */
if(*size < 1) *size = DEFAULT_ARRAY_SIZE;
if(*str_size < 1) *str_size = DEFAULT_BUFFER_SIZE;
/* If the memory for the array hasn't been allocated, do so now */
if(!data) data = (char**) malloc(*size * *str_size);
/* Get characters one-by-one, keeping track of the current amount of elements and the current buffer position */
size_t data_count = 0;
size_t str_pos = 0;
char curr;
while(fscanf(file, "%c", &curr)) {
if(data_count >= *size) data = (char**) realloc(data, (*size *= 2) * *str_size);
if(str_pos >= *str_size) data = (char**) realloc(data, *size * (*str_size *= 2));
if(curr == ',') {
data[data_count][str_pos] = '\0';
data_count++;
str_pos = 0;
continue;
}
if(curr == '\n') {
data[data_count][str_pos] = '\0';
data_count++;
break;
}
data[data_count][str_pos] = curr;
str_pos++;
}
/* Resize the array to fit */
*size = data_count;
data = (char**) realloc(data, *size * *str_size);
return 0;
}
【问题讨论】:
-
while(fscanf(file, "%c", &curr))会导致无限循环,因为EOF是一个非零(即真)值。循环应该是while(fscanf(file, "%c", &curr) == 1) -
至于内存分配,我们需要看看你如何调用那个函数。见minimal reproducible example。
-
不确定这是否是您的问题的原因,但请注意,您对函数中的
data双指针所做的任何更改都将永远丢失返回。该指针按值从调用模块传递给函数,并且您的函数所做的更改将不会传递回调用者。 -
IMO,您的代码 waaaay 过于复杂,无法从 CSV 文件中读取一行并将其拆分为多个字段。首先让您的代码读取行。然后使用单独的函数将每行拆分为字段。然后获取这些字段并填写您的数组。您可以轻松地测试每个步骤并让它们正常工作。你所写的是将所有这些混搭成一个,它太复杂而无法工作,而且不可能一步一步地测试。而且因为您正在阅读
char-by-char并涉及fseek(),所以它也是 S-L-O-W。