如何显示文件中的记录数?

问题描述 投票:-1回答:1

场景是这样的。

一个医疗中心需要将预约的详细信息存储在一个叫做 任命.数据。

它包括 患者姓名任用类型。 任用类型可以是 "咨询, "扫描'测试'. 文件中只存储第一个字母。

要求是:

  1. 创建 appointment.dat 档案
  2. 通过键盘输入获得5个病人的详细信息,并将数据写入到数据库中。appointment.dat 在给定的示例格式下的文件。
  Dave                C
  Ryan                T
  Mary                S
  George              C
  Julian              S
  1. 阅读 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 file-read record-count
1个回答
0
投票

你已经掉进了大多数新C程序员最先掉进的陷阱之一。为什么while ( !feof (file) ) 总是错误的? 在你调用 fscan (cPtr, "%s", &chan); (应该是 fscanf),对于最后一行输入,读取成功,并且 EOF 没有设置。您测试 while (!feof(cPtr)) -- 而它不是。你再次循环,并达到 fscan (cPtr, "%s", &chan); 现在失败的原因是 输入失败EOF 但你却盲目地继续检查 if (chan) 这时可能会失败,也可能看起来是正确的(在变量中增加一个错误的计数,对应于无论最后的 chan 是)。) 1

你进一步援引 未定义的行为 在你使用 printf 没有提供任何论据来证明这一点。"%d" 转换说明者 所载 格式化字符串例如

 printf ("Consulting                     %d        \n");

C11标准--7.21.6.1 fprintf函数(p2) (这解释了你的 "患者人数显示一些地址,而不是患者人数。")

当你每次读取一行输入时,使用一个 线性 输入函数,如 fgets() 或POSIX getline() 将完整的行读入一个足够大的数组,然后用 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.

现在你可以检查 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编译器将把所有相邻的以空格分隔的字符串串联起来,例如 "..." "..." 变成一个单一的字符串)

例子 UseOutput

仅仅是为程序提供您的意见 stdin 使用bash 遗传性,你会得到。

$ 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-Standard没有定义什么是 chan 将在一个 输入失败 发生。C11标准--7.21.6.2函数fscanf(p9) 该行为根本没有定义,因为 chan 此时是不确定的,在它有一个不确定的值时使用。C11标准--J.2未定义行为。 "The value of an object with automatic storage duration is used while it is indeterminate (6.2.4, 6.7.9, 6.8)." 且看下回分解 未定义、未说明和执行定义的行为。什么是C++中的不确定行为?它与未定义行为有什么不同?

© www.soinside.com 2019 - 2024. All rights reserved.