0

そのため、Linuxでlexツールを使用していて、恥ずかしい位置に落ちて、whileループから抜け出せませんでした。

例: 私は書きました。

while(1)
{
 int x = yylex();
 switch(x):
  case(ID):printf("ID");
  case(NUM):printf("NUM");

}

今、私は yyin を使ってファイルから読んでいます。問題は、ファイル全体を読み取った後も while ループが失敗せず、端末で追加の入力を要求し続けることです。そのため、 while ループを呼び出した後、他の関数を呼び出すことができませんでした。私は何か基本的なことが欠けていることを知っています.誰かがこの問題についての洞察を提供できれば素晴らしいことです.

PS# ご回答ありがとうございます。宿題提出日の前の緊張と睡眠不足。ところで - 私は自分の答えをすでに考え出しました。

4

4 に答える 4

2

関数内で何が起こっているかに関係なく、C コードにいくつかの問題がありyylex()ます。コードを次のように引用します。

while(1)
{
  int x = yylex();
  switch(x):
  case(ID):printf("ID");
  case(NUM):printf("NUM");
}

これは、C として受け入れられないため、明らかにコンパイルしたソースではありません。最初のコロン ( の後ろswitch(x)) を開きブレースに置き換える必要があり、最後に{別の閉じブレースが必要です。}

while(1)
{   
    int x = yylex();
    switch(x)
    {   
    case(ID):printf("ID");
    case(NUM):printf("NUM");
    }   
}

これは構文的に有効な C コードですが、まだ問題があります。

  1. break;おそらくafter eachがあるはずcaseです。
  2. default:おそらく、ループを終了するために使用される句があるはずです(ただしbreak、スイッチのスコープ内でそれを行うために使用することはできません)。
  3. printf()ステートメントは、データが表示されるように改行を出力する必要があります。

yylex()最後に到達すると 0 を返すため、次のようにコードを修正する必要があります。

void function(void)
{
    int x;
    while ((x = yylex()) != 0)
    {   
        switch (x)
        {   
        case ID: 
            printf("ID\n");
            break;
        case NUM:
            printf("NUM\n");
            break;
        default:
            printf("Other: %d\n", x); 
            break;
        }   
    }   
}

これにより、少なくとも何が起こっているかが表示され、lex正しく終了しないようにアナライザーを作成しない限り、無限ループは発生しません。yylex()代わりに 0 を返すことでループが制限されているため、デフォルトのケースではループを終了しないことにしました。

を書くときwhile (1)、あなたは無限ループを書いています。ループが本当に無限かどうかを検討するのはあなたの義務です。そうでない場合は、ループに別のサイクルがあるかどうかを制御するループの先頭でテストを実行できるようにする必要があります。

于 2012-06-22T02:15:53.293 に答える
1

yylex() は、入力の論理的な最後で 0 を返します。これを試して:

int x = -1;
while(!(x == 0))
{
    x = yylex();
    switch(x):
    {
        case(0): printf("that's all, folks!"); break;
        case(ID): printf("ID"); break;
        case(NUM): printf("NUM"); break;
    }
}
于 2012-06-22T02:16:15.400 に答える
0

デビッドの答えに追加するには、別のバージョンを次に示します。

do
{
    int x = yylex();

    if (!x)
        break;

    switch(x):
    {
        case(ID): printf("ID"); break;
        case(NUM): printf("NUM"); break;
    }
} while(1);

これは、あなたがしばらくの間抜け出せることを示すためだけのものでした(1)。x をローカル スコープに保持し、最初のパスを評価したり、不必要に切り替えたりしません。もちろん、誰かが「読みにくい」という切り札を出す可能性が高いです...

于 2012-06-22T03:35:02.390 に答える
0

ええと、私は lex が何であるかに精通していないことを認めますが、Linux 環境とターミナルについてはかなり知っているので...

ターミナルで「Ctrl」と「c」を同時に入力してみてください。それでもうまくいかない場合は、「Ctrl」+「z」を使用してください。コンピューターの電源が切れて完全に消えるまでプロセスをバックグラウンドで停止してもかまわない場合は、Ctrl + Z の​​後、他に何もする必要はありません。Ctrl + C が機能した場合、プログラムは終了し、問題ありません。

なんらかの理由でどちらも機能しない場合、作成したプログラムの名前がわかっている場合は、ターミナルに次のように入力できます。

pkill -9 [insert name of program here]

...無視できないキルシグナルをプロセスに送信し、すべてのメモリ(RAM-ディスクへの変更を元に戻さない)を親プロセスに返します。

プログラムの名前がわからないが、おそらく認識できると思われる場合は、次のことを試してください。

top

これにより、ターミナルで現在実行中のすべてのプロセスが表示されます。まだ実行中のプログラムの名前を見つけたら、q を押して top を終了し、top で認識した名前で上記の kill コマンドを入力します。プログラムの名前がわからず、Ctrl + Z が機能したが、停止したジョブがコンピューターの電源を切るまでメモリを占有し続けたくない場合は、次のように入力できます。

ps -a

プログラムを実行 (および停止) した端末セッションで、「停止」というラベルの付いたジョブが表示されるのは、おそらくあなたのものです。繰り返しますが、上記の pkill コマンドを使用すると、それが強制終了されます。なんらかの理由で、プロセス ID はわかっているが名前がわからない場合 (理由はわかりませんが、そのとおりです...)、「pkill」の代わりにコマンド「kill」を使用できます (これらのコマンドの使い方はインターネット上に散らばっているので、ここでは触れません. また、次の方法でアクセスできる便利なヘルプマニュアルページもあります:

man [the name of the program you want help with; 'pkill' or 'kill', in this case.]
于 2012-06-22T00:58:41.433 に答える