C - 带有 getline() 的字符指针,用于从文本文件中读取。为什么会这样?如何改进我的解决方法?
C - char pointers with getline() to read from a text file. Why does this happen? How to improve my workaround?
快速前提:由于 this 问题,我解决了我想做的事情,但我仍然想了解 C 在这种情况下是如何工作的。
我有一个与此类似的纯文本文件(我们称之为 my_file):
11
alpha
23.45
beta
我在 .c 文件中编写了一个函数,它读取该文件的每一行并根据我创建的自定义 struct
存储所有这些值。假设它是:
struct myStruct
{
int value1;
char *value2;
double value3
char *value4;
} my_struct;
这是我写的函数(不工作):
void myFunct(char *my_file_path, struct myStruct *my_struct)
{
FILE *my_file = fopen(my_file_path, "r");
int line_out;
char *line = NULL;
size_t len = 0;
if (my_file == NULL)
{
perror("Could not open file");
}
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value1 = atoi(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value2 = line;
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value3 = atof(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value4 = line;
}
else
perror("Error reading line of file");
fclose(my_file);
}
注意我将结构实例作为指针传递。
也就是说,调用该函数会产生以下结果(通过 printf
的终端输出):
value1: 11
value2: beta
value3: 23.450000
value4: beta
所以有两个问题:line
“指向指针的指针”(对吧?)似乎跳到下一个位置并影响了上一个条目(这是可以理解的,但我不确定如何在不创建新变量的情况下避免这种情况),并且在字符串末尾添加了一个 \n
,我不知道它来自哪里。
我不明白这一般是如何工作的,我也想知道一些聪明的想法来解决这个问题。
以防万一有人需要它(但回复中肯定会有更好的解决方案),我已经修改了我的功能:
void myFunct(char *my_file_path, struct myStruct *my_struct)
{
FILE *my_file = fopen(my_file_path, "r");
int line_out;
char *line = NULL;
char *line2 = NULL;
char *line4 = NULL;
size_t len = 0;
if (my_file == NULL)
{
perror("Could not open file");
}
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value1 = atoi(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line2, &len, my_file)) != -1)
{
line2[strlen(line2) - 1] = '[=14=]';
my_struct->value2 = line2;
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value3 = atof(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line4, &len, my_file)) != -1)
{
line4[strlen(line4) - 1] = '[=14=]';
my_struct->value4 = line4;
}
else
perror("Error reading line of file");
fclose(my_file);
}
这不是很可扩展,但可以完成工作。
感谢您的帮助!
getline()
仅在 line
参数指向空指针或未指向足够的 space 时分配新的行缓冲区。否则它会重用传递给它的相同缓冲区。所以每次你做
my_struct->something = line;
您可能正在保存指向同一字符串的指针。
使用 strdup()
复制字符串。
my_struct->something = strdup(line);
不要忘记在函数末尾 free(line)
,因为当您制作这些副本时不再需要它。
字符串末尾的\n
是结束用户输入的换行符。在 getline()
documentation:
中说得很清楚
The buffer is null-terminated and includes the newline character, if one was found.
这就像 fgets()
。您可以轻松删除它:
if (line[strlen(line)-1] == '\n') {
line[strlen(line)-1] = '[=12=]';
}
快速前提:由于 this 问题,我解决了我想做的事情,但我仍然想了解 C 在这种情况下是如何工作的。
我有一个与此类似的纯文本文件(我们称之为 my_file):
11
alpha
23.45
beta
我在 .c 文件中编写了一个函数,它读取该文件的每一行并根据我创建的自定义 struct
存储所有这些值。假设它是:
struct myStruct
{
int value1;
char *value2;
double value3
char *value4;
} my_struct;
这是我写的函数(不工作):
void myFunct(char *my_file_path, struct myStruct *my_struct)
{
FILE *my_file = fopen(my_file_path, "r");
int line_out;
char *line = NULL;
size_t len = 0;
if (my_file == NULL)
{
perror("Could not open file");
}
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value1 = atoi(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value2 = line;
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value3 = atof(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value4 = line;
}
else
perror("Error reading line of file");
fclose(my_file);
}
注意我将结构实例作为指针传递。
也就是说,调用该函数会产生以下结果(通过 printf
的终端输出):
value1: 11
value2: beta
value3: 23.450000
value4: beta
所以有两个问题:line
“指向指针的指针”(对吧?)似乎跳到下一个位置并影响了上一个条目(这是可以理解的,但我不确定如何在不创建新变量的情况下避免这种情况),并且在字符串末尾添加了一个 \n
,我不知道它来自哪里。
我不明白这一般是如何工作的,我也想知道一些聪明的想法来解决这个问题。 以防万一有人需要它(但回复中肯定会有更好的解决方案),我已经修改了我的功能:
void myFunct(char *my_file_path, struct myStruct *my_struct)
{
FILE *my_file = fopen(my_file_path, "r");
int line_out;
char *line = NULL;
char *line2 = NULL;
char *line4 = NULL;
size_t len = 0;
if (my_file == NULL)
{
perror("Could not open file");
}
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value1 = atoi(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line2, &len, my_file)) != -1)
{
line2[strlen(line2) - 1] = '[=14=]';
my_struct->value2 = line2;
}
else
perror("Error reading line of file");
if ((line_out = getline(&line, &len, my_file)) != -1)
{
my_struct->value3 = atof(line);
}
else
perror("Error reading line of file");
if ((line_out = getline(&line4, &len, my_file)) != -1)
{
line4[strlen(line4) - 1] = '[=14=]';
my_struct->value4 = line4;
}
else
perror("Error reading line of file");
fclose(my_file);
}
这不是很可扩展,但可以完成工作。
感谢您的帮助!
getline()
仅在 line
参数指向空指针或未指向足够的 space 时分配新的行缓冲区。否则它会重用传递给它的相同缓冲区。所以每次你做
my_struct->something = line;
您可能正在保存指向同一字符串的指针。
使用 strdup()
复制字符串。
my_struct->something = strdup(line);
不要忘记在函数末尾 free(line)
,因为当您制作这些副本时不再需要它。
字符串末尾的\n
是结束用户输入的换行符。在 getline()
documentation:
The buffer is null-terminated and includes the newline character, if one was found.
这就像 fgets()
。您可以轻松删除它:
if (line[strlen(line)-1] == '\n') {
line[strlen(line)-1] = '[=12=]';
}