【问题标题】:Converting input from lowercase to uppercase using ASCII codes in C++在 C++ 中使用 ASCII 代码将输入从小写转换为大写
【发布时间】:2026-01-13 09:05:02
【问题描述】:

这是我在这里的第一个问题,所以我已尽我最大的努力使这个问题成为一个好问题。

我正在创建一个程序,它基本上接受用户输入并将所有字符转换为大写。我正在使用 for 循环使用相应的 ASCII 代码扫描小写字符。

我可以使用在代码中分配了字符串的字符数组来做到这一点:char text[] = "Text"

我希望能够接受用户输入并在字符数组中使用它。我尝试使用getline(cin,myString) 并用它分配字符数组,但它说数组必须用大括号括起来的初始化程序进行初始化。

我保持字符数组未初始化,因为在初始化数组时 sizeof(text) 没有给出正确的大小。我正在阅读有关使用指针的信息,但我对该主题仍然有些新鲜。下面是我写的代码:

int main() {
    // User input as a string
    char textConvert[] = "This text will be converted to uppercase.";
    cout << textConvert << endl;
    int endChar = sizeof(textConvert); //Only gives correct size when array is uninitialized
    for (int i = 0; i < endChar; i++) {
        if (textConvert[i] >= 97 && textConvert[i] <= 122) {
            textConvert[i] = textConvert[i] - 32;
        }
    }
    cout << textConvert;
    return 0;
}

【问题讨论】:

  • 字符常量都有对应的字符码值。例如,如果您使用 ASCII 'a' == 97。无需自己编写数字常量。
  • sizeof(textConvert) 不会像您认为的那样做。请改用strlen(textConvert)
  • sizeof 数组给出了整个数组的大小,而不仅仅是初始化部分的大小。您可能会想到std::strlen,尽管改用std::string 会更容易。
  • 你没有。我的意思是你不会硬编码 ASCII 字符,而是使用像 std::toupper 这样的标准函数。你也不需要你的循环,但可以使用std::transform。最后,不要使用magic numbers
  • 如果您正在尝试编写生产质量的国际化案例转换例程,那简直就是一场噩梦。 1)在土耳其,“i”的大写形式不是“I”而是“İ”(“I”的小写形式是无点的-i。2)在德国,“Maße”的大写形式是“群众”(五个字符而不是四个)。 3)更糟的是,“MESSEN”的小写形式是“messen”,(所以你需要知道SS是ss还是ß)。 4) 更糟糕的是,“MASSE”的小写形式可以是“Maße”或“Masse”,具体取决于单词的含义(大写,因为它们是名词)。

标签: c++ arrays string ascii


【解决方案1】:

问题:

我尝试使用 getline(cin,myString) 并用它分配字符数组,但它说数组必须用大括号括起来的初始化程序初始化

编译器在这里计算出所需数组的大小。

    char textConvert[] = "This text will be converted to uppercase.";

如果您想要用户输入,您需要分配一个数组并指定大小。

    char textConvert[50];

现在您可以读取一行并将其复制到数组中:

    std::string myString;
    std::getline(std::cin , myString);
    // Should check that the string is not more than 50 characters.
    std::copy(std::begin(myString), std::end(myString), textConvert);

但实际上根本没有必要这样做。只需使用std::string 并遍历字符串。最好避免像数组这样的 C 结构,并使用可以防止出错的 C++ 结构。

字符串大小

这不是一个好主意。

    int endChar = sizeof(textConvert);

这会测量数组的大小(而不是字符串的大小)。还有一个问题是数组很容易衰减为指针。当这种情况发生时,sizeof() 会给你指针的大小(可能是 4 或 8)而不是数组的大小。

要获取字符串的大小,请使用std::strlen() (include &lt;cstring&gt;)。

但实际上,您应该使用 std::string 的 C++ 版本的字符串,它自己管理内存并根据需要重新调整大小。

幻数

不喜欢使用幻数:

        if (textConvert[i] >= 97 && textConvert[i] <= 122) {
            textConvert[i] = textConvert[i] - 32;
        }

这些神奇的数字使代码难以阅读。您可以改用字符常量。

        if (textConvert[i] >= 'a' && textConvert[i] <= 'z') {
            textConvert[i] = textConvert[i] - ('a' - 'A');
        }

首选标准库

但不建议手动执行此操作。您应该使用标准库例程。

std::islower() .  // Check if a character is lower case.
std::toupper() .  // Convert a lowercase character to upper.

// include <cctype>

C++ 示例

试试这个:

#include <iostream>
#include <string>
#include <cctype>

int main()
{
    std::string   myString;
    while(std::getline(std::cin, myString)) {
        std::cout << "User Input: " << myString << "\n";
        for(auto& c: myString) {
            c = std::toupper(c);
        }
        std::cout << "Upper Case: " << myString << "\n";
    }
}

【讨论】:

  • 注解应该是toupper而不是toUpper,除非你绝对100%确定输入永远不会包含一个负值的char(几乎所有非ASCII 字符),那么您需要调用 std::toupper((unsigned char)c) 以避免未定义的行为。
【解决方案2】:

由于您处理的是 ASCII,因此您可以使用 std::toupper

无需编写自定义代码即可,标准库已涵盖。

【讨论】:

  • 涉及使用 Unicode 进行字符转换的问题通常与典型的 Unicode 字符编码不是固定宽度的事实有关。 C 库字符分类和操作函数仅适用于固定宽度字符集。特别是,它们不会处理 UTF-8。它们不是为此而设计的。
  • @PeteBecker 但他们也不会搞砸(他们可能不会将所有字符都大写,但不会将任何非 ASCII 字符大写)。这是因为任何取一比一char 的代码点都不在正确的范围内(即所有值都高于 127)
  • @MartinYork -- 我认为您遗漏了一个重要条件:ASCII 编码字符 的 C 分类和操作函数不会弄乱 UTF-8 编码人物。是的,大多数系统都使用 ASCII,但人们需要记住还有其他字符编码,并且他们可能有一天会遇到其中的一种。
  • @PeteBecker:是的。我支持我们的 Unicode 大师,并将与他们一起为世界统治而战。