文件处理加上 c 中的标记化

file handling plus tokenization in c

我想做的是从标准输入中获取以下格式的输入

输入:

22|Subject 1|45
23|Subject 2|52
22|Subject 2|51
26|Subject 1|72
23|Subject 2|61
26|Subject 1|81

这不过是 学生 ID|主题|标记 现在我想标记这些细节并将它们存储在结构变量中,以便我可以对它们进行计算。此代码无效。最后一行中的 printf 给出 5 0 作为输出,这是不正确的。请帮忙。

struct student
{
  int sid;
  char sub[35];
  int marks;
};


void main()
{
  struct student std[16];
  int i,ch,j;
  char temp[50];
  FILE *fp;
  clrscr();
  //fp=fopen("xyz.txt", "r");
  //fscanf(fp,"%s", temp);
  //printf("\n%s", temp);
  i=0;
  std[i].sid=0;
  while((ch = getchar()) != EOF && i < 6)
  {
    std[i].sid = 10 * std[i].sid + (int)(ch - '0');
    while((ch = getchar()) != '|')
    {
      std[i].sid = 10 * std[i].sid + (int)(ch - '0');
    }
    while((ch = getchar()) != '|')
    {
      std[i].sub[j++] = ch;
    }
    std[i].sub[j] = '[=11=]';
    std[i].marks = 0;
    while ((ch = getchar()) != '\n')
    {
      std[i].sid = 10 * std[i].marks + (int)(ch - '0');
    }
    i++;

    if (i < 6)
      std[i].sid = 0;
  }
  printf("%d %s %d",std[0].sid, &(std[1].sub[0]), std[2].marks);
  //fclose(fp);
  getch();
}

你应该使用库函数而不是像这样手动完成所有操作

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

struct student
{
  int sid;
  char sub[35];
  int marks;
};


int main(void)
{
  struct student std[16];
  size_t i;
  size_t count;
  char   line[100];

  i          = 0;
  std[i].sid = 0;
  count      = sizeof(std) / sizeof(std[0]);
  while (((fgets(line, sizeof(line), stdin)) != NULL) && (i < count))
  {
    char *token;
    char *endptr;

    token = strtok(line, "|");
    if (token == NULL)
      continue;        
    std[i].sid = strtol(token, &endptr, 10);
    if (*endptr != '[=10=]')
      continue;

    token = strtok(NULL, "|");
    if (token == NULL)
      continue;
    /* WARNING: no bound checking is being performed, DANGER ... */
    strcpy(std[i].sub, token);

    token = strtok(NULL, "|");
    if (token == NULL)
      continue;
    std[i].marks = strtol(token, &endptr, 10);
    if (*endptr != '[=10=]')
      continue;

    ++i;
  }
}

您的代码经过一些修复后运行良好。

  • 填充主题后将 j 重置为 0
  • 您在计算分数时使用了 std[i].sid 而不是 std[i].marks

最后打印出所有数据:

for (i = 0; i < 6; ++i)
    printf("%d %s %d\n", std[i].sid, &(std[i].sub[0]), std[i].marks);

完整代码(我为 clrscr() 添加了一个垫片,因为我没有 conio.h):

// parser.c - Parses student data into struct
// To compile:
//  gcc parser.c -o parser
// To run:
//  ./parser < data.txt

#include <stdio.h> // So compiler doesn't complain

// Shim for clrscr() if <conio.h> not available
void clrscr()
{
    printf("\e[2J\e[1;1H");
}

struct student
{
  int sid;
  char sub[35];
  int marks;
};


void main()
{
  struct student std[16];
  int i,ch,j;
  char temp[50];
  FILE *fp;
  clrscr();
  //fp=fopen("xyz.txt", "r");
  //fscanf(fp,"%s", temp);
  //printf("\n%s", temp);
  i=0;
  std[i].sid=0;
  while((ch = getchar()) != EOF && i < 6)
  {
    std[i].sid = 10 * std[i].sid + (int)(ch - '0');
    while((ch = getchar()) != '|')
    {
      std[i].sid = 10 * std[i].sid + (int)(ch - '0');
    }
    while((ch = getchar()) != '|')
    {
      std[i].sub[j++] = ch;
    }
    std[i].sub[j] = '[=11=]';
    std[i].marks = 0;
    j = 0; // Reset j to 0

    while ((ch = getchar()) != '\n')
    {
      std[i].marks = 10 * std[i].marks + (int)(ch - '0');
    }
    i++;

    if (i < 6)
      std[i].sid = 0;
  }
  for (i = 0; i < 6; ++i)
    printf("%d %s %d\n", std[i].sid, &(std[i].sub[0]), std[i].marks);
  //fclose(fp);
  //getch(); // Commented out as not needed/don't have <conio.h>
}

使用您的数据的输出:

22 Subject 1 45
23 Subject 2 52
22 Subject 2 51
26 Subject 1 72
23 Subject 2 61
26 Subject 1 81

它在 Linux 下编译良好,使用 gcc 并在代码清单顶部添加。