#include <cs50.h>
#include <stdio.h>

int count_letters(string text);
int count_words(string text);
int count_sentences(string text);

int main(void)
{
    string text = get_string("Type in the text: ");

    int n1 = count_letters(text);
    int n2 = count_words(text);
    int n3 = count_sentences(text);

    printf("Letters: %i\n", n1);
    printf("Words: %i\n", n2);
    printf("Sentences: %i\n", n3);
}


int count_letters(string text)

{
    int letters = 0;
    for (int i = 0; i < text[i]; i++)
    {
        if (text[i] >= 'a' && text[i] <='z')
        {
            letters++;
        }
        else if (text[i] >= 'A' && text[i] <= 'Z')
        {
            letters++;
        }
        else
        {
            letters = letters + 0;
        }
    }
    return letters;
}


int count_words(string text)
{
    int words = 1;
    for (int i = 0; i < text[i]; i++)
    {
        if (text[i] == ' ')
        {
            words++;
        }
        else
        {
            words = words + 0;
        }
    }
    return words;
}

int count_sentences(string text)
{
    int sentences = 0;
    for (int i = 0; i < text[i]; i++)
    {
        if (text[i] == '!' || text[i] == '?' || text[i] == '.')
        {
            sentences++;
        }
        else
        {
            sentences = sentences + 0;
        }
    }
    return sentences;
}

当我运行这个程序并输入例如:"aa aa aa aa aa aa aa bb."它返回正确的值,即字母= 20,单词= 10,句子= 1.

然而,当我try 输入"AAA BBB"时.它看起来像是在文本[26]处进行迭代.即,它返回字母=27,单词=9,句子=0.

对可能导致这一问题的原因以及如何修复有什么建议吗?谢谢.

推荐答案

我试用了您的代码,主要问题在于上限值的"for"循环测试.为了说明这个移动目标问题,我添加了一个"printf"语句来跟踪为"i<;Text[i]"判断的值是如何变化的,并最终在各种计数中产生不希望看到的结果.

int count_letters(char *text)

{
    int letters = 0;
    for (int i = 0; i < text[i]; i++)
    {
        printf("i: %d  text[i]: %d  value for text[i + 1]: %d\n", i, text[i], text[i+1]);

使用较长的句子示例执行您的代码会产生以下输出.

craig@Vera:~/C_Programs/Console/Sentences/bin/Release$ ./Sentences 
Type in the text: aaa aaa aaa aaa aaa aaa aaa aaa aaa bbb.
i: 0  text[i]: 97  value for text[i + 1]: 97
i: 1  text[i]: 97  value for text[i + 1]: 97
i: 2  text[i]: 97  value for text[i + 1]: 32
i: 3  text[i]: 32  value for text[i + 1]: 97
i: 4  text[i]: 97  value for text[i + 1]: 97
i: 5  text[i]: 97  value for text[i + 1]: 97
i: 6  text[i]: 97  value for text[i + 1]: 32
i: 7  text[i]: 32  value for text[i + 1]: 97
i: 8  text[i]: 97  value for text[i + 1]: 97
i: 9  text[i]: 97  value for text[i + 1]: 97
i: 10  text[i]: 97  value for text[i + 1]: 32
i: 11  text[i]: 32  value for text[i + 1]: 97
i: 12  text[i]: 97  value for text[i + 1]: 97
i: 13  text[i]: 97  value for text[i + 1]: 97
i: 14  text[i]: 97  value for text[i + 1]: 32
i: 15  text[i]: 32  value for text[i + 1]: 97
i: 16  text[i]: 97  value for text[i + 1]: 97
i: 17  text[i]: 97  value for text[i + 1]: 97
i: 18  text[i]: 97  value for text[i + 1]: 32
i: 19  text[i]: 32  value for text[i + 1]: 97
i: 20  text[i]: 97  value for text[i + 1]: 97
i: 21  text[i]: 97  value for text[i + 1]: 97
i: 22  text[i]: 97  value for text[i + 1]: 32
i: 23  text[i]: 32  value for text[i + 1]: 97
i: 24  text[i]: 97  value for text[i + 1]: 97
i: 25  text[i]: 97  value for text[i + 1]: 97
i: 26  text[i]: 97  value for text[i + 1]: 32
i: 27  text[i]: 32  value for text[i + 1]: 97
i: 28  text[i]: 97  value for text[i + 1]: 97
i: 29  text[i]: 97  value for text[i + 1]: 97
i: 30  text[i]: 97  value for text[i + 1]: 32
i: 31  text[i]: 32  value for text[i + 1]: 97
i: 32  text[i]: 97  value for text[i + 1]: 97
i: 33  text[i]: 97  value for text[i + 1]: 97
i: 34  text[i]: 97  value for text[i + 1]: 32   <--- This is point where the subequent "for" loop test will exit.
Letters: 27
Words: 9
Sentences: 0

在注明的点上,"i"的下一个值将是"35",并将与文本[i]的值进行比较,后者将是"32"(空格的ascii值).因此,循环在该点终止.

使用"I<;Text[i]"将不是适当的测试.最终,在解析字符串时,通常需要获取字符串的长度,然后将该值用作将要进行的任何字符测试的限制.此外,正在进行的字符测试非常正确;但是,现在可能是熟悉标准"C"包含文件中可用的字符函数的好时机,特别是"ctype.h".

下面是利用字符串和字符功能的代码的重构版本.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define SIZE 200

int count_letters(char *text);
int count_words(char *text);
int count_sentences(char *text);

int main(void)
{
    char text[SIZE];                    /* Utilizing conventional character array definition - do not have CS50 */

    printf("Type in the text: ");       /* Utilizing conventional string acquisition - do not have CS50         */
    fgets(text, (SIZE - 1), stdin);

    for (int i = 0; i < SIZE; i++)
    {
        if (text[i] == '\n')            /* Remove newline character that is returned with fgets function        */
        {
            text[i] = '\0';
            break;
        }
    }

    int n1 = count_letters(text);
    int n2 = count_words(text);
    int n3 = count_sentences(text);

    printf("Letters: %d\n", n1);
    printf("Words: %d\n", n2);
    printf("Sentences: %d\n", n3);
}

int count_letters(char *text)

{
    int letters = 0;
    for (int i = 0; i < strlen(text); i++)  /* Standard string length function  */
    {
        if (isalpha(text[i]))               /* Alpha character identification function in ctype.h   */
            letters++;
    }
    return letters;
}

int count_words(char *text)
{
    int words = 1;
    for (int i = 0; i < strlen(text); i++)
    {
        if (text[i] == ' ')
            words++;
    }
    return words;
}

int count_sentences(char *text)
{
    int sentences = 0;
    for (int i = 0; i < strlen(text); i++)
    {
        if (text[i] == '!' || text[i] == '?' || text[i] == '.')
            sentences++;
    }
    return sentences;
}

需要注意的几点.

  • 因为我的系统上没有CS50库和文件,所以我重构了代码以利用字符数组的传统定义和输入数据的提示,但是如果您愿意的话,使用CS50字符串功能没有什么不对的.
  • 为了提供执行诸如获取正确的字符串长度("strlen()")和判断字符元素是否为字母字符("ispha()")等步骤所需的常规方法,添加了"string.h"和"ctype.h"包含文件.

进行这些更改后,以下是终端产生所需计数的测试输出.

craig@Vera:~/C_Programs/Console/Sentences/bin/Release$ ./Sentences 
Type in the text: aaa aaa aaa aaa aaa aaa aaa aaa aaa bbb.
Letters: 30
Words: 10
Sentences: 1
craig@Vera:~/C_Programs/Console/Sentences/bin/Release$ ./Sentences 
Type in the text: Now is the time for all good men to come to the aid of their country.
Letters: 53
Words: 16
Sentences: 1

需要注意的关键点是"for"循环的正确设置,特别是当它与极限测试有关时,要了解字符串(字符数组)的特性,并且"C"编程中内置的标准功能包括文件.此外,除了使用与CS50教程相关的学习工具外,深入研究其他教程也可能是有益的,因为它与循环(循环、While循环等)和字符数组有关.

C++相关问答推荐

VS代码';S C/C++扩展称C23真关键字和假关键字未定义

在为hashmap创建加载器时,我的存储桶指向它自己

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

为什么我可以在GCC的标签后声明变量,但不能声明Clang?

I2C外设在单次交易后出现故障

将变量或参数打包到 struct /联合中是否会带来意想不到的性能损失?

使用Open62541向OPCUA服务器发送读请求时内存泄漏

如何将两个uint32_t值交织成一个uint64_t?

生产者消费者计数器意外输出的C代码

向左移位3如何得到以字节为单位的位数?

C中的数组下标和指针算法给出了不同的结果

Leet代码运行时错误:代码不会在Leet代码上编译,而是在其他编译器中编译,如netbeans和在线编译器

不兼容的整数到指针转换传递';char';到类型';常量字符*

C: NULL>;NULL总是false?

为什么程序在打印每个数字之前要等待所有输入?

多行表达式:C 编译器如何处理换行符?

与 C 相比,C++ 中无副作用的无限循环的好处是 UB?

如何正确探测平台设备?

C 中类型说明符的顺序重要吗?

如何使用另一个 struct 变量初始化C struct 数组成员