c - 为什么我的 C 函数无法处理标点符号?

标签 c char cs50 toupper isalpha

我正在尝试在 cs50 pset 第 2 周中做一个简单的拼字游戏,并且函数 intcompute_score(string word) 无法处理使用标点符号的输入,即使它是通过将所有输入转换为大写,使用更少的代码行与正确答案大致相同。下面是代码,但您真正需要查看的是我上面命名的函数:

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

// Points assigned to each letter of the alphabet
int POINTS[] = { 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10 };

int compute_score(string word);

int main()
{
    // Get input words from both players
    string word1 = get_string("Player 1: ");
    string word2 = get_string("Player 2: ");

    // Score both words
    int score1 = compute_score(word1);
    int score2 = compute_score(word2);

    // TODO: Print the winner
    if (score1 > score2)
    {
        printf("Player 1 wins!\n");
    }
    else if (score1 < score2)
    {
        printf("Player 2 wins!\n");
    }
    else
    {
        printf("Tie!\n");
    }
}

int compute_score(string word)
{
    // TODO: Compute and return score for string
    //Initialize score
    int score = 0;

    //Convert array of chars to uppercase and solve
    for (int i = 0, N = strlen(word); i < N; i++)
    {
        score = score + POINTS[toupper(word[i]) - 65];
    }
    return score;
}

在此之前,我在单个字符上使用 toupper 时遇到了麻烦,直到我观看了一个视频,该视频解释了使用 ASCII 图表的逻辑以及如何在讲座中迭代字符串中的字符。所以在 for 循环中,我写道:

//Convert array of chars to uppercase and solve
    for (int i = 0, N = strlen(word); i < N; i++)
    {
        score = score + POINTS[toupper(word[i]) - 65];
    }
    return score;

我决定将输入转换为全部大写,因为 Ag 等字符与其大写/非大写对应的值具有相同的值,我我认为将其转换为大写会更简单,这样逻辑就更简单、更快、更有效。在我的脑海中也更有意义。但是,当我使用 check50 时,除了带有标点符号的内容(最后有一个异常(exception))之外,所有内容都会变成绿色。以下是终端测试显示的内容:

terminal results

现在我根本不明白这一点,因为在我眼中,它几乎与正确答案完全相同,那就是:

for (int i = 0, N = strlen(word); i < N; i++)
{
    if (isupper(word[i]))
    {
        score += POINTS[word[i] - 'A'];
    }
    else if (islower(word[i]))
    {
        score += POINTS[word[i] - 'a'];
    }
}

我不知道为什么它不起作用。我认为出于某种原因,它正在对标点符号进行评分。但这没有意义,因为由于 toupper 被设计为仅适用于字母字符,因此它应该排除特殊字符,将其值呈现为零。有人对出了什么问题有什么建议吗?

最佳答案

… toupper is designed to only work with alphabetical characters, it should be excluding special characters, rendering their value to zero.

toupper 不会更改非字母字符。 toupper('!') 的计算结果与 '!' 相同,而不是零。 toupper 在 C 2018 76.4.2.2 中指定,其中第 3 段表示(添加粗体):

If the argument is a character for which islower is true and there are one or more corresponding characters, as specified by the current locale, for which isupper is true, the toupper function returns one of the corresponding characters (always the same one for any given locale); otherwise, the argument is returned unchanged.

即使 toupper 确实为非字母字符生成零,您的表达式 POINTS[toupper(word[i]) - 65] 也会计算为 POINTS[0 - 65],这不是您想要的。 (另外,'A'千万不要写成65,除非是在字符集之间转换等特殊情况。在普通源代码中,使用'A' > 为“A”的代码。)

您必须编写代码来测试非字母字符,而不是添加到它们的分数中。

(另请注意,使用 x - 'A' 并不是将字母转换为 0 到 25 之间的值的完全可移植方式,因为 C 标准不要求字母的字符代码是连续的。对于简单的学生项目和您知道使用 ASCII 的情况来说是可以的,但完全可移植的解决方案需要额外的工作。)

关于c - 为什么我的 C 函数无法处理标点符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75801828/

相关文章:

c - 了解 socket() 输出

循环创建、连接信号到按钮

c - C语言新手;在 for 循环中使用 pow()

c - 使用trie的Load的Pset5实现

c - 编译相同的源代码如何生成不同的目标文件?

c - ENOMEM 来自 popen() 的 system(),同时有足够的内存

c - C 中无符号字符数组的带引号的初始值设定项

JAVA - 使用 set 类创建构造函数、调用 Set 和替换字符串中的字符

c++ - Char数据类型和while循环

c - 如何用C计算ISBN?