简体   繁体   English

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

[英]How to display the count of records in a file?

The scenario goes like this,剧情是这样的,

A medical center needs to store appointment details in a text file called appointment.dat.医疗中心需要将预约详细信息存储在名为约会.dat 的文本文件中。

It includes the Patient name and the Appointment type.它包括患者姓名约会类型。 The appointment types can either be 'Consulting' , 'Scanning' or 'Testing' .约会类型可以是“咨询”“扫描”“测试” Only the first letter is stored in the file.只有第一个字母存储在文件中。

The requirement is to,要求是,

  1. Create the appointment.dat file创建appointment.dat文件
  2. Get 5 patient details through keyboard input and write the data into the appointment.dat file under the given sample format.通过键盘输入获取5个患者详细信息,并将数据以给定的样本格式写入到appointment.dat文件中。
  Dave                C
  Ryan                T
  Mary                S
  George              C
  Julian              S
  1. Read the appointment.dat file and calculate and display the Number of Patients under the given format.阅读appointment.dat文件并计算并显示给定格式下的患者人数。
  Appointment Type       Number of patients
  Consulting                     2
  Scanning                       2
  Testing                        1

Here's the code I tried,这是我试过的代码,

#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;
}

I'm having trouble getting the displaying part right.我无法正确显示显示部分。 The Number of Patients displays some addresses instead of the patient count.患者人数显示一些地址而不是患者人数。

How do I modify the code to get the patient count right?如何修改代码以正确计算患者人数?

You have fallen into one of the first pitfalls most new C-programmers fall into.您已经陷入了大多数 C 程序员新手最容易陷入的陷阱之一。 Why is while (?feof (file) ) always wrong? 为什么 while (?feof (file) ) 总是错误的? On your call to fscan (cPtr, "%s", &chan);在您调用fscan (cPtr, "%s", &chan); (which should be fscanf ), for the last line of input, the read succeeds and EOF is not set. (应该是fscanf ),对于输入的最后一行,读取成功并且没有设置EOF You test while (!feof(cPtr)) -- and it's NOT.你测试while (!feof(cPtr)) - 它不是。 You loop again and reach fscan (cPtr, "%s", &chan);您再次循环并到达fscan (cPtr, "%s", &chan); which now fails due to an input-failure and EOF is returned -- but you blindly proceed to check if (chan) which may fail at this point or may appear to work correctly (adding an additional erroneous count to the variable corresponding to whatever the last value of chan was).现在由于输入失败而失败并返回EOF - 但是您盲目地继续检查if (chan)这可能在这一点上失败或可能看起来正常工作(向对应于任何内容的变量添加额外的错误计数chan的最后一个值是)。 1 1

You further invoke Undefined Behavior in your use of printf by failing to provide any argument for the "%d" conversion specifier contained in the format string , eg您在使用printf通过未能为格式字符串中包含的"%d"转换说明符提供任何参数来进一步调用未定义行为,例如

 printf ("Consulting                     %d        \n");

C11 Standard - 7.21.6.1 The fprintf function(p2) (this explains your "The Number of Patients displays some addresses instead of the patient count." ) C11 标准 - 7.21.6.1 fprintf 函数(p2) (这解释了您的“患者人数显示一些地址而不是患者人数。”

When you are reading a line-of-input at a time, use a line-oriented input function like fgets() or POSIX getline() to read a complete line into a sufficiently sized array, and then use sscanf() to separate the array into the needed values, eg当您一次读取输入行时,使用面向行的输入 function (如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 */

You use the return of the read function itself to control the continuation of the read-loop.您使用读取 function 本身的返回来控制读取循环的继续。 You cannot use any user-input function correctly without Checking the return .如果不检查return ,您将无法正确使用任何用户输入 function 。

Now you can check the type .现在您可以检查type A simple way is to use a switch() statement -- though there is nothing wrong with a sequence of if() statements.一种简单的方法是使用switch()语句——尽管if()语句序列没有任何问题。 You can use a switch() similar to:您可以使用类似于以下内容的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;
            }

Putting it altogether, and allowing the filename to be passed as the first argument to the program (or read from stdin by default if no filename is given), you could do:总而言之,并允许将文件名作为第一个参数传递给程序(如果没有给出文件名,则默认从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);
}

( note: you only need one printf statement for each contiguous output. The C compiler will concatenate all adjacent whitespace separated strings, eg "..." "..." into a single string) 注意:对于每个连续的 output,您只需要一个printf语句。C 编译器会将所有相邻的空格分隔字符串,例如"..." "..."

Example Use/Output示例使用/输出

Simply providing your input to the program on stdin using a bash heredoc , you would get:只需使用 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

Reading From A File从文件中读取

With your data in the file dat/appointment_types.txt , eg使用文件dat/appointment_types.txt中的数据,例如

$ cat dat/appointment_types.txt
Dave C
Ryan T
Mary S
George C
Julian S

Your use and output would be:您的使用和 output 将是:

$ ./bin/appointments dat/appointment_types.txt
Appointment Type       Number of patients
Consulting                     2
Scanning                       2
Testing                        1

Look things over and let me know if you have further questions.如果您还有其他问题,请仔细查看并告诉我。

Footnotes:脚注:

1. The C-Standard does not define what chan will hold after an input-failure occurs. 1. C-Standard 没有定义输入失败发生后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 标准 - 7.21.6.2 fscanf 函数(p9)行为只是未定义,因为此时chan是不确定的,并且在它具有不确定值时使用。 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)." 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)." and see discussion Undefined, unspecified and implementation-defined behavior and What is indeterminate behavior in C++?并查看讨论未定义、未指定和实现定义的行为以及C++ 中的不确定行为是什么? How is it different from undefined behavior?它与未定义的行为有何不同?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM