为了正确解析输入,我需要能够计算文件中的行数。但是,我不想计算只是换行符的行。为此,我创建了以下函数:
int countLinesInFile(char *filename) {
int newlines = 0;
if (access(filename,F_OK) != -1)
error("File not found",0);
FILE *input = fopen(filename,"r");
int size = 256 * 4;
char buffer[size];
while ((fgets(buffer,sizeof(buffer),input)) != EOF) {
printf("Read a string");
if (buffer == "\n")
continue;
newlines++;
}
fclose(input);
return newlines;
}
在文件的顶部,我有以下内容:
#include <stdio.h>
#include <unistd.h>
当我运行程序并尝试计算行数时,它会出现分段错误。使用valgrind,我可以看到以下内容:
==6632== Invalid read of size 4
==6632== at 0x4EA8E6B: fgets (in /usr/lib64/libc-2.24.so)
==6632== by 0x402219: countLinesInFile (in [executable])
[other information about program, does not seem relevant]
==6632== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6632==
==6632==
==6632== Process terminating with default action of signal 11 (SIGSEGV)
==6632== Access not within mapped region at address 0x0
==6632== at 0x4EA8E6B: fgets (in /usr/lib64/libc-2.24.so)
==6632== by 0x402219: countLinesInFile (in [executable])
[other information about program, does not seem relevant]
==6632== If you believe this happened as a result of a stack
==6632== overflow in your program's main thread (unlikely but
==6632== possible), you can try to increase the size of the
==6632== main thread stack using the --main-stacksize= flag.
==6632== The main thread stack size used in this run was 8388608.
==6632==
==6632== HEAP SUMMARY:
==6632== in use at exit: 475 bytes in 16 blocks
==6632== total heap usage: 19 allocs, 3 frees, 3,075 bytes allocated
==6632==
==6632== LEAK SUMMARY:
==6632== definitely lost: 0 bytes in 0 blocks
==6632== indirectly lost: 0 bytes in 0 blocks
==6632== possibly lost: 0 bytes in 0 blocks
==6632== still reachable: 475 bytes in 16 blocks
==6632== suppressed: 0 bytes in 0 blocks
==6632== Rerun with --leak-check=full to see details of leaked memory
==6632==
==6632== For counts of detected and suppressed errors, rerun with: -v
==6632== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
我试图在while循环的开头添加一行“printf(”读取文件“)”。这段代码没有执行,我相信fgets就是问题所在。不幸的是,我不知道这个问题是什么。
我已经确认我正在尝试阅读的文件中包含正确的文字,并且不是空的。
我创建的函数是否正确执行此任务的方法?如果是这样,我可以遇到什么问题?我将来如何避免这个问题?
更新:这对我来说真的是一个愚蠢的错误。我正在使用Valgrind运行该程序,看起来它不使用可执行文件的目录,这意味着它无法找到该文件。谢谢你的帮助。
答案 0 :(得分:1)
两件事:首先,只要不再能读取行,fgets
就会返回NULL
,而不是EOF
。因此,条件应为while(fgets(...) != NULL)
或短while(fgets(...))
。
其次,buffer == "\n"
比较两个指向字符的指针,即比较两个存储器地址。并且任何内容都不可能与字符串文字"\n"
具有相同的内存地址。因此,比较字符,即buffer[0]=='\n'
或buffer[0]!='\n'
。
我认为您可以轻松摆脱continue
- 语句,以便代码如下所示:
while (fgets(buffer,sizeof(buffer),input)) {
if (buffer[0] != '\n') {
newlines++;
}
}
答案 1 :(得分:0)
我认为您需要跟踪上一个\n
的文件偏移量,如果此\n
== last + 1的位置,则不会增加。
答案 2 :(得分:0)
函数fgets
返回指针值,失败时返回NULL。 EOF(通常,除非你已经改变它)定义为-1。他们永远不会比较平等,这意味着你应该在你应该停止之后很久就召唤fgets。
答案 3 :(得分:0)
fgets()
将您限制为预定义的行长度。要解决这个问题,您可以使用POSIX-standard getline()
。
在计算行数时,要跳过空行,您只需打折与"\n"
匹配的任何内容:
#include <stdio.h>
...
long countLines( const char *filename )
{
FILE *fp = fopen( filename, "r" );
if ( fp == NULL )
{
return( -1L );
}
char *line = NULL;
size_t bytes = 0UL;
long lineCount = 0L;
for ( ;; )
{
ssize_t result = getline( &line, &bytes, fp );
if ( -1 == result )
{
break;
}
if ( strcmp( line, "\n" ) )
{
lineCount++;
}
}
free( line );
fclose( fp );
return( lineCount );
}
答案 4 :(得分:-2)
FILE *input = fopen(filename,"r");
应该是
FILE *input;
input = fopen(filename,"r");
我不相信fgets()
会返回换行符或EOF。它会在换行符之前停止读取字符,下一个读取将是换行符或连续换行符之后的字符。
您可能需要使用二进制文件读取功能,该功能将立即读取整个文件,然后解析出这些行。这也将处理最后没有EOF的文本文件的情况。许多人没有