在C中解析整数行

时间:2010-06-10 15:03:03

标签: c parsing filehandle

这是一个经典问题,但我找不到简单的解决方案。

我有一个输入文件,如:

1 3 9 13 23 25 34 36 38 40 52 54 59 
2 3 9 14 23 26 34 36 39 40 52 55 59 63 67 76 85 86 90 93 99 108 114 
2 4 9 15 23 27 34 36 63 67 76 85 86 90 93 99 108 115 
1 25 34 36 38 41 52 54 59 63 67 76 85 86 90 93 98 107 113 
2 3 9 16 24 28 
2 3 10 14 23 26 34 36 39 41 52 55 59 63 67 76 

由空格分隔的不同整数的行。

我想在数组中解析它们,并用标记分隔每一行,比如-1

困难在于我必须处理整数和换行。

这是我现有的代码,它在scanf循环上循环(因为scanf不能在给定位置开始)。

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {

  if (argc != 4) {
    fprintf(stderr, "Usage: %s <data file> <nb transactions> <nb items>\n", argv[0]);
    return 1;
  }
  FILE * file;
  file = fopen (argv[1],"r");
  if (file==NULL) {
    fprintf(stderr, "Error: can not open %s\n", argv[1]);
    fclose(file);
    return 1;
  }
  int nb_trans = atoi(argv[2]);
  int nb_items = atoi(argv[3]);
  int *bdd = malloc(sizeof(int) * (nb_trans + nb_items));
  char line[1024];
  int i = 0;

  while ( fgets(line, 1024, file) ) {
    int item;
    while ( sscanf (line, "%d ", &item )){
      printf("%s %d %d\n", line, i, item);
      bdd[i++] = item;
    }
    bdd[i++] = -1;
  }

  for ( i = 0; i < nb_trans + nb_items; i++ ) {
    printf("%d ", bdd[i]);
  }
  printf("\n");
}

4 个答案:

答案 0 :(得分:6)

你有很多选择,但一般来说我会如何攻击它:

使用fgets()将输入文件作为文本文件(即一串字符串)读入。这将读取直到线路中断或EOF被击中。使用字符串标记生成器函数扫描每行读取空格并返回空格前的子字符串。您现在有一个整数的字符串表示形式。如果您愿意,可以将其解析为实际的int,或者将子串本身存储在数组中。如果你把它切换到一个int,你需要注意溢出它是否太大。

答案 1 :(得分:1)

将输入作为字符串读入,搜索换行符,创建一个新的字符串,其中换行符为-1,并重复此操作,直到所有换行符都替换为-1。当你这样做时,你也可以计算空格的数量,这样你就可以知道声明你的数组有多大。 (不过,你应该在更换新行之后这样做。)

然后创建你的数组。

接下来,使用sscanf或其他东西来解释循环中字符串的整数,并将它们添加到正确位置的数组中,直到所有整数(包括-1s)都被解释为止。

编辑:......这似乎与你正在做的事情非常接近,在我输入你的答案时,你在问题中添加了代码。

答案 2 :(得分:0)

好的我找到了解决方案,对不起噪音,我应该多搜索一下......

reading unknown number of integers from stdin (C)

使用这个:而不是我的scanf循环:

  while ( fgets(line, 1024, file) ) {
    int item;
    for (p = line; ; p = e) {
        item = strtol(p, &e, 10);
        if (p == e)
            break;
        bdd[i++] = item;
    }
    bdd[i++] = -1;
  }

答案 3 :(得分:0)

这是一个完整的C程序,展示了如何做到这一点。它基本上一次用fgets读取行,然后使用sscanf来处理该行上的每个inetegrs。

它有基本的错误检查,但它没有使用不良数据(行非数字)进行测试,但它应该是一个良好的开端。只需将printf语句替换为将每个数字附加到数组的代码:

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

int main (void) {
    char line[1000];
    FILE *fIn;
    char *str;
    int val, num;

    // Open input file and process line by line.

    if ((fIn = fopen ("infile.txt", "r")) == NULL) {
        fprintf (stderr, "Cannot open infile.txt, errno = %d\n", errno);
        return 1;
    }

    while (fgets (line, sizeof (line), fIn) != NULL) {
        // Check if line was too long.

        if (line[strlen (line) - 1] != '\n') {
            fprintf (stderr, "Line too long: [%s...]\n", line);
            fclose (fIn);
            return 1;
        }

        // Oyput the line and start processing it.

        printf ("%s   ", line);
        str = line;

        // Skip white space and scan first inetegr.

        while (*str == ' ') str++;

        num = sscanf (str, "%d", &val);

        // Process the integer if it was there.

        while ((num != 0) && (num != EOF)) {
            // Print it out then skip to next.

            printf ("[%d] ", val);
            while ((*str != ' ') && (*str != '\0')) str++;
            while (*str == ' ') str++;
            num = sscanf (str, "%d", &val);
        }

        // -1 for line separator.

        printf ("[%d]\n", -1);
    }

    // Close input file and exit.

    fclose (fIn);

    return 0;
}

以下输出显示它正在运行:

1 3 9 13 23 25 34 36 38 40 52 54 59
   [1] [3] [9] [13] [23] [25] [34] [36] [38] [40] [52] [54] [59] [-1]
2 3 9 14 23 26 34 36 39 40 52 55 59 63 67 76 85 86 90 93 99 108 114
   [2] [3] [9] [14] [23] [26] [34] [36] [39] [40] [52] [55] [59] [63] [67] [76] [85] [86] [90] [93] [99] [108] [114] [-1]
2 4 9 15 23 27 34 36 63 67 76 85 86 90 93 99 108 115
   [2] [4] [9] [15] [23] [27] [34] [36] [63] [67] [76] [85] [86] [90] [93] [99] [108] [115] [-1]
1 25 34 36 38 41 52 54 59 63 67 76 85 86 90 93 98 107 113
   [1] [25] [34] [36] [38] [41] [52] [54] [59] [63] [67] [76] [85] [86] [90] [93] [98] [107] [113] [-1]
2 3 9 16 24 28
   [2] [3] [9] [16] [24] [28] [-1]
2 3 10 14 23 26 34 36 39 41 52 55 59 63 67 76
   [2] [3] [10] [14] [23] [26] [34] [36] [39] [41] [52] [55] [59] [63] [67] [76] [-1]