Разбор потока данных для управляющих строк - PullRequest
0 голосов
/ 14 октября 2010

Мне кажется, что это довольно распространенная проблема, но я не совсем понял, что искать.

У меня есть большой файл (поэтому я не хочу загружать все это в память), из которого мне нужно разобрать управляющие строки и затем передать эти данные на другой компьютер. В настоящее время я читаю файл размером 1000 байт.

Так, например, если у меня есть строка, содержащая коды ASCII, экранированные с помощью ('$' некоторое количество цифр ';'), и данные выглядят так: "quick $ 33; brown $ 126; fox $ a $ 12a ». Строка, идущая на другой компьютер, будет "быстро коричневая! ~ Fox $ a $ 12a".

В моем текущем подходе у меня есть следующие проблемы:

  • Что происходит, когда управляющие строки попадают на границу буфера?
  • Если за строкой стоит '$', за которой следует что угодно, кроме цифр и ';' Я хочу игнорировать это. Поэтому мне нужно читать вперед, пока не будет найдена строка полного управления.

Я пишу это прямо на C, поэтому у меня нет потоков, чтобы помочь мне.

Будет ли работать альтернативный двойной буферный подход, и если да, то как управлять текущими местоположениями и т. Д.

Ответы [ 2 ]

2 голосов
/ 14 октября 2010

Если я следовал тому, о чем вы спрашиваете, это называется лексическим анализом, токенизацией или регулярными выражениями.Для обычных языков вы можете создать конечный автомат, который распознает ваш ввод.На практике вы можете использовать инструмент, который понимает регулярные выражения, для распознавания и выполнения различных действий для ввода.

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

Вам следует использовать кольцевой буфер для ввода, чтобы индексирование конца снова переместилось на передний план.Всякий раз, когда половина данных, которые может содержать буфер, была обработана, вы должны сделать еще одно чтение, чтобы пополнить его.Размер вашего буфера должен быть как минимум вдвое больше самого большого «слова», которое вам нужно распознать.Индексация в этом буфере будет использовать оператор модуля (остатка) % для выполнения переноса (если вы выберете размер буфера, равный степени 2, например 4096, то вместо этого вы можете использовать побитовый &).

Теперь вы просто смотрите на символы, пока не прочитаете $, выведите то, на что вы смотрели, до этого момента, а затем узнаете, что находитесь в другом состоянии, потому что вы видели $ вассмотрите на другие символы, пока не увидите другой символ, который завершает текущее состояние (;), и выполните некоторые другие действия с данными, которые вы прочитали. Как обрабатывать случай, когда $ отображается без хорошо отформатированного числапо;было не совсем понятно в вашем вопросе - что делать, если перед тем, как вы увидите ;, например, миллион цифр

Регулярные выражения будут:

 [^$]

Любой не знак доллара.Это может быть дополнено закрытием ([^$]* или [^$]+) для распознавания строки не $ символов за раз, но это может быть очень длинным.

$[0-9]{1,3};

Это распознаетзнак доллара, за которым следуют от 1 до 3 цифр и точка с запятой.

[$]

Это будет признавать только знак доллара.Он заключен в квадратные скобки, потому что $ является особенным во многих представлениях регулярных выражений, когда он находится в конце символа (что в данном случае и есть), и означает «совпадать только в конце строки».

В любом случае, в этом случае он распознает знак доллара в том случае, если он не распознается другим, более длинным шаблоном, который распознает знаки доллара.

В lex у вас может быть

[^$]{1,1024}          { write_string(yytext); }
$[0-9]{1,3};          { write_char(atoi(yytext)); }
[$]                   { write_char(*yytext); }

, и он сгенерирует файл .c, который будет функционировать как фильтр, аналогичный тому, который вы запрашиваете.Вам нужно будет прочитать немного больше о том, как использовать lex .

0 голосов
/ 14 октября 2010

Семейство функций "f" в <stdio.h> может позаботиться о потоковой передаче за вас. В частности, вы ищете fopen(), fgets(), fread() и т. Д.

Ответ Nategoose об использовании lex (и я добавлю yacc, в зависимости от сложности вашего ввода) также заслуживает рассмотрения. Они генерируют работающие лексеры и парсеры, и после того, как вы их используете, вы никогда больше не напишите их вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...