动态地从文本文件中读取一行
Reading a line from text file dynamically
我正在尝试学习如何在读取文件时为很长的行动态分配内存。我在这里和网上搜索并尝试了一些代码。
首先,这是我的第一个非动态代码:
char line[256];
file = fopen(inputFileName, "r");
// Here, of course I checked file is opened or not.
while (fgets(line, sizeof(line), file)) {
// do some operations
}
// Closing operations
当我阅读文件时,这对我有用。但这里的行必须等于或小于 255 个字符。所以,我想从文件中读取例如 300 个字符长度的行。
我尝试了以下代码:
size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
printf("Memory not allocated!!\n");
return -2;
}
file = fopen(inputFileName, "r");
while (fgets(line, sizeof(line), file)) {
while(line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'){
char *tmp = realloc (line, 2 * maxl);
//fgets(line, sizeof(line), file);
if (tmp) {
line = tmp;
maxl *= 2;
}
else{
printf("Not enough memory for this line!!\n");
return -3;
}
}
// do some operations
}
我试图在这个问题中实际实现答案:Reading a line from file in C, dynamically
但它总是输入"Not enough memory"部分代码。那么,我做错了什么?
感谢您的回答和建议。
编辑:代码根据第一条评论更新。
编辑 2:代码总是从文件中读取相同的 3 个字符。
假设文件是这样的:
abcdabcdabcd...
即使在重新分配操作之后,line
变量始终是 "abc"。
以下是您需要做的一些更正:
- 将
char *tmp = realloc (line, 2 * maxl);
更改为 char *tmp = realloc (line, 2 * maxl * sizeof(char);
(只是一个建议!)。
- 重新分配内存后,您必须在文件中重新查找才能读取完整的字符串。例如,
fseek(file,0,SEEK_SET);
将查找文件的开头 inputFileName
.
sizeof(line)
将始终是一个 常量 值,因为您正在计算字符指针的大小,而不是字符串长度。因此,将 while (fgets(line, sizeof(line), file)) {
更改为 while (fgets(line, maxl, file)) {
。
- 将注释行
//fgets(line, sizeof(line), file);
移到 if (tmp)
块内,因为您希望在重新分配后再次从文件中读取字符串。
- 表达式
line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'
逻辑上不正确。您可能希望仅当 line
的最后一个字符既不是 '\n'
也不是 '\r'
时才进入循环。所以你必须在那里使用 &&
而不是 ||
.
修改后的代码如下:
size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
printf("Memory not allocated!!\n");
return -2;
}
file = fopen(inputFileName, "r");
while (fgets(line, maxl, file)) {
while(line[strlen(line) - 1] != '\n' && line[strlen(line) - 1] != '\r'){
char *tmp = realloc (line, 2 * maxl * sizeof(char));
fseek(file,0,SEEK_SET); //or wherever you want to seek to
if (tmp) {
line = tmp;
maxl *= 2;
fgets(line, maxl, file);
}
else{
printf("Not enough memory for this line!!\n");
return -3;
}
}
printf("%s\n",line); //just to check
}
您的代码中的问题是:
- 您只从文件中读取了几个字符,因为您只读取了
sizeof(line)
个字符,而不是 maxl
个字符。
- 您可能想要返回一些字节以再次读取整个字符串,但这取决于您。
- 仅当重新分配成功时(
if(tmp)
),重新分配后才从文件中再次读取字符串。
现在,为什么要打印 Not enough memory..
?
这是因为您的循环 运行 多次并且重新分配的内存大小(maxl
值)正在增加,例如 256、512、1024、2048、...、65536、.. .
当此大小大到足以让编译器拒绝重新分配时,您就会打印出该错误字符串。如果愿意,请尝试调试您的代码版本或在内部 while
循环的每次迭代中打印 maxl
的值。
我正在尝试学习如何在读取文件时为很长的行动态分配内存。我在这里和网上搜索并尝试了一些代码。
首先,这是我的第一个非动态代码:
char line[256];
file = fopen(inputFileName, "r");
// Here, of course I checked file is opened or not.
while (fgets(line, sizeof(line), file)) {
// do some operations
}
// Closing operations
当我阅读文件时,这对我有用。但这里的行必须等于或小于 255 个字符。所以,我想从文件中读取例如 300 个字符长度的行。
我尝试了以下代码:
size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
printf("Memory not allocated!!\n");
return -2;
}
file = fopen(inputFileName, "r");
while (fgets(line, sizeof(line), file)) {
while(line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'){
char *tmp = realloc (line, 2 * maxl);
//fgets(line, sizeof(line), file);
if (tmp) {
line = tmp;
maxl *= 2;
}
else{
printf("Not enough memory for this line!!\n");
return -3;
}
}
// do some operations
}
我试图在这个问题中实际实现答案:Reading a line from file in C, dynamically
但它总是输入"Not enough memory"部分代码。那么,我做错了什么?
感谢您的回答和建议。
编辑:代码根据第一条评论更新。
编辑 2:代码总是从文件中读取相同的 3 个字符。
假设文件是这样的:
abcdabcdabcd...
即使在重新分配操作之后,line
变量始终是 "abc"。
以下是您需要做的一些更正:
- 将
char *tmp = realloc (line, 2 * maxl);
更改为char *tmp = realloc (line, 2 * maxl * sizeof(char);
(只是一个建议!)。 - 重新分配内存后,您必须在文件中重新查找才能读取完整的字符串。例如,
fseek(file,0,SEEK_SET);
将查找文件的开头inputFileName
. sizeof(line)
将始终是一个 常量 值,因为您正在计算字符指针的大小,而不是字符串长度。因此,将while (fgets(line, sizeof(line), file)) {
更改为while (fgets(line, maxl, file)) {
。- 将注释行
//fgets(line, sizeof(line), file);
移到if (tmp)
块内,因为您希望在重新分配后再次从文件中读取字符串。 - 表达式
line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'
逻辑上不正确。您可能希望仅当line
的最后一个字符既不是'\n'
也不是'\r'
时才进入循环。所以你必须在那里使用&&
而不是||
.
修改后的代码如下:
size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
printf("Memory not allocated!!\n");
return -2;
}
file = fopen(inputFileName, "r");
while (fgets(line, maxl, file)) {
while(line[strlen(line) - 1] != '\n' && line[strlen(line) - 1] != '\r'){
char *tmp = realloc (line, 2 * maxl * sizeof(char));
fseek(file,0,SEEK_SET); //or wherever you want to seek to
if (tmp) {
line = tmp;
maxl *= 2;
fgets(line, maxl, file);
}
else{
printf("Not enough memory for this line!!\n");
return -3;
}
}
printf("%s\n",line); //just to check
}
您的代码中的问题是:
- 您只从文件中读取了几个字符,因为您只读取了
sizeof(line)
个字符,而不是maxl
个字符。 - 您可能想要返回一些字节以再次读取整个字符串,但这取决于您。
- 仅当重新分配成功时(
if(tmp)
),重新分配后才从文件中再次读取字符串。
现在,为什么要打印 Not enough memory..
?
这是因为您的循环 运行 多次并且重新分配的内存大小(maxl
值)正在增加,例如 256、512、1024、2048、...、65536、.. .
当此大小大到足以让编译器拒绝重新分配时,您就会打印出该错误字符串。如果愿意,请尝试调试您的代码版本或在内部 while
循环的每次迭代中打印 maxl
的值。