Ако проблемът е толкова прост, колкото показва вашият пример, можете просто да използвате fscanf
. Проблемът с fscanf
вероятно няма да се различава от проблема с използването на вашия генериран от flex скенер, който е, че новите редове просто се третират като интервал. Ако вашият скенер връща специален знак за нови редове (или може да бъде убеден да го направи, вижте по-долу), тогава прочетете нататък.
Ако разбирам какво искате да направите правилно, просто трябва да настроите входа правилно и след това многократно да извиквате yylex
. Ако използвате приложния програмен интерфейс (API) без повторно влизане по подразбиране, тогава може да изглежда по следния начин:
// Returns a count, and sets the out parameter to a
// malloc'd array of malloc'd strings.
// The free function is left as an exercise.
int read_headers(char*** out) {
int count = 0;
char** id_array = NULL;
*out = id_array;
int token;
while ((token = yylex()) == TOKEN_IDENTIFIER) {
id_array = realloc(id_array, (count + 1) * sizeof *id_array);
if (id_array) *out = id_array;
else
// Handle error
id_array[count ++] = strdup(yytext);
}
if (token != '\n')
// Handle error
return count;
}
// Reads exactly n numbers and stores them in the out parameter,
// which must point at an array of size n.
// Returns: n on success. 0 if EOF reached. -1 on error
int read_n_numbers(double* out, int n) {
for (int i = 0; i < n; ++i, ++out) {
int token = yylex();
if (token != TOKEN_NUMBER) {
if (i == 0 && token == 0) return 0;
// Error: non-number or too few numbers
return -1;
}
*out = yylval.number;
}
if (yylex() != '\n') {
// Error: too many numbers
return -1;
}
return 0;
}
Вероятно вашият скенер всъщност не връща \n
за нов ред. Това рядко би било полезно в граматиката на израза (въпреки че понякога е полезно). Но е лесно да модифицирате скенера да обработва нови редове при поискване; просто трябва да използвате начално условие. Ние го правим включително условие за начало, защото то трябва да обработва само нови редове, но имайте предвид, че това означава, че всички немаркирани правила също са активни, така че трябва да се уверите, че немаркираното правило, което обработва също само нови редове обработва един нов ред.
%s RETURN_NEWLINES
%%
<RETURN_NEWLINES>\n { return '\n'; }
\n ; // Ignore a single newline
[ \t]+ ; // Ignore any number of horizontal whitespace
С това място можете да активирате нови редове, като просто извикате BEGIN(RETURN_NEWLINES)
преди сканиране (и BEGIN(INITIAL)
, за да се върнете към игнорирането им.) Ще трябва да поставите функции, които активират и деактивират сканирането за нов ред във вашия файл с дефиниции на flex, тъй като изискваните макроси не се изнасят.
person
rici
schedule
28.07.2015