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 将是一个空白,因此始终与 '.' 不同。和'\n'。由于在我的解决方案中,您只在最内层循环中获取一个字符,因此在其他循环中,您需要“吃掉”空白和点才能继续使用其他字符。

在两个内部循环中检查这些条件使代码工作。请注意,我删除了您的一些指纹。

希望能帮助到你。

编辑:我添加了打印您键入的内容的说明,并在句子 ++ 之后的 while 循环中进行最后一次检查以检查空白,否则它会多算一个单词。

于 2014-02-02T17:37:10.930 回答
1

我认为问题是因为你的外部 while 循环的条件。它检查换行符'\n',一旦找到一个,循环就会终止。您可以尝试将代码包含在具有以下条件的 while 循环中

而((c=getchar())!=EOF)

当用户按下 Ctrl+z 时,这将停止输入

希望这可以帮助..

于 2014-02-02T17:15:59.410 回答
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
int ch;
int flag;
while ((ch = getch()) != '\r'){
    ++count;
    flag = 1;
    while(flag && (ch == ' ' || ch == '.')){
        ++words;//no good E.g Contiguous space, Space at the beginning of the sentence
        flag = 0;;
    }
    flag = 1;
    while(flag && ch == '.'){
        ++sentences;
        flag=0;
    }
    printf("%c", ch);
}
printf("\n");
于 2014-02-02T18:10:43.517 回答
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');

解决这些解析问题的一般方法是编写一个有限状态机,它一次读取一个字符,并对这个字符可能触发的所有可能的转换做出反应。

在这个例子中,机器必须记住它当前是否正在解析一个单词,以便仅在第一次遇到终止空格或点时才计算一个新单词。

这段代码为了简洁使用了一个开关。您可以将其替换为 if...else if 序列以取悦您的老师 :)。

如果你的老师强迫你只使用 while 循环,那么你的老师做了一件愚蠢的事情。没有其他条件表达式的等效代码会更重、更难理解和冗余。

由于有些人似乎认为这很重要,因此这是一种可能的解决方案:

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 回答
0

所有这些解决方案都不正确。解决这个问题的唯一方法是创建一个使用自然语言处理的 AI程序并不容易做到

输入:

“这是一段关于图灵机的文章。艾伦·图灵博士发明了图灵机。它解决了一个问题,但有0.1%的变化被解决了。”

结帐 OpenNLP

https://sourceforge.net/projects/opennlp/

http://opennlp.apache.org/

于 2019-06-03T07:54:27.957 回答