Re: Паттерны на Си, надо выкусить нормальные слова из мусора
От: Кодт Россия  
Дата: 05.08.03 08:52
Оценка: 14 (6)
Здравствуйте, Аноним, Вы писали:

А>Помогите написать паттерн для выкусывания текста из файла с мусором, может какой-нибудь более нормальный путь есть?


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;
  }
}

Вот примерно так.
(Программу не отлаживал, не обессудьте).
Перекуём баги на фичи!
Re: Паттерны на Си, надо выкусить нормальные слова из мусора
От: e-Xecutor Россия  
Дата: 06.08.03 06:53
Оценка: 34 (5)
Здравствуйте, Аноним, Вы писали:

А>Помогите написать паттерн для выкусывания текста из файла с мусором, может какой-нибудь более нормальный путь есть?


А>
А>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;
}
Re: Паттерны на Си, надо выкусить нормальные слова из мусора
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 05.08.03 09:43
Оценка: 3 (1)
Можно использовать для этой цели 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.


К преимуществам этого подхода следует отнести тот факт, что при усложнении правил определения слов, больших изменений вносить не прийдется...
Re[3]: Паттерны на Си, надо выкусить нормальные слова из мус
От: Кодт Россия  
Дата: 06.08.03 08:57
Оценка: 3 (1)
Здравствуйте, 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;
}

ДА?
Перекуём баги на фичи!
Паттерны на Си, надо выкусить нормальные слова из мусора
От: Аноним  
Дата: 05.08.03 07:44
Оценка:
Помогите написать паттерн для выкусывания текста из файла с мусором, может какой-нибудь более нормальный путь есть?

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);


Спасибо
Re[2]: Паттерны на Си, надо выкусить нормальные слова из мус
От: WolfHound  
Дата: 05.08.03 17:42
Оценка:
Здравствуйте, Кодт, Вы писали:

К>sscanf'ом здесь не обойдешься: он не запоминает, где закончил разбор.


%n Ы?
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Паттерны на Си, надо выкусить нормальные слова из мусора
От: alexandrov_alex США  
Дата: 06.08.03 03:44
Оценка:
Ну строго говоря, в случае создания собственного более или менее языка еще есть смысл приплетать Lex+Yacc. В данном случае регулярных выражений — девать некуда. Если нужна библиотека — бери PCRE (Perl Compatible Regular Expressions), стабильная вроде штука, в PHP используется.
А вообще насчет регулярных выражений рекомендую книгу Фридла "Регулярные выражения" издательства O'Reilly. Вообще, O'Reilly — хорошее издательство. Впрочем, я отвлекся... Пока.
Posted via RSDN NNTP Server 1.7 beta
It's kind of fun to do the impossible (Walt Disney)
Re[2]: Паттерны на Си, надо выкусить нормальные слова из мус
От: _Budda_ Украина http://vfm.1gb.ru
Дата: 09.02.06 12:30
Оценка:
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 лет ищу нормальный модуль регулярных выражений для С, а он оказывается уже встроен... во круто.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.