Использование sscanf для извлечения int из строки в C++

моя функция должна обрабатывать строки, которые выглядят как Say hello y(5) или data |x (3)|, и мне нужно иметь возможность извлечь показанное целое число и сохранить его в отдельную переменную int с именем address. Однако некоторые строки, проходящие через, не будут иметь целых чисел, и для них адрес должен по умолчанию иметь значение 0. Когда строка содержит целое число, она всегда будет находиться между скобками. Я попытался использовать sscanf, но, будучи очень новым для sscanf, я сталкиваюсь с проблемами.. По какой-то причине адрес всегда читается как 0. Вот мой код:

void process(string info)
{
int address = 0; // set to 0 in case info contains no digits
sscanf(info.c_str(), "%d", address);
.
.
.
// remainder of code makes other function calls using the address, etc
}

любые идеи о том, почему sscanf не удается найти целое число между скобками? Спасибо!

4 ответов


почему sscanf не может найти целое число между скобками

на "%d" на sscanf(info.c_str(), "%d", address) вызывает sscanf() чтобы остановить сканирование после обнаружения нечисловой последовательности. Текст как "(5)" просто прекратит сканирование на "(".

вместо кода нужно пропустить нечисловой текст.


псевдо-код

  in a loop
    search for any of "-+0123456789"
    if not found return 0
    convert from that point using sscanf() or strtol()
    if that succeeds, return number
    else advance to next character

образец код

int address;
const char *p = info.c_str();
for (;;) {
  p += strcspn(p, "0123456789+-");
  if (*p == 0) return 0;
  if (sscanf(p, "%d", &address) == 1) {
    return address;
  }
  p++;
}

Примечания:

на strcspn функция вычисляет максимальную длину начального сегмента строки, на которую указывает s1 который полностью состоит из символов, не из строки, на которую указывает s2. C11 7.24.5.3 2


если код хочет полагаться на " это всегда будет между скобками."и входы "abc()def(123)" не происходит, который имеет предшествующие нечисловые данные между ().:

const char *p = info.c_str();
int address;
if (sscanf(p, "%*[^(](%d", &address)==1) {
  return address;
}
return 0;

или просто

int address = 0;
sscanf(info.c_str(), "%*[^(](%d", &address);
return address;

вы можете использовать что-то простое, как это, где strchr находит первое вхождение "(" затем используйте atoi, чтобы вернуть целое число, которое остановится на первой не-цифре.

  char s1[] = "hello y(5)";
  char s2[] = "data [x(3)]";
  char s3[] = "hello";

  int a1 = 0;
  int a2 = 0;
  int a3 = 0;

  char* tok = strchr( s1, '(');
  if (tok != NULL)
    a1 = atoi(tok+1);

  tok = strchr( s2, '(');
  if (tok != NULL)
    a2 = atoi(tok+1);

  tok = strchr(s3,'(');
  if (tok != NULL)
    a3 = atoi(tok+1);

  printf( "a1=%d, a2=%d, a3=%d", a1,a2,a3);

  return 0;

когда строка содержит целое число, она всегда будет находиться между скобки

строго соответствовать с этим требованием Вы можете попробовать:

void process(string info)
{
    int address;
    char c = '5'; //any value other than ) should work

    sscanf(info.c_str(), "%*[^(](%d%c", &address, &c);
    if(c != ')') address = 0;
    .
    .
    .
}

ссылка на решение

int address;

sscanf(info.c_str(), "%*[^0-9]%d", &address);
printf("%d", address);

это должно извлечь целое число между скобками