【问题标题】:C++ - Changing single lowercase charachter in a word to uppercase and vice versa using struct data typeC++ - 使用结构数据类型将单词中的单个小写字符更改为大写,反之亦然
【发布时间】:2020-08-28 14:42:36
【问题描述】:

从标题中可以看出,我想将 word 中的小写字符更改为大写,反之亦然。 我还需要使用结构对象(在我的例子中)。 当我将字符从小写更改为大写时,我遇到了一个问题,它只会在第一个单词中发生变化,而不是在第二个、第三个等等中发生变化。我也在从文件中读取单词

这是输入文件

Aayak Audi 
Ahmed Golf7 
Samed Golf5

这里是代码

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

struct pismaStr
{
    string ime;
    string objekat;
};


void malaVelikaSlova (string name)
{
    for (int i = 0; i < name.length()-1; i++)
    {
            if (name.at(i) >= 'A' && name.at(i) <= 'Z')
            name.at(i) += 32;
            else if (name.at(i) >= 'a' && name.at(i) <= 'z')
            name.at(i) -= 32;
            cout << name;
            break;
    }
}
int main()
{
    ifstream pismo;
    pismo.open("pismo.txt");
    ofstream novoPismo;
    novoPismo.open("novaSlova.txt");
    pismaStr stvari[200];
    int brojStvari = 0;

    while(pismo >> stvari[brojStvari].ime >> stvari[brojStvari].objekat)
    {
        brojStvari++;
    }
for (int i = 0; i < brojStvari; i++)
    {
       vector <pismaStr> vec = {pismaStr{stvari[i].ime}};
       for (auto obj : vec)
       {
        malaVelikaSlova (obj.ime);
       }
}

这是输出:

aayak
ahmed
samed

原来是:

Aayak 
ahmed 
samed

我希望它看起来像这样

aAYAK
sAMED
aHMED

我该如何解决这个问题? 有什么建议吗?

【问题讨论】:

标签: c++ arrays struct lowercase


【解决方案1】:

切线,

但这将是一个问题,是这条线

for (int i = 0; i < name.length()-1; i++)

这将从name[0] 循环到name[name.length() - 2]std::string::length 返回可用字符的数量。它不包括空终止符,所以你不需要减1。应该是

for (int i = 0; i < name.length(); i++)

你更大的问题

是循环末尾的break 语句(为清楚起见添加了缩进)

for (int i = 0; i < name.length()-1; i++)
{
    if (name.at(i) >= 'A' && name.at(i) <= 'Z')
        name.at(i) += 32;
    else if (name.at(i) >= 'a' && name.at(i) <= 'z')
        name.at(i) -= 32;
    cout << name;
    break;          // <--- this exits the loop entirely
}

您的break; 告诉程序立即退出循环。不再执行循环的进一步迭代。您的 cout 语句也在循环中。一旦您为每次迭代运行循环,您将输出转换的每个步骤。只输出一次(最后)你把它放在循环之外。如果你想遍历每个字符(你确实这样做了),你的最终代码看起来像

void malaVelikaSlova (string name)
{
    for (int i = 0; i < name.length() - 1; i++)
    {
        if (name.at(i) >= 'A' && name.at(i) <= 'Z')
            name.at(i) += 32;
        else if (name.at(i) >= 'a' && name.at(i) <= 'z')
            name.at(i) -= 32;
    }
    cout << name;
}

您可以更改的其他内容

您不需要对string 索引进行边界检查,因为您是根据string 长度循环的,并且它没有改变,因此您不需要额外的std::string::at 开销.您可以只使用索引运算符:

// name.at(i); // <-- no need to do this anywhere
name[i]        // <-- slightly faster

由于您正在对容器(字符串)中的每个元素(字符)应用一些操作,因此这是来自 &lt;algorithm&gt; 库的 std::transform 的绝佳候选者。我在这里也使用了一个 lambda 表达式,这对 C++ 来说也很适合熟悉。

https://en.cppreference.com/w/cpp/algorithm/transform
https://en.cppreference.com/w/cpp/language/lambda

void malaVelikaSlova (string name)
{
    std::transform(
        name.begin(),
        name.end(),
        [](char c) -> char
        {
            if (c >= 'A' && c <= 'Z')
                return c + 32;
            if (c >= 'a' && c <= 'z')
                return c - 32;
            return c; // <-- for all other characters
        }
    );
    
    std::cout << name << "\n";
}

您甚至可以利用std::isupperstd::islowerstd::toupperstd::tolower 函数使您的代码更加明确。请注意std::stringstd::basic_string&lt;char&gt; 的别名(其值类型为char),upperlower 函数在unsigned chars 上运行,因此您需要转换chars给unsigned chars:

https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/string/byte/tolower
https://en.cppreference.com/w/cpp/string/byte/toupper
https://en.cppreference.com/w/cpp/string/byte/isupper
https://en.cppreference.com/w/cpp/string/byte/islower

void malaVelikaSlova (string name)
{
    std::transform(
        name.begin(),
        name.end(),
        [](unsigned char c) -> unsigned char // <-- must convert to unsigned to be safe with upper/lower functions
        {
            if std::isupper(c) return std::tolower(c);
            if std::islower(c) return std::toupper(c);

            return c; // <-- for all other characters
        }
    );
    
    std::cout << name << "\n";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-29
    • 2022-01-08
    • 2020-07-24
    • 2014-02-15
    • 2017-01-26
    • 2016-02-24
    • 2013-09-21
    • 1970-01-01
    相关资源
    最近更新 更多