Как мне прочитать пробел, используя scanf в c? - PullRequest
9 голосов
/ 22 сентября 2010

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

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

как прочитать строку из файла \ 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

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

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

Ответы [ 5 ]

5 голосов
/ 22 сентября 2010

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

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

1 голос
/ 22 сентября 2010
while ( scanf ( "%c", &x ) == 1 )

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

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' '))
  ya da ya da
else ((*cptr)== ' '))
  ya da ya da
  sscanf(++cptr, "%d", &x);
else 
  ya da ya da
0 голосов
/ 03 февраля 2015

Вот решение, которое использует только функцию 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;
}
0 голосов
/ 22 сентября 2010

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

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

0 голосов
/ 22 сентября 2010

Каково ваше определение «пробела»?

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

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

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

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

...