C++ - 使用结构数据类型将单词中的单个小写字符更改为大写,反之亦然



正如您从标题中看到的,我想将单词中的小写字符更改为大写,反之亦然。 我还需要使用结构对象(在我的案例名称中(。 当我将字符从小写更改为大写时,我遇到了问题,它只在第一个单词中更改,而不会在第二个,第三个等单词中更改。我也在阅读文件中的单词

这是输入文件

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

我该如何解决这个问题? 有什么提示吗?

切线,

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

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

由于您要对容器(字符串(中的每个元素(字符(应用一些操作,因此这是<algorithm>库中std::transform的绝佳候选项。我在这里也使用了lambda表达式,这也是一个C++熟悉的好东西。

https://en.cppreference.com/w/cpp/algorithm/transformhttps://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<char>的别名(其值类型为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";
}

相关内容

最新更新