【问题标题】:counting the number of sentences in a paragraph in c计算c中段落中的句子数
【发布时间】:2014-02-26 02:15:27
【问题描述】:

作为课程的一部分,我必须使用 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();
   }

它确实有效(至少计算字符和单词的数量)。但是,当我编译代码并在控制台窗口上检查它时,我无法让程序停止运行。它应该在我输入回车键后立即结束。这是为什么呢?

【问题讨论】:

  • 想想问题的本质。您编写了一个三重嵌套循环,其中问题似乎需要一个循环。尝试仅使用一个循环和一些 if 语句(或 switch)来对不同类型的字符执行不同的操作。
  • 就是这样。我知道(或至少认为我知道)如何使用 if 语句(或 switch)来做到这一点,但老师不希望我们使用它。只有当..
  • 附注:最后应该是int mainreturn 0
  • 您确定您的老师说不要使用条件句吗?从您的帖子中可以看出他不希望您使用函数。两个不同的东西,if else 不是函数
  • 在 if 语句之前会教你 while 循环,这似乎很奇怪。

标签: c while-loop char words text-segmentation


【解决方案1】:

这里有解决问题的方法:

#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 循环中最后检查以检查空白,否则它会多算一个单词。

【讨论】:

  • 我认为这些打印是必要的,因为现在它不打印任何空间。此外,当我按 Enter 键时,它仍然没有“结束”代码。
  • '.' 不打印。并且没有计数。
  • 对我来说,它会打印结果并在结束程序之前等待一个字符,因为最终的 getch()。
  • 你确定吗?我在 CodeBlocks 和 TurboC 中测试了你的代码,没有显示空格或打印输出。
  • 顺便说一句,您可以通过在每个 getch() 之后放置一个 printf 来克服打印所写内容的问题(即执行回显)(记住单行的 while 循环中的括号)和你删除 count++ 之前的那个。
【解决方案2】:
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");

【讨论】:

  • 谢谢。经过数小时的测试不同的东西,你是唯一真正有效的代码。是否可以在不使用 break 命令的情况下中断循环?或者这是否意味着更改整个代码?
  • @david 可以替代zvisofer的break方法。
【解决方案3】:

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

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

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

希望这会有所帮助..

【讨论】:

    【解决方案4】:

    您可以使用 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();
    }
    

    【讨论】:

    • 整个问题在于不使用ifs
    • 您使用的是布尔值。听起来很傻,但我的老师不想要这个。
    • 听起来确实如此。将其更改为 int。您使用的是整数,不是吗?
    【解决方案5】:
    #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,你可以选择,但它会不太优雅:)

    【讨论】:

    • @BLUEPIXY 谢谢你,修复了一切,有一些错误,编译和测试。
    【解决方案6】:

    您的代码的问题在于您在每个循环中都使用了字符。 '\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 循环进行此练习是徒劳的,并且会导致与真正的解析器代码几乎没有关系。

    【讨论】:

    • 如果允许他使用 if/else 和 switch 会容易很多,但他说:只使用 printf、getch() 和 while 循环
    • char ch; 应该是 int ch; 你应该为交换机添加一个 EOF 的案例。
    • @wildplasser 对于 int 可以,至于 EOF,呸,这仅适用于 TurboC,因此 EOF 不太可能出现。重点是说明解析器通常是如何工作的,而不会纠缠于细微的细节。
    • 即使那样我也必须使用 if 和 switch 语句,不是吗?我做不到。
    • 那样的话我只能同情了。周围有足够多可怕的程序员,我们不需要老师教愚蠢的做事方式:)。当我还是项目经理时,如果我的一个团队成员编写了一段类似的代码,我会狠狠地责骂他并要求 ihm 立即重写。
    【解决方案7】:

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

    输入:

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

    检查 OpenNLP

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

    http://opennlp.apache.org/

    【讨论】:

      猜你喜欢
      • 2015-06-02
      • 1970-01-01
      • 2015-08-19
      • 2014-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      相关资源
      最近更新 更多