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

问题描述 投票:0回答:1

正如你从标题中看到的那样,我想把单词中的小写字母改为大写字母,反之亦然,而且我需要使用结构体对象(在我的情况下),我有一个问题,当我把小写字母改为大写字母时,它只在第一个单词中改变,而不是在第二个,第三个等。我还从文件中读取单词

以下是输入文件

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个回答
0
投票

切题。

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

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

因为你要对容器(字符串)中的每个元素(字符)进行一些操作,所以这是一个很好的候选方案。std::transform,来自 <algorithm> 库。我在这里还用了一个lambda表达式,这是一个伟大的太从C++熟悉。

https:/en.cppreference.comwcppalgorithmtransform https:/en.cppreference.comwcpplanguagelambda。

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::toupperstd::tolower 函数来使你的代码更加明确。注意 std::string 的别称。std::basic_string<char> (其价值类型为 char)、 upperlower 功能运行于 unsigned chars,所以你需要将这些数据转换为 charunsigned chars:

https:/en.cppreference.comwcppstringbasic_string。 https:/en.cppreference.comwcppstringbytetolower。 https:/en.cppreference.comwcppstringbytetoupper。 https:/en.cppreference.comwcppstringbyteisupper。 https:/en.cppreference.comwcppstringbyteislower。

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";
}
© www.soinside.com 2019 - 2024. All rights reserved.