Sscanf не перемещается, просматривает одно и то же целое число каждый раз! С

У меня есть строка с ints, и я пытаюсь получить все ints в другом массиве. Когда sscanf не находит int, я хочу, чтобы цикл остановился. Итак, я сделал следующее:

int i;
int getout=0;
for(i=0; i<bsize && !getout;i++){
  if(!sscanf(startbuffer, "%d", &startarray[i])){
    getout=1;
  }
}
//startbuffer is a string, startarray is an int array.

Это приводит к тому, что все элементы startarray будут первым char в startbuffer. sscanf работает отлично, но не перемещается на следующий int, он просто остается в первой позиции.

Любая идея, что не так? Спасибо.

Ответ 1

Тот же указатель строки передается каждый раз, когда вы вызываете sscanf. Если бы он "перемещал" вход, ему приходилось перемещать все байты строки каждый раз, что было бы медленным для длинных строк. Кроме того, он будет перемещать байты, которые не были отсканированы.

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

int nums_now, bytes_now;
int bytes_consumed = 0, nums_read = 0;

while ( ( nums_now = 
        sscanf( string + bytes_consumed, "%d%n", arr + nums_read, & bytes_now )
        ) > 0 ) {
    bytes_consumed += bytes_now;
    nums_read += nums_now;
}

Ответ 2

Это правильное поведение sscanf. sscanf работает с const char*, а не с входным потоком из файла, поэтому он не будет хранить информацию о том, что он потреблял.

Что касается решения, вы можете использовать %n в строке формата, чтобы получить количество символов, которое оно потребляло до сих пор (это определено в стандарте C89).

например. sscanf("This is a string", "%10s%10s%n", tok1, tok2, &numChar); numChar будет содержать количество символов, потребляемых до сих пор. Вы можете использовать это как смещение, чтобы продолжить сканирование строки.

Если строка содержит только целые числа, которые не превышают максимальное значение длинного типа (или длинного длинного типа), используйте strtol или strtoll. Помните, что тип long может быть 32-разрядным или 64-битным, в зависимости от системы.

Ответ 3

Вы правы: sscanf действительно не "перемещается", потому что двигаться нечего. Если вам нужно сканировать кучу ints, вы можете использовать strtol - он сообщает вам, сколько он читает, поэтому вы можете передать следующий указатель обратно функции на следующей итерации.

char str[] = "10 21 32 43 54";
char *p = str;
int i;
for (i = 0 ; i != 5 ; i++) {
    int n = strtol(p, &p, 10);
    printf("%d\n", n);
}