Как читать пробел с помощью scanf в c?

проблема: мне нужно иметь возможность определить, когда два пробела происходят последовательно.

Я прочитал следующие вопросы:

как читать строку из файла с разделителями n

как читать scanf с пробелами

и я знаю о проблемах scanf:http://c-faq.com/stdio/scanfprobs.html

вход будет в следующем формате:

1 5 3 2  4 6 2  1 9  0

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

хотя я могу использовать fgets и различные встроенные функции для решения этой проблемы, я нахожусь в точке, где решение проблемы с scanf на данный момент, вероятно, будет проще. Однако, если это не так, использование fgets, strtok и atoi сделает большую часть работа, но мне все еще нужно определить два пробела подряд.

внизу будет принимать числа до нецелым занесены.

while ( scanf ( "%d", &x ) == 1 )

то, что мне нужно, это читать пробелы, а также, если есть два последовательных пробела, я буду программа, чтобы сделать что-то другое со следующим набором данных.

и как только я получаю пробел, я не знаю, как сказать:

if ((input == "whitespace") && (previousInput == "whitespace"))
  ya da ya da
else (input == "whitespace")
  ya da ya da
else 
  ya da ya da

Я ценю ваше время и благодарю вас за вашу помощь.

урок: В то время как решение для scanf опубликовано ниже Джонатаном Леффлером, решение было немного более простым с getc (путем требования менее глубокого знания внутреннего scanf, регулярных выражений и char). Оглядываясь назад, лучшее знание регулярных выражений, scanf и char облегчили бы проблему и, конечно, знали, какие функции доступны, и какой из них был бы лучшим для использования с самого начала.

5 ответов


getc и ungetc являются друзьями

#include <stdio.h>

int main(void) {
  int ch, spaces, x;
  while (1) {
    spaces = 0;
    while (((ch = getc(stdin)) != EOF) && (ch == ' ')) spaces++;
    if (ch == EOF) break;
    ungetc(ch, stdin);
    if (scanf("%d", &x) != 1) break;
    printf("%d was preceded by %d spaces\n", x, spaces);
  }
  return 0;
}

демо на http://ideone.com/xipm1

редактировать Rahhhhhhhhh ... Я загрузил это как C++. Вот то же самое, но теперь C99 strict( http://ideone.com/mGeVk )


while ( scanf ( "%c", &x ) == 1 )

используя %c вы можете читать пробелы, вы должны только читать все данные и хранить в массиве. Тогда выделите char* cptr и получить set cptr для начала массива, затем вы анализируете свой массив, и если вы хотите прочитать десятичные числа, вы можете использовать просто sscanf on cptr пока вы хотите прочитать decimal, но у вас должен быть указатель в хорошем положении на массиве (на номер, который вы хотите прочитать)

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' '))
  ya da ya da
else ((*cptr)== ' '))
  ya da ya da
  sscanf(++cptr, "%d", &x);
else 
  ya da ya da

если вы действительно хотите scanf введите функциональность, вы можете использовать fgets и sscanf, и использовать %n спецификатор, чтобы получить scanf, чтобы дать вашей программе смещения для начала и конца каждого пробела в то же время он выполняет остальную часть своей работы.

в противном случае, бросьте все scanf семья. На мой взгляд, это, возможно, самая бесполезная часть стандартной библиотеки.


каково ваше определение "белого пространства"?

честно говоря, я не думаю, что хотел бы попробовать использовать scanf() определить двойные пробелы; почти каждый другой метод был бы намного проще.

однако, если вы настаиваете на выполнении не отчаянно разумного, то вы можете использовать код, полученный из следующего:

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

int main(void)
{
    int d;
    char sp[3] = "";
    int n;

    while ((n = scanf("%d%2[ \t]", &d, sp)) > 0)
    {
        printf("n = %d; d = %d; sp = <<%s>>", n, d, sp);
        if (n == 2 && strlen(sp) == 2)
            printf(" end of group");
        putchar('\n');
    }
    return 0;
}

квадратные скобки заключают класс символов, а 2 перед ним настаивают не более чем на 2 символах из класса. Вы могли бы беспокоиться об этом, читая новую строку и пытаясь получить больше данных, чтобы удовлетворить класс символов, который может быть разрешен путем удаления новой строки из класса символов. Но тогда это зависит от вашего определения пробела и от того, заканчиваются ли группы автоматически новой строкой или нет. Не помешало бы сбросить sp[0] = ''; в конце цикла.

вы могли бы, возможно, лучше перевернуть поля, чтобы обнаружить два пробела перед числом. Но что бы не в обычный случай, так что вы бы вернуться на простой "%d" формат для чтения номера (и если это не удается, вы знаете, что у вас нет ни пробелов, ни ошибки номера). Обратите внимание, что %d жует ведущее белое пространство (как определено стандартом) - все из них.

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


вот решение, которое использует только функцию scanf (). Я использовал sscanf () в этом примере примерно для той же функциональности.

#include <stdio.h>


int p_1_cnt = 0, p_2_cnt = 0;

void process_1(int x)
{
    p_1_cnt++;
}


void process_2(int x)
{
    p_2_cnt++;
}


char * input_line = "1 5 3 2  4 6 2  1 9  0";

int main(void)
{
    char * ip = input_line;

    int x = 0, ws_0 = 0, ws_1 = 0, preceding_spaces = 1, fields = -2;

    while (sscanf (ip, "%d%n %n", &x, &ws_0, &ws_1) > 0)
    {
        ip += ws_0;

        if ((preceding_spaces) == 1)
            process_1(x);
        else
            process_2(x);

        preceding_spaces = ws_1 - ws_0;
    }

    printf("\np_1_cnt = %d, p_2_cnt = %d", p_1_cnt, p_2_cnt);
    _fgetchar();

    return 0;
}