2014-12-08 1 views
1

сказать, что у меня есть строка:Определить, если sscanf Читать Anything с% * с

char* foo = " blah blee bleck "; 

Теперь говорят, что я хочу прочитать и выбросить первые два слова:

int bar = 0; 

sscanf(foo, "%*s%n", &bar); 
foo += bar; 

if(bar > 0) sscanf(foo, "%*s%n, &bar); 

Мои вопрос в том, как я могу узнать, прочитал ли второй код sscanf?

Нужно ли мне 0 bar между каждым чтением, чтобы определить, действительно ли строка была прочитана, или есть лучший способ?

EDIT:

Проверка sscanf возвращаемое значение не будет работать, потому что% * s и% п не увеличивают sscanf «s возвращаемого значения:

printf("%d ", sscanf(foo, "%*s%n", &bar)); 
printf("%d ", bar); 
printf("%d ", sscanf(foo + bar, "%*s%n", &bar)); 
printf("%d\n", bar); 

Выведем:

+1

Возможно, вам понравится [мой ответ на соответствующий вопрос] (http://stackoverflow.com/a/4160001/25324). – pmg

+0

@pmg Я понял, что эта концепция 'sscanf', возвращающая' EOF', мне не хватало. –

ответ

2

Проверьте возвращаемое значение вызова sscanf, так как иконка документа сообщит, что будет возвращено целочисленное значение.

int sscanf(const char   *buffer, const char   *format, ...); (C99) 

Я попробовал небольшой кусок кода в моей машине, подобной Вашему запросу, и в самом деле sscanf возвращает отрицательные значения для неудачной операции.

код теста:

#include <stdio.h> 

void main(void) 
{ 
char* foo = " blah bleee bleckk "; 
//char* foo = " blah"; 
int bar = 0; 
int ret = -10; 

printf("#m1 foo:%s\n",foo); 
printf("#m1 bar:%d\n",bar); 
printf("#m1 ret:%d\n\n",ret); 

ret = sscanf(foo, "%*s%n", &bar); 
foo += bar; 
printf("#m2 foo:%s\n",foo); 
printf("#m2 bar:%d\n",bar); 
printf("#m2 ret:%d\n\n",ret); 

if(bar > 0) 
{ 
    ret = -10; 
    ret = sscanf(foo, "%*s%n", &bar); 
    foo += bar; 
} 
printf("#m3 foo:%s\n",foo); 
printf("#m3 bar:%d\n",bar); 
printf("#m3 ret:%d\n",ret); 
} 

Испытательный выход для двух сценариев:

./a.out 
#m1 foo: blah bleee bleckk 
#m1 bar:0 
#m1 ret:-10 

#m2 foo: bleee bleckk 
#m2 bar:6 
#m2 ret:0 

#m3 foo: bleckk 
#m3 bar:7 
#m3 ret:0 


./a.out 
#m1 foo: blah 
#m1 bar:0 
#m1 ret:-10 

#m2 foo: 
#m2 bar:6 
#m2 ret:0 

#m3 foo:oo:%s 

#m3 bar:6 
#m3 ret:-1 

Проблема заключается значение бара не устанавливается на ноль для неудачных вызовов sscanf.

+0

Ответ в этом сообщении во втором сценарии, когда 'foo' просто« бла ». Обратите внимание, что 'ret' равен -1 (' EOF') в последнем выпуске. При таком понимании смысл @hdante [answer] (http://stackoverflow.com/a/27359266/2642059) имеет смысл. –

0

Лучшим способом, вероятно, будет использование некоторого правильного кода токенизации, а не построение на sscanf(). Я бы, наверное, написать что-то вроде этого:

const char * skip_word(const char *s) 
{ 
    while(isspace(*s)) 
    ++s; 
    while(*s && !isspace(*s)) 
    ++s; 
    return s; 
} 

Это может быть использовано, чтобы пропустить ведущие пробелы с последующим словом, где слово очень слабо определяется как «не-пробельных символов». Затем вы можете извлечь третье слово, дважды позвонив выше, конечно, проверяя промежуточные возвращаемые значения для чувствительности. Что-то вроде того.

Но да, вам нужно было бы очистить bar, чтобы получить свежую интерпретацию, конечно.

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

+0

Под «правильным кодом токенизации» вы подразумеваете, что я пишу свое собственное чтение функции одним символом за раз, выбрасывая пробелы и возвращая, когда следующий символ является пробелом или нулевым? –

+0

Хотя я считаю, что токенизация является допустимой альтернативой, она, без сомнения, создает сложность того, что должно быть простым решением. [hdante] (http://stackoverflow.com/users/1797000/hdante) и [MuruganV-userm] (http://stackoverflow.com/users/2854673/muruganv-userm) предотвращает повторное использование колеса. –

-1

Из sscanf() документации:

ВОЗВРАТ СТОИМОСТИ

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

Итак, если sscanf() не возвращает число соответствий, которое вы ожидаете, вероятно, оно не читало то, что вы хотели.

+1

Нет, звездочка подавляет это. – unwind

+0

@GreenScape Ни «% * s», ни «% n» не увеличивают возвращаемое значение из 'sscanf'. (Сначала я попробовал этот подход.) –

+0

@JonathanMee Не могли бы вы рассказать нам, почему этот метод не работает? Если sscanf не работает, он должен вернуть значения отказа –

1

Если вы игнорируете пробелы, правильным способом является проверка EOF в возвращаемом значении sscanf(). EOF означает, что% * s ничего не читал. Если вы не игнорируете пробелы, решение тривиально: if * foo! = 0 перед sscanf, тогда sscanf что-то прочитает.

1

... читать и выбросить первые два слова:

const char* foo = " blah blee bleck "; 
int bar = 0; 
sscanf(foo, "%*s%*s% %n", &bar); 
if (bar) { 
    printf("Success: string with first two words thrown away:'%s'\n", &foo[bar]); 
} 

выше добавил пробел перед "%n" выбросить белое-пространство после того, как «бли».


Чтобы узнать, прочитал ли второй sscanf что-нибудь? Нужно ли мне 0?

Да, сбрасывание bar = 0; - это простой способ. "%n" не действует, если предыдущие "%*s" не сканировали некоторое небелое пространство.

char* foo = " blah blee bleck "; 
int bar = 0; 
sscanf(foo, "%*s%n", &bar); 
foo += bar; 

if(bar > 0) { 
    puts("first sscanf read something."); 
    bar = 0; 
    sscanf(foo, "%*s%n", &bar); 
    if (bar) puts("second sscanf read something."); 
} 
+0

Ницца Я узнал из этого сообщения, что: «Единственное пробел в строке формата проверяет любое количество пробельных символов, извлеченных из потока (в том числе и нет)». http://www.cplusplus.com/reference/cstdio/scanf/#parameters –

+0

@Jonathan Mee Еще одна ценная заметка о '' '' ',' '\ t" ',' "\ n" и т. д. заключается в том, что они никогда не сработает. Сканирование всегда переходит к следующей директиве. – chux

+0

Да, я читал это. Человек scanf настолько силен, мне просто жаль, что я не знал все эти трюки еще в колледже! –

 Смежные вопросы

  • Нет связанных вопросов^_^