C++ - 使用结构数据类型将单词中的单个小写字符更改为大写,反之亦然
C++ - Changing single lowercase charachter in a word to uppercase and vice versa using struct data type
正如您从标题中看到的,我想将word中的小写字符更改为大写,反之亦然。
我还需要使用 struct object (在我的案例名称中)。
当我将 charachter 从小写更改为大写时出现问题,它仅在第一个单词中发生变化,而在第二个、第三个等中没有变化。我也在阅读文件
中的文字
这是输入文件
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
returns 可用字符数。它不包括空终止符,所以你不需要减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/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::isupper
、std::islower
、std::toupper
和 std::tolower
函数使您的代码更加明确。注意 std::string
是 std::basic_string<char>
的别名(其值类型是 char
),upper
和 lower
函数对 unsigned char
进行操作,所以你需要将 char
s 转换为 unsigned char
s:
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";
}
正如您从标题中看到的,我想将word中的小写字符更改为大写,反之亦然。 我还需要使用 struct object (在我的案例名称中)。 当我将 charachter 从小写更改为大写时出现问题,它仅在第一个单词中发生变化,而在第二个、第三个等中没有变化。我也在阅读文件
中的文字这是输入文件
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
returns 可用字符数。它不包括空终止符,所以你不需要减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/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::isupper
、std::islower
、std::toupper
和 std::tolower
函数使您的代码更加明确。注意 std::string
是 std::basic_string<char>
的别名(其值类型是 char
),upper
和 lower
函数对 unsigned char
进行操作,所以你需要将 char
s 转换为 unsigned char
s:
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";
}