给定一个按行排序信息的文件,我被要求编写一个程序来将每一行存储在一个字符串中。
This is the first line.
This is the second line.
This is the third line.
This is the fourth line.
我的代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 70
#define NLine 4
int main()
{
FILE *arq;
char line[MAX];
char *eof;
char name[20];
char *nline[NLine];
int i;
printf("\nGive me the name of the file: ");
fgets(name, 20 , stdin);
arq = fopen(name, "r");
while( ( eof = fgets(line, MAX, arq ) )!= NULL )
{
nline[i] = strdup(eof);
i++;
}
printf("\n");
for(i = 0; i < NLine; i++)
printf("%s", nline[i]);
for(i = 0; i < NLine; i++)
free( nline[i] );
fclose(arq);
return 0;
}
我的输出是分段错误;但当我用arq = fopen(name, "r");
代替arq = fopen("test.txt", "r");
时,程序运行完美。我执行gdb
并返回
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a7ea2b in fgets () from /lib64/libc.so.6
使用字符串数组作为参数调用fopen
是错误,还是我在程序中做错了什么?
另外我想知道该部分是怎样的
while( ( eof = fgets(line, MAX, arq ) )!= NULL )
{
nline[i] = strdup(eof);
i++;
}
的工作原理。我刚看到这个question中的代码并将其设置为可行;但我不明白该函数如何读取另一行而不是保持读取同一行,因为从文件中读取eof
的方式没有明显变化。
答案 0 :(得分:1)
您没有初始化nline
数组中的指针。您需要将每个设置为NULL。否则,当你过来并在以后释放它们时,你将有不确定的行为。
for( i = 0; i < NLine; i++ ) nline[i] = NULL;
或者,您可以保存您读入的行数,并且只释放那么多的值,而不是所有NLine
个值。您可能应该这样做,因为在打印值时需要执行相同的操作。你想得到一个计数。我在这里使用了line_count
。
for( i = 0; i < line_count; i++ ) free(nline[i]);
当你读取行时,你有潜在的缓冲区溢出。你需要确保你的数组索引保持在范围内:
line_count = 0;
while( line_count < NLine && fgets(line, MAX, arq) )
nline[i++] = strdup(line);
还有另一件事,正如用户 Myforwik 指出的那样,fgets
会在字符串中留下行分隔符,并且在读入文件名时必须自行删除它:
if( fgets(name, 20 , stdin) ) {
/* Remove line terminator(s) if any: iscntrl() from ctype.h is okay */
for( i = strlen(name)-1; i >= 0 && iscntrl(p[i]); i-- ) p[i] = '\0';
} else {
name[0] = '\0';
}
答案 1 :(得分:1)
fgets将包含名称中的carrage返回,因此您尝试打开名称末尾带有回车符的文件,该文件将失败。由于您从不检查程序是否成功打开了文件,因此下一个fgets将是未定义的行为。
首先,您需要在尝试fopen后添加:if (!arq) { printf("could not open file"); return; }
。
另一部分很简单,它将fof分配给fgets的输出,然后将eof与null进行比较。
你还有其他大量问题。 char * eof;不为字符串分配空间。它只分配一个指针。你可能想要char *eof; eof = malloc(1024);
之类的东西你的行数也有这个问题。您需要为每一行分配内存。你不能只是将字符串复制到一个点 - 这些点首先需要指向一些内存。