【问题标题】:Return the complete uppercase/lowercase converted string返回完整的大写/小写转换字符串
【发布时间】:2020-11-14 20:45:28
【问题描述】:

我正在编写一个程序,将字符串中的所有小写字母转换为大写字母,反之亦然。 但是,我发现我的程序无法返回整个转换后的字符串。

这是结果和我的程序代码。
输入:“a Survey”,输出:“A”。
输入:“Hello”,输出:“hELLO”。

#include <iostream>
#include <cstring>
using namespace std;
int main() {
    char inWord[50], outWord[50];
    int j = 0;
    cin.getline(inWord, 50);
    for (j = 0; j < strlen(inWord); j++)
    {
        //upper to lower
        if (inWord[j]>='A'&&inWord[j]<='Z')
            outWord[j] = inWord[j] + 'a' - 'A';
        //lower to upper
        else
            outWord[j] = inWord[j] + 'A' - 'a';
    }
    cout << outWord;
    return 0;
}

【问题讨论】:

  • ' ' 不在'A'-'Z' 范围内,而且很危险,它是'a' - 'A'
  • 不要混淆“从函数返回”和“打印到控制台”,这里的意思很明显,但总的来说,这两者是完全不同且不相关的
  • 请使用std::string 以避免出现一堆问题。
  • outword[j] 如果 inword 不在 [a-zA-Z] 范围内,则未设置 (0)。空格会导致该字符的默认 0 值保持不变,即空终止符表示已到达字符串的末尾。
  • 除了上述问题outWord不是nul终止,这是C字符串的要求。

标签: c++


【解决方案1】:

您需要考虑非字母字符。现在您将空格转换为 0,这是 cout 知道他需要停止从字符串读取的方式。这是一个简单的解决方案:

#include <iostream>
#include <cstring>
using namespace std;
int main() {
    char inWord[50], outWord[50];
    cin.getline(inWord, 50);
    for (int j = 0; j < strlen(inWord); j++)
    {
        char c = inWord[j];
        //upper to lower
        if (c>='A' && c<='Z')
            outWord[j] = c + 'a' - 'A';
        //lower to upper
        else if (c>='a' && c<='z')
            outWord[j] = c + 'A' - 'a';
        else
            outWord[j] = c;
    }
    cout << outWord;
    return 0;
}

如果你使用 C++ 编程,你可能应该用 std::string 替换那些 char[50],并避免使用命名空间 std:

#include <iostream>
#include <string>
int main() {
    std::string inWord, outWord;
    std::getline(std::cin, inWord);
    outWord.reserve(inWord.size());
    for (int i = 0; i < inWord.size(); i++)
    {
        char c = inWord[i];
        //upper to lower
        if (c>='A' && c<='Z') {
            outWord.push_back(c + 'a' - 'A');
        }
        //lower to upper
        else if (c>='a' && c<='z') {
            outWord.push_back(c + 'A' - 'a');
        }
        else {
            outWord.push_back(c);
        }
    }
    std::cout << outWord;
    return 0;
}

【讨论】:

    【解决方案2】:

    在ASCII中,

    ' ' 不在'A'-'Z' 范围内,因此采用第二个分支。 危险的是,它的值是'a' - 'A'。导致'\0'(C 字符串的 nul 终止符)。

    要解决这个问题,您必须处理第三种情况:

    const std::size_t size = strlen(inWord)
    for (std::size_t j = 0; j < size; j++)
    {
        //upper to lower
        if (inWord[j]>='A'&&inWord[j]<='Z')
            outWord[j] = inWord[j] + 'a' - 'A';
        //lower to upper
        else if (inWord[j]>='a'&&inWord[j]<='z')
            outWord[j] = inWord[j] + 'A' - 'a';
        else
            outWord[j] = inWord[j];
    }
    

    'a'-'z', 'A'-'Z' 不保证是连续范围(它适用于 Ascii,而不适用于 EBCDIC),因此您可以改用标准方法(即使它们的接口是错误的容易:( ):

    const std::size_t size = strlen(inWord)
    for (std::size_t j = 0; j < size; j++)
    {
        unsigned char c = static_cast<unsigned char>(inWord[j]);
    
        if (std::isupper(c))
            outWord[j] = static_cast<char>(std::tolower(c));
        //lower to upper
        else if (std::islower(c))
            outWord[j] = static_cast<char>(std::toupper(c));
        else
            outWord[j] = inWord[j];
    }
    

    【讨论】:

      【解决方案3】:

      如果要将所有字母转换为例如相反的大小写,则需要检查输入后字符串的大小写。 (例如通过计算大写字符)。
      现在您正在反转每个字母的大小写,因为您对循环中的每个字母进行 if else 比较。如果您只执行两个分支条件之一,它将转换为相同的情况。

      关于您可能希望如何改进您的风格的几句话:

      • 如果不使用循环外的 int,可以在 for 循环内定义 j for (int j = 0; j < strlen(inWord); j++){}
      • 'a' - 'A' 和 'A' - 'a'
        确实具有相同的绝对值,并且在循环期间不会改变,因此您可以在循环之前定义一个变量,然后在循环内部进行加减运算分别是循环。

      知道 C++ 在 ascii 的情况下将字符视为 8 位数字也很有用,这就是偏移计算起作用的原因: Link to an ASCII table

      【讨论】:

        猜你喜欢
        • 2016-01-25
        • 1970-01-01
        • 2011-01-16
        • 2018-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-30
        • 2017-05-18
        相关资源
        最近更新 更多