Сканирование нескольких строк, пока не достигнет определенного символа - PullRequest
0 голосов
/ 18 октября 2019

У меня есть следующие данные:

Someting sth
example
 5  15   
3

Я хочу scanf вводить по строкам, чтобы получить все содержимое строки. Но при достижении первой цифры (перед ней могут быть пробелы / символы табуляции) я хочу отсканировать ее как int.

Это то, что я придумала, но она не работает должным образом - курсор по-прежнему не останавливается насимвол цифры.

char person_name[1000];
int n;

while (scanf("%[^\n/D]%*c", person_name) > 0) {
    if (checkIfContainsNumber(person_name) == 0) {
      appendToLinkedList(&head_ref, person_name);
    } else {
      break;
    }
}

while (scanf("%d", &n) > 0) {
    printf("%d ", n);
}

Ответы [ 3 ]

1 голос
/ 18 октября 2019

Насколько я понимаю проблему, каждую строку можно рассматривать либо как последовательность имен, либо как последовательность целых чисел.
Поэтому я постараюсь прочитать файл построчно и проанализировать каждую извлеченную строку как одну последовательностьили другой (пробелы используются неявно).
Хитрость здесь в том, чтобы использовать "%n" для дальнейшего анализа той же строки.

#include <stdio.h>

int
main(void)
{
  FILE *input=fopen("input.txt", "r");
  if(!input)
  {
    return 1;
  }
  char line[1024];
  while(fgets(line, sizeof(line), input))
  {
    int pos=0;
    int value, count;
    char name[256];
    if(sscanf(line+pos, "%d%n", &value, &count)==1)
    {
      pos+=count;
      printf("a line with values: <%d>", value);
      while(sscanf(line+pos, "%d%n", &value, &count)==1)
      {
        pos+=count;
        printf(" <%d>", value);
      }
      printf("\n");
    }
    else if(sscanf(line+pos, "%255s%n", name, &count)==1)
    {
      pos+=count;
      printf("a line with names: <%s>", name);
      while(sscanf(line+pos, "%255s%n", name, &count)==1)
      {
        pos+=count;
        printf(" <%s>", name);
      }
      printf("\n");
    }
  }
  fclose(input);
  return 0;
}
1 голос
/ 18 октября 2019

Считайте ввод построчно с помощью fgets и сохраните режим: TEXT для текста, NUMBER для чисел и ERROR для состояния ошибки. (Состояние ошибки не описано. Это может произойти, если вы встретите нечисловые данные, например, в режиме NUMBER.)

Начните с TEXT. Перед обработкой строки в текстовом режиме проверьте, может ли это быть цифра простым sscanf в строке. Если вы можете прочитать число, переключитесь в режим нумерации, где вы сканируете все числа из строки.

char line[80];
enum {TEXT, NUMBER, ERROR = -1} mode = TEXT;

while (mode != ERROR && fgets(line, sizeof(line), stdin)) {
    if (mode == TEXT) {
        int n;

        if (sscanf(line, "%d", &n) > 0) mode = NUMBER;
    }

    if (mode == TEXT) {
        line[strcspn(line, "\n")] = '\0';
        process_string(line);
    } else if (mode == NUMBER) {
        char *p = line;
        char *end;
        int n = strtol(p, &end, 0);

        if (end == p) mode = ERROR;

        while (end > p) {
            process_number(n);
            p = end;
            n = strtol(p, &end, 0);
        }            
    }
}

(Но этот подход не удастся, если все числа в одном очень длинны. fgets усекаетввод, так что указанный размер не будет превышен.)

0 голосов
/ 18 октября 2019

Рассмотрите возможность изменения стратегии сканирования - игнорируйте все нецифровые символы и затем прочитайте целое число из этих цифр вперед

if ( scanf("%*[^0-9]%d", &n) == 1 ) { ... }

Первое поле "% * [...]" будет пропущенопо всему, что не является цифрой. Обратите внимание, что можно достичь EOF, прежде чем найти цифру - если для проверки требуется оператор.

...