Сканирование чисел среди букв в предложении - PullRequest
2 голосов
/ 11 мая 2010

У меня довольно простой вопрос. (используя C)

В предложении, таком как

In this document, there are 345 words and 6 figures

Как я могу сканировать 345 и 6, игнорируя все, что находится между ними?

Я пытался fscanf(FILE *pointer,"%d %d",&words,&figs); Но он получает только первое значение ...

Что я делаю не так?

EDIT

Извините, я забыл упомянуть, утверждение всегда исправлено ... In this document, there are # words and # figures

Ответы [ 5 ]

2 голосов
/ 11 мая 2010

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

const char *format = "In this document, there are %d words and %d figures";

int n = fscanf(fp, format, &words, &figs);
if (n != 2) //--- not recognized ...

Конечно, формат должен быть точно таким же, по крайней мере, до считываемых значений, поэтому безопаснее хранить его в одном месте, следуя Один раз и Только один раз принцип, и необходимо проверить код возврата fscanf().

2 голосов
/ 11 мая 2010

Проблема с вашей строкой формата в том, что пробел в строке формата приводит только к игнорированию пробела.

Я не думаю, что это возможно сделать, используя только scanf(), если перед следующим переводом строки не может быть второго числового значения, и вы также будете уязвимы для произвольной длины ввода. Но комбинация fgets() / sscanf() подойдет:

int a=0, b=0;
char buf[255];
fgets(buf, sizeof(buf), stdin);
sscanf(buf, "%*[^0-9]%d%*[^0-9]%d", &a, &b);

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

int a=0, b=0;
scanf("%*[^0-9]%d%*[^0-9]%d", &a, &b);
2 голосов
/ 11 мая 2010

Я думаю, что способ сделать это - объединить strpbrk с strtol.

Это будет выглядеть примерно так:

long int n;
const char *p = str;
while( (p = strpbrk(p, "-0123456789")) ) {
    n = strtol(p, &p, 0);
    handle(n);
}

Обновление:
В зависимости от того, что вы хотите, может быть лучше использовать strtol(p, &p, 10), потому что в тесте, который я только что выполнил, я обнаружил, что он действительно преобразовал Testing0x100what happens if I use base16 hex в 256, 16.

1 голос
/ 11 мая 2010

Вам нужно токенизировать строку и проверять каждое слово в последовательности. Следующий код изменен из ссылки C ++ , вызов на самом деле C.

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample 9876 string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    if (pch[0] >= '0' && pch[0] <= '9')
    {
        // It's a number
    }
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}
1 голос
/ 11 мая 2010

Я не думаю, что scanf / fscanf будет делать то, что вам нужно в этом случае, если вы не знаете точный формат входной строки.

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

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

    int main() {
      char* buff = "In this document, there are 345 words and 6 figures";
      char extra1[5000];
      char extra2[5000];
      int a,b;
      sscanf(buff,"%[In this document, there are ]%d%[ words and ]%d", extra1, &a, extra2, &b);
      cout<<a<<" "<<b<<endl;
      return 0;
    }
...