解析 C 中的整数行

发布于 2024-09-05 07:12:02 字数 1373 浏览 1 评论 0原文

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

我有一个输入文件,例如:

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

This is a classical problem, but I can not find a simple solution.

I have an input file like:

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 

Lines of different number of integers separated by a space.

I would like to parse them in an array, and separate each line with a marker, let say -1.

The difficulty is that I must handle integers and line returns.

Here my existing code, it loops upon the scanf loop (because scanf can not begin at a given position).

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

那小子欠揍 2024-09-12 07:12:02

您有许多选项可供选择,但这通常是我攻击它的方式:

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

You have a number of options open to you, but this is in general how I would attack it:

Read in the input file as a text file - that is as a bunch of strings - with fgets(). This will read until a line break or EOF is hit. Use a string tokenizer function that scans each line read for spaces and returns the substring before the space. You now have a string representation of an integer. Parse that into an actual int if you wish, or store the substring itself in your array. If you do switch it to an int, you need to beware of overflow if it gets too big.

樱娆 2024-09-12 07:12:02

将输入作为字符串读入,搜索换行符,在换行符所在的位置使用 -1 创建一个新字符串,然后重复此操作,直到所有换行符都替换为 -1。当您执行此操作时,您还可以计算空格数,以便您知道要声明数组的大小。 (不过,您应该在替换换行符后执行此操作。)

然后创建数组。

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

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

Read in the input as a string, do a search for a newline, create a new string with -1 where the newline would be, and repeat this until all newlines are replaced with -1. While you're doing this, you could also count the number of spaces so you'll know how large to declare your array. (You should probably do that after replacing the newlines, though.)

Then create your array.

Next, use sscanf or something to interpret the integers from the string in a loop and add them to the array in the right place until all the integers (including the -1s) have been interpreted.

EDIT: ...And that seems to be pretty close to what you're doing already, going by the code you added to your question while I was typing up my answer.

笑脸一如从前 2024-09-12 07:12:02

好的,我找到了解决方案,抱歉产生噪音,我应该搜索更多...

从 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;
  }

OK I found the solution, sorry for the noise, I should have search more...

reading unknown number of integers from stdin (C)

Instead of my scanf loop, use this one:

  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;
  }
红衣飘飘貌似仙 2024-09-12 07:12:02

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

它具有基本的错误检查功能,但尚未使用错误数据(非数字行)进行测试,但这应该是一个良好的开始。只需将 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]

Here's a complete C program that shows how you can do this. It basically reads in lines at a time with fgets, then uses sscanf to process each of the inetegrs on that line.

It has rudimentary error checking but it hasn't been tested with bad data (line non-numerics) but it should be a good start. Just replace the printf statements with code that will append each number to an array:

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

And here's the output to show you that it's working:

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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文