如何从文件中读取特定的字符和整数(更新问题)?

How to read specific chars and ints from file (update question)?

我有一个输入文件:

H
3(3,3)
V
1(5,4)
2(7,7)

我正在阅读这篇文章:

 12 FILE *fp = fopen (argv[1], "r");
 13   if (fp == NULL)
 14   {
 15     return EXIT_FAILURE;
 16   }
 17   Stack* top = NULL;
 18   char gets[1024];
 19   while (fgets (gets, 1024, fp))
 20   {
 21     char node;
 22     int width = 0;
 23     int height = 0;
 24     int check = (sscanf (gets, " %c(%d,%d", &node, &width, &height));
 25     if (check == 1)
 26     {
 27       push(&top,node,0,0);
 28     }
 29     else if (check == 3)
 30     {
 31        push(&top,node,width,height);
 32     }
 33   }
 34   fclose (fp);

效果很好。

  1 3(3,3)
  2 1(5,4)
  3 2(7,7)
  4 V
  5 H

但是当我读到类似这样的内容时(由于文件很大,输入被缩短了):

  1 93(11,16)
  2 11(12,33)
  3 H
  4 34(7,11)
  5 10(9,27)
  6 V
  7 32(12,30)
  8 30(12,16)
  9 41(12,19)
 10 H
 11 V
 12 50(12,13)

我明白了,例如:

  1 9(0,0)
  2 1(0,0)
  3 H
  4 3(0,0)
  5 1(0,0)
  6 V
  7 3(0,0)
  8 3(0,0)
  9 4(0,0)
 10 H
 11 V
 12 5(0,0)

如何修复此错误以提供正确的输出 - 因此我获得了节点的正确值而不是 9 而不是例如 93。 编辑: 它不工作,我得到这样的东西:

20 45(11,16)
 21 45(11,16)
 22 45(11,16)
 23 45(11,16)
 24 45(11,16)
 25 45(11,16)
 26 45(11,16)
 27 45(11,16)
 28 45(11,16)
 29 45(11,16)
 30 45(11,16)
 31 45(11,16)
 32 45(11,16)
 33 45(11,16)
 34 45(11,16)
 35 45(11,16)
 36 45(11,16)
 37 45(11,16)
 38 45(11,16)
 39 45(11,16)
 40 45(11,16)
 41 45(11,16)
 42 45(11,16)
 43 45(11,16)
 44 45(11,16)
 45 45(11,16)
 46 45(11,16)
 47 45(11,16)

这甚至不是输入。

int check = (sscanf (gets, " %c(%d,%d", &node, &width, &height));char node; 替换为更复杂的行:

int node = 0;
int check = (sscanf (gets, "%d(%d,%d", &node, &width, &height));
if (check == 0)
{
  char n = 0;
  check = sscanf(gets, " %c", &n);
  node = n;
}

在你的问题的这次迭代中,改变的是在第一个 "(" 之前只有一个字符或单独一行,你现在可以有多个字符。您仍然希望能够读取 'H'93 作为该行的第一部分,因此您需要调整 format-string 以读取多个第一个 "(" 之前的字符,如果它是字母字符,则将其视为字符串,如果它由数字组成,则将其转换为整数值。您可以使用类似的东西:

#define MAXN   32
...
    while (fgets (buf, MAXC, fp)) {
        char tmp[MAXN];
        int node, width, height;
        switch (sscanf (buf, " %31[^(\n](%d,%d", tmp, &width, &height)) {
           ...

格式字符串是 " %31[^(\n](%d,%d" 其中 '\n' 包含在 否定 字符 class 中连同 '(' 到trim 那些只包含单个字符的行中的 '\n'[^..] 开头的 circumflex(例如 '^')告诉您阅读不包括字符 class 中包含的内容的字符。 (例如,遇到第一个否定字符时停止阅读)

一个完整的例子是:

#include <stdio.h>

#define MAXC 1024   /* if you need a constant, #define one (or more) */
#define MAXN   32

int main (int argc, char **argv) {

    char buf[MAXC];
    /* 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)) {
        char tmp[MAXN];
        int node, width, height;
        switch (sscanf (buf, " %31[^(\n](%d,%d", tmp, &width, &height)) {
            case 1 : printf ("single char/digit: '%s'\n", tmp);
                    break;
            case 3 : if (sscanf (tmp, "%d", &node) == 1)
                        printf ("all values: %d  %d  %d\n", node, width, height);
                    else
                        fputs ("error: parsing node from tmp.\n", stderr);
                    break;
            default : fputs ("invalid line format\n", stderr);
        }
    }
    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);
}

您可以将 switch() 语句更改为您的 if/else 语句。

例子Use/Output

根据您更新后的输入,您现在将获得:

$ ./bin/fgets_sscanf_multival2 dat/multivals2.txt
all values: 93  11  16
all values: 11  12  33
single char/digit: 'H'
all values: 34  7  11
all values: 10  9  27
single char/digit: 'V'
all values: 32  12  30
all values: 30  12  16
all values: 41  12  19
single char/digit: 'H'
single char/digit: 'V'
all values: 50  12  13

您可以在其中将所有价值推送到需要的堆栈中。如果您还有其他问题,请告诉我。