2

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

我有一个输入文件,如:

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

4 回答 4

6

你有很多选择,但一般来说,这是我攻击它的方式:

使用 fgets() 将输入文件作为文本文件读入 - 即作为一堆字符串。这将一直读取,直到遇到换行符或 EOF。使用字符串标记器函数扫描读取的每一行以查找空格并返回空格之前的子字符串。您现在有一个整数的字符串表示形式。如果您愿意,可以将其解析为实际的 int,或者将子字符串本身存储在数组中。如果确实将其切换为 int,则需要提防溢出,如果它变得太大。

于 2010-06-10T15:14:31.440 回答
1

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

然后创建你的数组。

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

编辑:...这似乎与您已经在做的非常接近,通过您在我输入答案时添加到您的问题中的代码。

于 2010-06-10T15:14:17.233 回答
0

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

从标准输入(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;
  }
于 2010-06-10T15:16:42.710 回答
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]
于 2010-06-10T15:46:39.243 回答