【问题标题】:C: How to use strtok to output grades from input file & find average, minimum and maximum?C: 如何使用 strtok 从输入文件中输出成绩并找到平均值、最小值和最大值?
【发布时间】:2015-05-19 07:35:50
【问题描述】:

我正在尝试从输入文件中输出作业的成绩,以及输出每个作业的平均、最低和最高成绩。

例如,一个有 4 个学生和 3 个作业的班级的输入文件可能如下所示:

8.5, 10.5, 90.5
49.5, 99, 97
88, 88, 100
88.5, 99, 0

输出应该是

Student grades from the input file:
8.5, 10.5, 90.5
49.5, 99.0, 97.0
88.0, 88.0, 100.0
88.5, 99.0, 0.0

Assignment # 1 stats
avg = 58.6
min = 8.5
max = 88.5

Assignment # 2 stats
avg = 74.1
min = 10.5
max = 99.0

Assignment # 3 stats
avg = 71.9
min = 0.0
max = 100.0

到目前为止,我被困在必须输出文件内容的第一部分。这是我到目前为止所拥有的,对此或功能的任何帮助将不胜感激。

int main(int argc, char *argv[]) {
    FILE *input_file;
    int line_number = 0;
    char *next_field;
    char line[MAX_STUDENTS+1];

    input_file = fopen(argv[1], "r");

    //OUTPUT THE GRADES FROM THE INPUT FILE
    while (1) {
        fgets(line, MAX_STUDENTS, input_file);
        if (feof(input_file))
            break;

       next_field = strtok(line, " \n");


    while (next_field != NULL) {
            printf("==================================/n");
            printf("Student grades from the input file/n");
            printf("==================================/n");
            printf("%s,", next_field);

            next_field = strtok(NULL, " \n");
        }
    }

【问题讨论】:

  • char line[MAX_STUDENTS+1]; 应该重新考虑。使用strtod将字符串转换为双精度。

标签: c strtok text-parsing


【解决方案1】:

你可以像这样标记和输出:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>

#define MAX_LINE_LEN 1024

int main(int argc, char **argv) 
{
  int   line_number = 0;
  FILE *input_file;
  char  line[MAX_LINE_LEN + 1];
  char *next_field;
  char *end_field;

  if (1 == argc)
  {
    fprintf(stderr, "usage: %s <filename>\n", argv[0]);
    exit(1);
  }

  if (NULL == (input_file = fopen(argv[1], "r")))
  {
    perror(argv[1]);
    exit(1);
  }

  fprintf(stdout, "Student grades from the input file:\n");

  while (fgets(line, sizeof(line), input_file))
  {
    int first = 1;

    ++line_number;

    for (next_field = strtok(line, ",\n"); NULL != next_field; next_field = strtok(NULL, ",\n")) 
    {
      errno = 0;

      double grade = strtod(next_field, &end_field);

      if (errno || end_field == next_field || *end_field)
      {
        fprintf(stderr, "Warning: malformed input '%s'? Skipping!\n", next_field);
        continue;
      }

      fprintf(stdout, "%s%.1lf", (first ? "" : ", "), grade);
      first = 0;

      // TODO: store grade (or at least running min, max, avg) in a structure that stores assignments stats for later processing and printing
    }

    if (!first)
      fprintf(stdout, "\n");
  }

  return 0;
}

您需要以某种结构存储有关每个作业的统计信息,以便在阅读完所有输入后打印出作业统计信息。

请注意,我使用“,\n”而不是“\n”来调用strtok,因为我相信逗号确实是您输入中的重要分隔符。至少,对于 .csv 文件来说通常是这样,这是用于分隔待处理数据的常用格式。

请注意,我们的两种方法都会对不同类型的输入产生一些令人担忧的事情。例如,如果一行看起来像 "7.0,8.0,9.0,10.0\n"(这在 .csv 文件中很常见),您的标记化将无法正常工作。您的程序可能只处理 7.0 并忽略该行的其余部分。您的程序也可能不会反对像"7.0,HiThere 8.0, 9.0\n" 这样的输入。再说一次,您的程序可能会像处理"7.0, 8.0, 9.0, 10.0\n" 一样处理"7.0 8.0 9.0, 10.0\n",即使前一个字符串中缺少一些逗号。是好还是坏?答案取决于您的输入文件格式以及您希望对其结构的严格程度。对于前一个字符串,我的标记化方法将反对 7.0 在原始输入中不紧跟 ',''\n''\0',但在数字开始之前允许空格,这是空格的不对称处理有些奇怪。它还会愉快地处理"7.0,,,,10.0\n",甚至不会注意到行上的“缺失”字段。

因此,您需要弄清楚自己想要多挑剔,以及想要在程序中进行多好的错误处理。

【讨论】:

  • 次要:很多人认为“行长”不包括'\n',建议使用char line[MAX_LINE_LEN + 2];
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2016-12-29
  • 1970-01-01
  • 2013-04-01
  • 2018-03-18
相关资源
最近更新 更多