sscanf: неизвестное об известном
От: VVV Россия  
Дата: 18.11.02 19:04
Оценка: 143 (18)
Совсем недавно нашёл замечательную возможность функции sscanf, о которой не читал ни в одной книге, да и поиск по этому сайту говорит, что эта возможность выпала из поля зрения многих — очень многих.
Речь идёт о таком формате: %[search_set]

В квадратных скобках можно задавать [не]ожидающиеся во входном потоке символы и интервалы символов — похоже на синтаксис регулярных выражений.

Несколько примеров:

1. разбор строк типа key=value — периодически появляется здесь(на форуме) такой вопрос — теперь можно дать простой ответ .

char *s="caption=RSDN forum";
char key[64];
char value[128];
sscanf(s, "%[^=]=%[]", key, value);
printf("key=%s value=%s\n", key, value);


"%[^=]=%[]"
%[^=] — читать всё до символа = в переменную key
= — прочитать символ =
%[] — читать всё, включая пробелы в переменную value

2. разбор comma-separated строк/файлов
Q38335 — к сожалению эта статья сейчас недоступна на сайте Микрософт- делаю копию из своего MSDN

HOWTO: sscanf() Example Using a Comma (,) as Delimiter

Q38335


--------------------------------------------------------------------------------
The information in this article applies to:

The C Run-Time (CRT), included with:
Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, 6.0ax
Microsoft C for OS/2, versions 5.1, 6.0, 6.0a
Microsoft C/C++ for MS-DOS, version 7.0
Microsoft Visual C++ for Windows, 16-bit edition, versions 1.0, 1.5
Microsoft Visual C++, 32-bit Editions, versions 1.0, 2.0, 4.0, 5.0, 6.0

--------------------------------------------------------------------------------


SUMMARY
The example below shows how to use the sscanf() C run-time function to read from an internal buffer delimiting fields with a comma (,). The key is to use the brackets in the format of sscanf() function. The format will be %[^','], which tells the function to read from the buffer until a comma (,) is reached.

Sample Code


/* The following sample illustrates the use of brackets and the
   caret (^) with sscanf().
   Compile options needed: none
*/ 

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

char *tokenstring = "first,25.5,second,15";
int result, i;
double fp;
char o[10], f[10], s[10], t[10];

void main()
{
   result = sscanf(tokenstring, "%[^','],%[^','],%[^','],%s", o, s, t, f);
   fp = atof(s);
   i  = atoi(f);
   printf("%s\n %lf\n %s\n %d\n", o, fp, t, i);
}


3. ещё пример разбор строк вида <строка><число>, например id1, id234, Build2002
char t[32];
char d[32];
char *text="Build2002";
sscanf(text, "%[^0-9]%[0-9]", t, d);


Можно придумать ещё много примеров, где можно использовать эту возможность: разбор номеров телефонов, электронных адресов, строк запросов к веб сайтам,....

Хотя стандарт ANSI этого не требует:

Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]. This is a common scanf function extension, but note that the ANSI standard does not require it.

но эта возможность присутствует в VS6.0, VS7.0, Borland C++ 5.02
Re: sscanf: неизвестное об известном
От: Andrew S Россия http://alchemy-lab.com
Дата: 18.11.02 21:58
Оценка:
Да ну — а почему ж в MSDN не посмотреть. Там про это есть.. несколько страничек. Я как то давно это знал и тем более всегда пользовал. Особенно удобно при разборе текстовых файлов, а один из программеров на перле после этого удивился — "надо же, в sscanf'е совсем немного до регулярных выражений не дотянули".
А я как то считал это обычным делом... да, судя по всему, некоторым здесь стоит подучить давно забытый С .

Успехов.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: sscanf: неизвестное об известном - вдогонку
От: Andrew S Россия http://alchemy-lab.com
Дата: 18.11.02 22:11
Оценка: 27 (6)
На правах "вдогонку".

Кстати, как еще оказалось, тоже немногие прочитали описание типа %n. Использование %n позволяет получить текущее смещение во входном потоке данных.
Так очень удобно выяснять какой кусок буфера был просмотрен в поисках шаблона. Например, sscanf("void fun(1) {};", "%*s fun ( %i )%n", &i, &pos); вернет в pos 0xB, т.е. позицию сразу за определением функции, что позволит далее приступить к разбору ее тельца.
Успеховъ.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: sscanf: неизвестное об известном
От: korzhik Россия  
Дата: 25.03.05 17:28
Оценка:
Здравствуйте, VVV, Вы писали:

Удалено излишнее цитирование

VVV>sscanf(s, "%[^=]=%[]", key, value);


VVV>%[] — читать всё, включая пробелы в переменную value


Последнее утверждение ложно, подробности здесь
Автор: Андрей Тарасевич
Дата: 19.03.05
Re: sscanf: неизвестное об известном
От: Андрей Тарасевич Беларусь  
Дата: 25.03.05 18:26
Оценка:
Здравствуйте, VVV, Вы писали:

VVV>Совсем недавно нашёл замечательную возможность функции sscanf, о которой не читал ни в одной книге, да и поиск по этому сайту говорит, что эта возможность выпала из поля зрения многих — очень многих.

VVV>Речь идёт о таком формате: %[search_set]

VVV>В квадратных скобках можно задавать [не]ожидающиеся во входном потоке символы и интервалы символов — похоже на синтаксис регулярных выражений.


Один недостаток такого спецификатора формата — он не может соответствовать пустой подстроке во входе. Что-то обязательно должно ему соответствовать. Иначе — ошибка и 'scanf' прекращает разбор.

VVV>Несколько примеров:


VVV>1. разбор строк типа key=value — периодически появляется здесь(на форуме) такой вопрос — теперь можно дать простой ответ .


VVV>
VVV>char *s="caption=RSDN forum";
VVV>char key[64];
VVV>char value[128];
VVV>sscanf(s, "%[^=]=%[]", key, value);
VVV>printf("key=%s value=%s\n", key, value);

VVV>


VVV>"%[^=]=%[]"

VVV>%[^=] — читать всё до символа = в переменную key
VVV>= — прочитать символ =
VVV>%[] — читать всё, включая пробелы в переменную value

Последнее неверно с точки зрения стандартной библиотеки. Спецификатор формата '[]' не поддерживает пустых наборов символов. Если за символом '[' сразу следует ']' (или за '[^' сразу следует ']'), то это ']' считается частью символьного набора, а не окончанием спецификатора. Например, "%[]ab] — это спецификатор, который соответствует символам ']', 'a' и 'b' во входе. А "%[]%[]" — это один спецификатор с символами ']', '%' и '[' внутри, а не два спецификатора, как может показаться с первого взгляда.

То, что ты написал — "%[]", это ни что иное как спецификатор с одним символом ']' внутри и без закрывающей скобки вообще, т.е. спецификатор сформирован некоррректно. Поведение не определено.

VVV>2. разбор comma-separated строк/файлов

VVV>Q38335 — к сожалению эта статья сейчас недоступна на сайте Микрософт- делаю копию из своего MSDN

VVV>HOWTO: sscanf() Example Using a Comma (,) as Delimiter


VVV>
VVV>...
VVV>   result = sscanf(tokenstring, "%[^','],%[^','],%[^','],%s", o, s, t, f);
VVV>...
VVV>


И что же тут делают эти апострофы в спецификаторах формата?
Best regards,
Андрей Тарасевич
http://files.rsdn.org/2174/val.gif
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.