提问人:Crashzen 提问时间:10/22/2023 最后编辑:Crashzen 更新时间:10/22/2023 访问量:98
在 C 语言中对文件中包含数据的行进行计数
Counting data-containing lines from a file in C
问:
我是一名目前正在学习 C 的大学生,我需要创建一个函数来打开文件并计算包含数据的行数,然后返回值。我在尝试从文件中读取多行时遇到问题。
这就是我目前所拥有的。
注意:这些在另一个文件中定义
#define FNAME "sample_data.txt"
#define NAMELEN 30
#include <stdio.h>
#include <stdlib.h>
#include "utility.h"
int get_datafile_size(char file_name)
{
FILE* fp = fopen(FNAME, "r");
int datalines = 0;
while (!feof(fp))
{
char temp_str[NAMELEN];
fgets(temp_str, NAMELEN - 1, fp);
if (temp_str[0] != "#" && temp_str[0] != " ")
{
datalines++;
}
}
fclose(fp);
printf("<%d>", datalines);
return datalines;
}
目前,该函数仅输出第一行中的字符数。
供参考的是有问题的文件:
# These records are in the form EMPLOYEE_NAME:EMPLOYEE_ID:EMPLOYEE_SALARY
# The following are administrators::
Eric Braun:174328:240378.94
Sunil Ahuja:285832:190415.87
# The following are staff members:
Joe Smith:132754:25018.14
Sally Jones:158113:32019.55
Janice P Oliver:185639:11458.32
Robert North:317543:85321.11
Janice J Oliver:298734:47166.76
# The following are student workers:
Davy Crockett:345216:5372.18
Billy Bones:239954:1141.66
Amanda Nice:398751:514.32
Tiny T Tim:301865:1093.54
函数输出:
<27>
答:
代码中有很多问题!
int get_datafile_size(char file_name)
- 不适当的函数名称
- 未指示 C 字符串文件名char
char *
FILE* fp = fopen(FNAME, "r");
-什么?FNAME
while (!feof(fp))
- 不要使用...只是不要!feof()
char temp_str[NAMELEN];
NAMELEN = 30
- 最好使用令牌而不是幻数。限制缓冲区大小不好。
fgets(temp_str, NAMELEN - 1, fp);
- 假设是深思熟虑的。不用担心。 考虑到这一点,并保证将返回以 NUL 结尾的字符串。 只要向缓冲区提供正确的缓冲区大小,就不会溢出缓冲区。
- 缓冲区和令牌可以单独更改。最好使用,允许编译器使用缓冲区的最新大小。-1
'\0'
fgets()
fgets()
sizeof temp_str
if (temp_str[0] != "#" && temp_str[0] != " ")
- 将单个字符与包含一个字符和一个终止 NUL 字符的字符串混合在一起。使用撇号,而不是双引号。
printf("<%d>", datalines);
- 假设这是一个“打印调试语句。如果没有 ,则此输出可能不会在预期时通过缓冲区推送。
更好用:'\n'
fprintf( stderr, "datalines<%d>\n", datalines );
如果函数对文件中任何行的长度没有期望,那就更好了。这可以通过处理单个字符(来自流的缓冲输入)来处理,因此速度不会严重降低。
int cnt_datalines( char *file_name ) {
FILE *fp = fopen( file_name, "r" );
if( fp == NULL )
return -1; // let caller handle the error
int datalines = 0;
int ch;
for( int bgn = 1; ( ch = fgetc( fp ) ) != EOF; bgn = ch == '\n' )
// Add 1 only when 1st char after newline is not hash, SP or newline
datalines += ( bgn && ch != '\n' && ch != '#' && ch != ' ' );
fclose(fp);
fprintf( stderr, "datalines <%d>\n", datalines );
return datalines;
}
flag 变量在开始和遇到任何时候都为 true。True 表示下一个字符将是一行的开头。bgn
'\n'
评论
:-)
for()
for()
while()
由于代码正在寻找 a 后跟 a 以外的其他内容的出现,因此可以考虑直接对其进行编码。'\n'
'#'
int previous = '\n';
int ch;
while ((ch = fgetc(fp)) != EOF) {
datalines += previous == '\n' && !isspace(ch) && ch != '#';
previous = ch;
}
评论
char file_name
30
fgets()
30-1