如何显示文件中的记录数?
How to display the count of records in a file?
剧情是这样的,
医疗中心需要将预约详细信息存储在名为 appointment.dat.
的文本文件中
它包括患者姓名和预约类型。预约类型可以是'Consulting'、'Scanning' 或 'Testing'。只有第一个字母存储在文件中。
要求是,
- 创建
appointment.dat
文件
- 通过键盘输入获取5个患者的详细信息,并以给定的样本格式将数据写入
appointment.dat
文件。
Dave C
Ryan T
Mary S
George C
Julian S
- 读取
appointment.dat
文件并计算并显示给定格式下的患者人数。
Appointment Type Number of patients
Consulting 2
Scanning 2
Testing 1
这是我试过的代码,
#include <stdio.h>
int main()
{
int cCount, sCount, tCount;
char name, chan, C, S, T, c, s, t;
chan = " ";
cCount = sCount = tCount = 0;
FILE *cPtr;
cPtr = fopen ("appointment.dat", "r");
while (!feof(cPtr))
{
fscan (cPtr, "%s", &chan);
if (chan == C)
cCount++;
else if (chan == S)
sCount++;
else if (chan == T)
tCount++;
}
printf ("Appointment Type Number of patients\n");
printf ("Consulting %d \n");
printf ("Scanning %d \n");
printf ("Testing %d \n");
return 0;
}
我无法正确显示显示部分。患者人数显示一些地址而不是患者人数。
如何修改代码以使患者计数正确?
您已经掉进了大多数新 C 程序员掉入的第一个陷阱中。 Why is while ( !feof (file) ) always wrong? 在您调用 fscan (cPtr, "%s", &chan);
(应该是 fscanf
)时,对于输入的最后一行,读取成功并且未设置 EOF
。您测试了 while (!feof(cPtr))
—— 但事实并非如此。你再次循环并到达 fscan (cPtr, "%s", &chan);
现在由于 输入失败 而失败并且 EOF
被 returned - 但你盲目地继续检查if (chan)
此时可能会失败,或者看起来可以正常工作(向对应于 chan
的最后一个值的变量添加额外的错误计数)。 1
您在使用 printf
时未为 "%d"
转换说明符 提供任何参数,从而进一步调用了 未定义行为 =97=] 包含在 格式字符串 中,例如
printf ("Consulting %d \n");
C11 Standard - 7.21.6.1 The fprintf function(p2)(这解释了你的 "The Number of Patients displays some addresses instead of the patient count.")
当您一次读取一行输入时,使用面向行的输入函数,如fgets()
或POSIXgetline()
将完整的一行读入一个足够大的数组,然后使用 sscanf()
将数组分隔为所需的值,例如
#define MAXC 128 /* if you need a constant, #define one (or more) */
...
char buf[MAXC], name[MAXC], type;
...
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
if (sscanf (buf, "%s %c", name, &type) == 2) { /* split buf into name, type */
您使用读取函数本身的return来控制读取循环的继续。如果不检查 return
.
,您将无法正确使用任何用户输入功能
现在您可以查看 type
。一种简单的方法是使用 switch()
语句——尽管一系列 if()
语句没有任何问题。您可以使用类似于 switch()
的
switch (type) { /* switch on type */
case 'C': C++; break;
case 'S': S++; break;
case 'T': T++; break;
default:
fprintf (stderr, "error: invalid type '%c'\n", type);
break;
}
把它放在一起,并允许将文件名作为第一个参数传递给程序(如果没有给出文件名,则默认从 stdin
读取),你可以这样做:
#include <stdio.h>
#define MAXC 128 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char buf[MAXC], name[MAXC], type;
size_t C = 0, S = 0, T = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
if (sscanf (buf, "%s %c", name, &type) == 2) { /* split buf into name, type */
switch (type) { /* switch on type */
case 'C': C++; break;
case 'S': S++; break;
case 'T': T++; break;
default:
fprintf (stderr, "error: invalid type '%c'\n", type);
break;
}
}
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
printf ("Appointment Type Number of patients\n" /* output results */
"Consulting %9zu\n"
"Scanning %9zu\n"
"Testing %9zu\n", C, S, T);
}
(注意:每个连续输出只需要一个 printf
语句。C 编译器将连接所有相邻的空格分隔的字符串,例如 "..."
"..."
成一个字符串)
例子Use/Output
只需使用 bash heredoc 向 stdin
上的程序提供输入,您将得到:
$ cat << eof | ./bin/appointments
> Dave C
> Ryan T
> Mary S
> George C
> Julian S
> eof
Appointment Type Number of patients
Consulting 2
Scanning 2
Testing 1
正在读取文件
将您的数据放在文件 dat/appointment_types.txt
中,例如
$ cat dat/appointment_types.txt
Dave C
Ryan T
Mary S
George C
Julian S
您的使用和输出将是:
$ ./bin/appointments dat/appointment_types.txt
Appointment Type Number of patients
Consulting 2
Scanning 2
Testing 1
检查一下,如果您还有其他问题,请告诉我。
脚注:
1. C 标准没有定义在 输入失败 发生后 chan
将保持什么。 C11 Standard - 7.21.6.2 The fscanf function(p9) The behavior is simply undefined because chan
is indeterminate at this point and used while it has an indeterminate value. C11 Standard - J.2 Undefined Behavior "The value of an object with automatic storage duration is used while it is indeterminate (6.2.4, 6.7.9, 6.8)."
and see discussion Undefined, unspecified and implementation-defined behavior and What is indeterminate behavior in C++ ? How is it different from undefined behavior?
剧情是这样的,
医疗中心需要将预约详细信息存储在名为 appointment.dat.
的文本文件中它包括患者姓名和预约类型。预约类型可以是'Consulting'、'Scanning' 或 'Testing'。只有第一个字母存储在文件中。
要求是,
- 创建
appointment.dat
文件 - 通过键盘输入获取5个患者的详细信息,并以给定的样本格式将数据写入
appointment.dat
文件。
Dave C
Ryan T
Mary S
George C
Julian S
- 读取
appointment.dat
文件并计算并显示给定格式下的患者人数。
Appointment Type Number of patients
Consulting 2
Scanning 2
Testing 1
这是我试过的代码,
#include <stdio.h>
int main()
{
int cCount, sCount, tCount;
char name, chan, C, S, T, c, s, t;
chan = " ";
cCount = sCount = tCount = 0;
FILE *cPtr;
cPtr = fopen ("appointment.dat", "r");
while (!feof(cPtr))
{
fscan (cPtr, "%s", &chan);
if (chan == C)
cCount++;
else if (chan == S)
sCount++;
else if (chan == T)
tCount++;
}
printf ("Appointment Type Number of patients\n");
printf ("Consulting %d \n");
printf ("Scanning %d \n");
printf ("Testing %d \n");
return 0;
}
我无法正确显示显示部分。患者人数显示一些地址而不是患者人数。
如何修改代码以使患者计数正确?
您已经掉进了大多数新 C 程序员掉入的第一个陷阱中。 Why is while ( !feof (file) ) always wrong? 在您调用 fscan (cPtr, "%s", &chan);
(应该是 fscanf
)时,对于输入的最后一行,读取成功并且未设置 EOF
。您测试了 while (!feof(cPtr))
—— 但事实并非如此。你再次循环并到达 fscan (cPtr, "%s", &chan);
现在由于 输入失败 而失败并且 EOF
被 returned - 但你盲目地继续检查if (chan)
此时可能会失败,或者看起来可以正常工作(向对应于 chan
的最后一个值的变量添加额外的错误计数)。 1
您在使用 printf
时未为 "%d"
转换说明符 提供任何参数,从而进一步调用了 未定义行为 =97=] 包含在 格式字符串 中,例如
printf ("Consulting %d \n");
C11 Standard - 7.21.6.1 The fprintf function(p2)(这解释了你的 "The Number of Patients displays some addresses instead of the patient count.")
当您一次读取一行输入时,使用面向行的输入函数,如fgets()
或POSIXgetline()
将完整的一行读入一个足够大的数组,然后使用 sscanf()
将数组分隔为所需的值,例如
#define MAXC 128 /* if you need a constant, #define one (or more) */
...
char buf[MAXC], name[MAXC], type;
...
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
if (sscanf (buf, "%s %c", name, &type) == 2) { /* split buf into name, type */
您使用读取函数本身的return来控制读取循环的继续。如果不检查 return
.
现在您可以查看 type
。一种简单的方法是使用 switch()
语句——尽管一系列 if()
语句没有任何问题。您可以使用类似于 switch()
的
switch (type) { /* switch on type */
case 'C': C++; break;
case 'S': S++; break;
case 'T': T++; break;
default:
fprintf (stderr, "error: invalid type '%c'\n", type);
break;
}
把它放在一起,并允许将文件名作为第一个参数传递给程序(如果没有给出文件名,则默认从 stdin
读取),你可以这样做:
#include <stdio.h>
#define MAXC 128 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char buf[MAXC], name[MAXC], type;
size_t C = 0, S = 0, T = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
if (sscanf (buf, "%s %c", name, &type) == 2) { /* split buf into name, type */
switch (type) { /* switch on type */
case 'C': C++; break;
case 'S': S++; break;
case 'T': T++; break;
default:
fprintf (stderr, "error: invalid type '%c'\n", type);
break;
}
}
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
printf ("Appointment Type Number of patients\n" /* output results */
"Consulting %9zu\n"
"Scanning %9zu\n"
"Testing %9zu\n", C, S, T);
}
(注意:每个连续输出只需要一个 printf
语句。C 编译器将连接所有相邻的空格分隔的字符串,例如 "..."
"..."
成一个字符串)
例子Use/Output
只需使用 bash heredoc 向 stdin
上的程序提供输入,您将得到:
$ cat << eof | ./bin/appointments
> Dave C
> Ryan T
> Mary S
> George C
> Julian S
> eof
Appointment Type Number of patients
Consulting 2
Scanning 2
Testing 1
正在读取文件
将您的数据放在文件 dat/appointment_types.txt
中,例如
$ cat dat/appointment_types.txt
Dave C
Ryan T
Mary S
George C
Julian S
您的使用和输出将是:
$ ./bin/appointments dat/appointment_types.txt
Appointment Type Number of patients
Consulting 2
Scanning 2
Testing 1
检查一下,如果您还有其他问题,请告诉我。
脚注:
1. C 标准没有定义在 输入失败 发生后 chan
将保持什么。 C11 Standard - 7.21.6.2 The fscanf function(p9) The behavior is simply undefined because chan
is indeterminate at this point and used while it has an indeterminate value. C11 Standard - J.2 Undefined Behavior "The value of an object with automatic storage duration is used while it is indeterminate (6.2.4, 6.7.9, 6.8)."
and see discussion Undefined, unspecified and implementation-defined behavior and What is indeterminate behavior in C++ ? How is it different from undefined behavior?