Разобрать строки целых чисел в C - PullRequest
2 голосов
/ 10 июня 2010

Это классическая проблема, но я не могу найти простое решение.

У меня есть входной файл, такой как:

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 ]

6 голосов
/ 10 июня 2010

У вас есть несколько открытых вариантов, но в целом я бы так на них напал:

Чтение во входном файле в виде текстового файла, то есть набора строк, с помощью функции fgets (). Это будет читаться до тех пор, пока не произойдет разрыв строки или EOF. Используйте функцию токенайзера строк, которая сканирует каждую прочитанную строку на наличие пробелов и возвращает подстроку перед пробелом. Теперь у вас есть строковое представление целого числа. Если хотите, разберите его на фактическое int или сохраните подстроку в вашем массиве. Если вы переключаете его на int, вам нужно остерегаться переполнения, если оно становится слишком большим.

1 голос
/ 10 июня 2010

Считайте входные данные как строку, выполните поиск новой строки, создайте новую строку с -1, где будет новая строка, и повторяйте это, пока все новые строки не будут заменены -1.Пока вы делаете это, вы также можете посчитать количество пробелов, чтобы вы знали, насколько велика объявлять ваш массив.(Вы, вероятно, должны сделать это после замены новых строк.)

Затем создайте свой массив.

Далее, используйте sscanf или что-то еще, чтобы интерпретировать целые числа из строки в цикле и добавить ихв массив в нужном месте, пока все целые числа (включая -1) не будут интерпретированы.

РЕДАКТИРОВАТЬ: ... И это, кажется, довольно близко к тому, что вы уже делаете, проходя мимокод, который вы добавили к своему вопросу, пока я печатал свой ответ.

0 голосов
/ 10 июня 2010

Вот полная программа на C, которая показывает, как вы можете это сделать. Он в основном читает в строках одновременно с fgets, затем использует sscanf для обработки каждого из встроенных в эту строку.

У него есть элементарная проверка ошибок, но он не был протестирован с неверными данными (строки не числовые), но это должно быть хорошим началом. Просто замените операторы 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]
0 голосов
/ 10 июня 2010

ОК. Я нашел решение, извините за шум, мне нужно поискать больше ...

чтение неизвестного числа целых чисел из стандартного ввода (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;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...