简体   繁体   English

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

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

I have an input file:我有一个输入文件:

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

I am reading this with:我正在阅读:

 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);

Which works fine.哪个工作正常。

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

But when I read something like this(input shortened as the file is big):但是当我读到这样的东西时(输入缩短,因为文件很大):

  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)

I get this, for example:我明白了,例如:

  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)

How can I fix this error to put the right output - so I get the proper value of a node instead of getting 9 instead of 93 for example.如何修复此错误以放置正确的输出 - 例如,我获得节点的正确值而不是 9 而不是 93。 Edit: Its not working, I get something like this:编辑:它不工作,我得到这样的东西:

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)

which isnt even an input.这甚至不是输入。

Replace int check = (sscanf (gets, " %c(%d,%d", &node, &width, &height)); and char node; with bit more complex lines:用更复杂的行替换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;
}

In this iteration of your question, what is changed is instead of having only a single-character before the first "(" or on a line by itself, you can now have multiple characters. You still want to be able to read either 'H' or 93 as the first part of the line, so you need to adjust your format-string to read multiple character before the first "(" and then either treat that as a string if it is an alpha-character, or convert it to an integer values if it is composed of digits. You can use something like:在你的问题的这个迭代中,改变的是在第一个"("或单独一行之前只有一个字符,你现在可以有多个字符。你仍然希望能够读取'H'93作为该行的第一部分,因此您需要调整格式字符串以在第一个"("之前读取多个字符,然后如果它是字母字符,则将其视为字符串,或者将其转换为如果它由数字组成,则为整数值。您可以使用以下内容:

#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)) {
           ...

The format string being " %31[^(\\n](%d,%d" where the '\\n' is included in the negated character class along with '(' to trim the '\\n' from those lines that just contain a single character. The circumflex (eg '^' ) at the beginning of the [^..] telling you to read character not including what is contained within the character class. (eg stop reading when the first negated character is encountered)格式字符串为" %31[^(\\n](%d,%d" ,其中'\\n''('一起包含在否定字符类中,以从那些行中修剪掉'\\n'包含单个字符。 [^..]开头的抑扬符(例如'^' )告诉您阅读字符,不包括字符类中包含的内容。(例如,遇到第一个否定字符时停止阅读)

A full example would be:一个完整的例子是:

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

You can change the switch() statement to your if/else statements.您可以将switch()语句更改为if/else语句。

Example Use/Output示例使用/输出

With your updated input, you would now get:使用更新后的输入,您现在将获得:

$ ./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

Where you can push all value to your stack where needed.您可以在需要的地方将所有价值推送到您的堆栈中。 Let me know if you have further questions.如果您还有其他问题,请告诉我。

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

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