Здравствуйте, Аноним, Вы писали:
А>Помогите написать паттерн для выкусывания текста из файла с мусором, может какой-нибудь более нормальный путь есть?
sscanf'ом здесь не обойдешься: он не запоминает, где закончил разбор.
Что считать текстом? Например, такое определение:
— текст — это последовательность слов, разделенных пробелами (общей длиной не менее 2 знаков)
— слово — это непустая последовательность букв [A-Za-z]
— код — это что угодно кроме текста
Строим конечный автомат:
START --> CODE, запомнить позицию C
CODE , A-Z|a-z --> TEXT1, запомнить позицию T
CODE , ? --> CODE
CODE , end --> вывести код от C до текущей, конец
TEXT1, A-Z|a-z|space --> TEXT, вывести код от C до T, сбросить C
TEXT1, ? --> CODE
TEXT1, end --> вывести код от C до текущей, конец
TEXT , A-Z|a-z|space --> TEXT
TEXT , ? --> CODE, вывести текст от T до текущей, сбросить T, запомнить C
TEXT , end --> вывести текст от T до текущей, конец
И пишем прогу
void print_begin();
void print_text(const char* s, int len);
void print_code(const char* s, int len);
void print_end();
void parse(const char* s)
{
print_begin();
const char* pc = s;
const char* pt = NULL;
char ch;
enum { CODE, TEXT1, TEXT } st = CODE;
while(true)
{
ch = *s;
switch(st)
{
case CODE:
if (ch == 0) { print_code(pc, s-pc); print_end(); return; }
else if(isalpha(ch)) { pt = s; st = TEXT1; }
else { }
break;
case TEXT1:
if (ch == 0) { print_code(pc, s-pc); print_end(); return; }
else if(isalpha(ch) || isspace(ch)) { print_code(pc, pt-pc); pc = NULL; }
else { st = CODE; pt = NULL; }
break;
case TEXT:
if (ch == 0) { print_text(pt, s-pt); print_end(); return; }
else if(isalpha(ch) || isspace(ch)) { }
else { print_text(pt, s-pt); st = CODE; pt = NULL; pc = s; }
break;
}
++s;
}
}
Вот примерно так.
(Программу не отлаживал, не обессудьте).
Здравствуйте, Аноним, Вы писали:
А>Помогите написать паттерн для выкусывания текста из файла с мусором, может какой-нибудь более нормальный путь есть?
А>А>int main(void)
А>{
А> char *mtext="*p902X Privet 5?*p902XTest DCL Printing?*p2038X00C0A2050995?(19U?(s1p0s0b16901T?(s10V?&d@?INFO ";
А> char mItog[100]={0};
А> sscanf(mtext,"[PATTERN]", &mItog); //iscntrl sprintf
А> printf("%s",mItog);
А> sleep(5);
А>
А>Спасибо
Так?
#include <stdio.h>
#include <string.h>
int main(int argc,char* argv[])
{
char *mtext="*p902X Privet 5?*p902XTest DCL Printing?*p2038X00C0A2050995?(19U?(s1p0s0b16901T?(s10V?&d@?INFO ";
int len=strlen(mtext);
int n=0;
char buf0[128];
char buf1[128];
while(n<len)
{
int i;
sscanf(mtext+n,"%[^a-zA-Z0-9 ]%[a-zA-Z0-9 ]%n",buf0,buf1,&i);
printf("%s\n",buf1);
n+=i;
}
return 0;
}
Можно использовать для этой цели LEX. В Delphi это бы выглядело примерно так:
%{
unit W;
interface
uses SysUtils, Classes, LexLib;
procedure GetWords(const St: string; Out: TStrings);
implementation
var
OutStringList: TStrings;
%}
L [A-Za-z]
%%
{L}+ begin OutStringList.Add(yytext) end;
. ;
%%
procedure GetWords(const St: string; Out: TStrings);
var
RetValue: Integer;
begin
Out.Clear;
yyinput := TStringStream.Create(St);
yyoutput := TMemoryStream.Create;
try
OutStringList := Out;
RetValue := yylex;
if RetValue <> 0 then raise Exception.CreateFmt('Lex error %d', [RetValue]);
finally
FreeAndNil(yyinput);
FreeAndNil(yyoutput);
end;
end;
end.
К преимуществам этого подхода следует отнести тот факт, что при усложнении правил определения слов, больших изменений вносить не прийдется...
Здравствуйте, WolfHound, Вы писали:
К>>sscanf'ом здесь не обойдешься: он не запоминает, где закончил разбор.
WH>%n Ы?
Интэрэсно, надо запомнить.
Тогда так
const char* src;
...
while(true)
{
int skip;
char word[1000];
int n = sscanf("%[a-zA-Z]%n", word, &skip);
if(n != 2) break;
process_word();
src += skip;
}
ДА?
Помогите написать паттерн для выкусывания текста из файла с мусором, может какой-нибудь более нормальный путь есть?
int main(void)
{
char *mtext="*p902X Privet 5?*p902XTest DCL Printing?*p2038X00C0A2050995?(19U?(s1p0s0b16901T?(s10V?&d@?INFO ";
char mItog[100]={0};
sscanf(mtext,"[PATTERN]", &mItog); //iscntrl sprintf
printf("%s",mItog);
sleep(5);
Спасибо
Здравствуйте, Кодт, Вы писали:
К>sscanf'ом здесь не обойдешься: он не запоминает, где закончил разбор.
%n Ы?
... << RSDN@Home 1.1 alpha 1 >>
Ну строго говоря, в случае создания собственного более или менее языка еще есть смысл приплетать Lex+Yacc. В данном случае регулярных выражений — девать некуда. Если нужна библиотека — бери PCRE (Perl Compatible Regular Expressions), стабильная вроде штука, в PHP используется.
А вообще насчет регулярных выражений рекомендую книгу Фридла "Регулярные выражения" издательства O'Reilly. Вообще, O'Reilly — хорошее издательство. Впрочем, я отвлекся... Пока.
Posted via RSDN NNTP Server 1.7 beta
EX>EX>#include <stdio.h>
EX>#include <string.h>
EX>int main(int argc,char* argv[])
EX>{
EX> char *mtext="*p902X Privet 5?*p902XTest DCL Printing?*p2038X00C0A2050995?(19U?(s1p0s0b16901T?(s10V?&d@?INFO ";
EX> int len=strlen(mtext);
EX> int n=0;
EX> char buf0[128];
EX> char buf1[128];
EX> while(n<len)
EX> {
EX> int i;
EX> sscanf(mtext+n,"%[^a-zA-Z0-9 ]%[a-zA-Z0-9 ]%n",buf0,buf1,&i);
EX> printf("%s\n",buf1);
EX> n+=i;
EX> }
EX> return 0;
EX>}
EX>
Это ж надо... 100 лет ищу нормальный модуль регулярных выражений для С, а он оказывается уже встроен... во круто.