2

コースの一環として、Turbo C を使用して C を学習する必要があります (残念ながら)。

私たちの先生は、段落内の文字、単語、文の数を数えるコードを作成するように私たちに求めました (printf、getch()、および while ループのみを使用します..彼はまだ他のコマンドを使用することを望んでいません)。 . ここに私が書いたコードがあります:

#include <stdio.h>
#include <conio.h>

void main(void)  
{  
clrscr();  
int count = 0;  
int words = 0;  
int sentences = 0;  
char ch;

while ((ch = getch()) != '\n')
{
    printf("%c", ch);
    while ((ch = getch()) != '.')
    {
        printf("%c", ch);
        while ((ch = getch()) != ' ')
        {
            printf("%c", ch);
            count++;
        }
        printf("%c", ch);
        words++;
    }
    sentences++;
}

printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
   }

それは機能します(少なくとも文字数と単語数を数えます)。しかし、コードをコンパイルしてコンソール ウィンドウでチェックアウトすると、プログラムの実行を停止できません。エンターキーを入力するとすぐに終了するはずです。何故ですか?

4

7 に答える 7

4

ここにあなたの問題に対する解決策があります:

#include <stdio.h>
#include <conio.h>

void main(void)
{
    clrscr();  
    int count = 0;  
    int words = 0;  
    int sentences = 0;  
    char ch;

    ch = getch();
    while (ch != '\n')
    {
        while (ch != '.' && ch != '\n')
        {
            while (ch != ' ' && ch != '\n' && ch != '.')
            {
                count++;
                ch = getch();
                printf("%c", ch);
            }
            words++;
            while(ch == ' ') {
                ch = getch();
                printf("%c", ch);
            }
        }
        sentences++;
        while(ch == '.' && ch == ' ') {
           ch = getch();
           printf("%c", ch);
        }
    }

    printf("The number of characters are %d", count);
    printf("\nThe number of words are %d", words);
    printf("\nThe number of sentences are %d", sentences);
    getch();
}

コードの問題は、最も内側の while ループがすべての文字を消費していたことです。そこに入ってドットまたは改行を入力すると、chは空白とは異なるため、そのループ内にとどまります。ただし、最も内側のループから出ると、ch が空白になり、常に '.' とは異なるため、2 番目のループでスタックしたままになるリスクがあります。および「\n」。私のソリューションでは、最も内側のループでのみ文字を取得するため、他のループでは、他の文字を続行するために空白とドットを「食べる」必要があります。

内側の 2 つのループでこれらの条件をチェックすると、コードが機能します。プリントの一部を削除したことに注意してください。

それが役に立てば幸い。

編集:入力内容を印刷する手順と、空白をチェックするための文++の後のwhileループの最後のチェックを追加しました。そうしないと、さらに1単語カウントされます。

于 2014-02-02T17:37:10.930 に答える
1

while ステートメントを使用して if ステートメントを簡単に実装できます。

bool flag = true;
while(IF_COND && flag)
{
    //DO SOMETHING
    flag = false;
}

if ステートメントを使用する単純なソリューションにプラグインするだけです。

例えば:

#include <stdio.h>
#include <conio.h>

void main(void)  
{  
    int count = 0;  
    int words = 1;  
    int sentences = 1;  
    char ch;

    bool if_flag;

    while ((ch = getch()) != '\n')
    {
        count++;
        if_flag = true;
        while (ch==' ' && if_flag)
        {
            words++;
            if_flag = false;
        }
        if_flag = true;
        while (ch=='.' && if_flag)
        {
            sentences++;
            if_flag = false;
        }
    }

    printf("The number of characters are %d", count);
    printf("\nThe number of words are %d", words);
    printf("\nThe number of sentences are %d", sentences);
    getch();
}
于 2014-02-02T17:18:19.983 に答える
1
#include <stdio.h>
#include <ctype.h>

int main(void){

int sentence=0,characters =0,words =0,c=0,inside_word = 0,temp =0;
// while ((c = getchar()) != EOF) 
while ((c = getchar()) != '\n') {
   //a word is complete when we arrive at a space after we 
  // are inside a word or when we reach a  full stop

    while(c == '.'){
        sentence++;
        temp = c;
        c = 0;
    }
     while (isalnum(c)) {
        inside_word = 1;
        characters++;
        c =0;
    }
    while ((isspace(c) || temp == '.') && inside_word == 1){
        words++;
        inside_word = 0;
        temp = 0;
        c =0;
    }
}
printf(" %d   %d   %d",characters,words,sentence);
return 0;
}

これでうまくいくはずです。

isalnum は、文字が英数字かどうかをチェックします。アルファベットまたは数字の場合、このプログラムの文にランダムな ASCII 文字は期待できません。

isspace 名前が示すように、スペースを確認してください

これには ctype.h ヘッダーが必要です。または追加できます

   while(c == ' ') and whie((c>='a' && c<='z') || (c >= 'A' && c<='Z') 

isalpace と isalnum を使用したくない場合は、選択しますが、エレガントではなくなります :)

于 2014-02-02T17:25:41.263 に答える
1

問題は、外側の while ループの状態が原因だと思います。改行文字 '\n' をチェックし、見つかったらすぐにループを終了します。次の条件でwhileループにコードを含めることができます

while((c=getchar())!=EOF)

これは、ユーザーが Ctrl+z を押すと入力の受け取りを停止します

お役に立てれば..

于 2014-02-02T17:15:59.410 に答える
0

コードの問題は、各ループで文字を消費することです。'\n' は for 文の単語をスキャンするループによって消費されるため、外側のループはそれを認識しません。

問題の可能な解決策は次のとおりです。

int sentences = 0;
int words = 0;
int characters = 0;

int in_word = 0; // state of our parser

int ch;
do
{
    int end_word = 1; // consider a word wil end by default
    ch = getch();
    characters++; // count characters
    switch (ch)
    {
    case '.':
        sentences++; // any dot is considered end of a sentence and a word
        break;
    case ' ': // a space is the end of a word
        break;
    default:
       in_word = 1;  // any non-space non-dot char is considered part of a word
       end_word = 0; // cancel word ending
    }

    // handle word termination
    if (in_word and end_word) 
    {
        in_word = 0;
        words++;
    }

} while (ch != '\n');

これらの構文解析の問題に対する一般的なアプローチは、一度に 1 文字を読み取り、この文字がトリガーできるすべての可能な遷移に反応する有限状態マシンを作成することです。

この例では、マシンは現在単語を解析しているかどうかを記憶する必要があるため、最初に終端のスペースまたはドットが検出された場合にのみ 1 つの新しい単語がカウントされます。

このコードでは、簡潔にするためにスイッチを使用しています。それを if...else if シーケンスに置き換えて、先生を喜ばせることができます :)。

先生が while ループのみを使用するように強制した場合、先生はばかげたことをしたことになります。他の条件式を含まない同等のコードは、より重く、理解しにくく、冗長になります。

一部の人々はそれが重要であると考えているように思われるため、考えられる解決策の 1 つを次に示します。

int sentences = 0;
int words = 0;
int characters = 0;

int in_word = 0; // state of our parser
int ch;

// read initial character
ch = getch();

// do it with only while loops
while (ch != '\n')
{
    // count characters
    characters++;

    // count words
    while (in_word)
    {
        in_word = 0;
        words++;
    }

    // skip spaces
    while (ch == ' ')
    {
        ch = -1;
    }

    // detect sentences
    while (ch == '.')
    {
        sentences++;
        ch = -1;
    }

    // detect words
    while ((ch != '\n')
    {
        word_detected = 1;
        ch = -1;
    }

    // read next character
    ch = getch();
}

基本的に、人為的で不自然なプログラミング方法である に if (c== xxx) ...置き換えることができます。while (c== xxx) { c = -1; ... }

運動は愚かなやり方を助長するべきではありません、私見です。
ですから、先生が尋ねたことをあなたが誤解したのではないかと思います。
明らかに、whileループを使用できる場合は、ifステートメントも使用できます。

ループだけでこの演習を行おうwhileとしても無駄であり、実際のパーサー コードとほとんどまたはまったく関係のない結果になります。

于 2014-02-02T16:54:59.140 に答える