为什么我的char函数不能正常工作?

问题描述 投票:-1回答:2

所以我还是C ++的新手,我正在尝试创建一个用户输入字符串的程序,然后我的函数以相反的情况返回字符串,全部小写,然后全部大写。相反,我只是继续收到字符串的第一个字母,总是大写。不确定我做错了什么。有什么建议?

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

char answer[255] = "";
int max = strlen(answer);

void reverse() {
    for (int i = 0; i < max; i++) {
        if (islower(answer[i])) {
            isupper(answer[i]);
        }
        else if (isupper(answer[i])) {
            islower(answer[i]);
        }
        else if (isspace(answer[i])) {
            isspace(answer[i]);
        }
    }
    cout << answer[max];
}

void lower() {
    for (int i = 0; i < max; i++) {
        if (isupper(answer[i])) {
            islower(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << answer[max];
}

void upper() {
    for (int i = 0; i < max; i++) {
        if (islower(answer[i])) {
            isupper(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << answer[max];
}

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    cin >> answer[max];

    reverse();
    lower();
    upper();

    system("pause");
    return 0;
}
c++
2个回答
0
投票

islower(char)只是一个内置函数来检查char是否是小写的。与isupper相同。它不会改变角色的情况。

要转换为小写/大写,请使用tolower / toupper。这将返回转换后的字符中的字符。但是,重要的是您需要将返回的值分配给字符本身。

有关this answerislowerisuppertolower的更多清晰度,请参阅toupper

  • 而现在已经到了为什么它只打印第一个字符:正如@ user4581301在他的评论中提到的,

“cin”answer [max];将只读取一个字符因为答案[max]正好是一个字符,第一个字符。在C ++中你必须按顺序做事。例如,int max = strlen(answer); will根据当时该字符串中的内容提供答案。由于字符串早于一行初始化并包含空字符串,因此max将为0。

因此,你的cin应该是cin >> answer。但是,这将接受你的第一个字。为了接受包括空格在内的所有单词,请使用getline()。为了使用它,answer应该被声明为string answer而不是char数组。

这是你如何接受一个完整的句子:getline(cin,answer);

  • 而你的变量max会在一些编译器中给出错误的错误。这是因为using namespace std;。要避免这种情况,请将max重命名为其他内容,例如maxlen
  • 并找到answer的长度:如果你在接受来自用户的字符串后调用answer.length()而不是全局地执行它会更好。

您的工作代码应如下所示:

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

string answer;
int maxlen;

void reverse() {
    for (int i = 0; i < maxlen; i++) {
        if (islower(answer[i])) {
            answer[i] = toupper(answer[i]);
        }
        else if (isupper(answer[i])) {
            answer[i] = tolower(answer[i]);
        }
        else if (isspace(answer[i])) {
            answer[i]=' '; 
        }
    }
    cout << "Reversed string: " + answer << endl;
}

void lower() {
    for (int i = 0; i < maxlen; i++) {
        if (isupper(answer[i])) {
            answer[i] = tolower(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << "Lower case string: " + answer << endl;
}

void upper() {
    for (int i = 0; i < maxlen; i++) {
        if (islower(answer[i])) {
            answer[i] = toupper(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << "Upper case string: " + answer << endl;
}

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    getline(cin,answer);
    cout << "Original string: " + answer << endl;
    maxlen = answer.length();
    reverse();
    lower();
    upper();
    return 0;
}

随着输出:

Please enter a word, or a series of words:
ReVeRsAl UPPER aNd lower
Original string: ReVeRsAl UPPER aNd lower
Reversed string: rEvErSaL upper AnD LOWER
Lower case string: reversal upper and lower
Upper case string: REVERSAL UPPER AND LOWER

0
投票
cin >> answer[max];

将读取一个字符,因为answer[max]正好是一个字符,数组中的字符位于max

max是0因为你必须按顺序做事。例如,

int max = strlen(answer);

将提供当时达到这条线的answer的长度。由于字符串早先初始化了一行

char answer[255] = "";

并且包含一个空字符串,max将为0.这意味着answer[max]answer[0]代码中的任何内容都没有更改max,因此它将保持为0。

好吧,说我们改变一点而不是读一个字符,我们读作answer作为一个字符串。你需要

cin.getline(answer, sizeof(answer));

因为

cin >> answer; 

将读取一个以空格分隔的标记。一个词。您声明的目标是阅读多个单词。 istream::getline会将它找到的所有内容读入第一个参数直到行的末尾,或者它会查找第二个参数中指定的字符数减1(以便为字符串的空终止符保留空间)。 sizeof(answer)字面上是answer数组的大小,以字节为单位。我们使用字节大小的字符操作,因此字符数和字节数是相同的。如果使用多字节字符,必须格外小心。

这似乎是推荐使用std::stringstd::getline的好地方。它们会产生大量问题,例如可以读取的最大字符数,在绝大多数情况下都会消失。

我不会在这里使用它们,但因为作业可能有“No strings”政策。

所以现在我们有cin.getline(answer, sizeof(answer));读取用户的输入,我们可以努力获得max的大小。我们可以strlen,但我们也可以使用istream::gcount来获取getline读取的字符数。

main现在看起来像

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    cin.getline(answer, sizeof(answer));
    max = cin.gcount();

    reverse();
    lower();
    upper();

    system("pause");
    return 0;
}

在这一点上,整堆东西都可能出错。

由于可能与using namespace std;发生碰撞,max可能对std::max造成严重破坏。一般情况下,避免使用using namespace std;它可以通过浪费时间调试它可能引入的奇怪错误来恢复它为您节省的几个字母。

isupper(answer[i]);没有做任何有用的事情,正如其他人在评论中指出的那样。你要

answer[i] = toupper(static_cast<unsigned char>(answer[i])); 

请参阅Do I need to cast to unsigned char before calling toupper(), tolower(), et al.?,了解为什么那些疯狂且毫无意义的演员表可能是必要的。感谢HolyBlackCat引起我的注意。

自我指派如

answer[i] = answer[i];

一旦你停下来思考它就应该是显而易见的,这是毫无意义的。

同样

else if (isspace(answer[i])) {
    isspace(answer[i]);
 }

可能不是特别有用。如果answer[i]是一个空格,请将其设置为空格?它已经是一个空间了。它会做的是用空格替换其他形式的空格,制表符和回车符。 Newline已被getline选中。也可能需要类似于上面的toupper示例中使用的演员表。我还在读这个。

如上所述,

cout << answer[max];

没有效果。它打印出一个字符,如果max已经修复,answer[max]将终止null。而是打印出整个阵列。

cout << answer;

一般建议:

不要一次写很多代码。在编译和测试之前,先写几行,最多一个函数。如果你已经测试过了

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    cin >> answer[max];
    cout << answer;
}

您可能会立即看到数据未正确读取。并在继续之前修复它。通过允许错误构建,您可以更难找到任何一个错误。您可以正确修复错误,以找到另一个错误撤消或隐藏的修复程序。

避免使用全局变量。尝试将变量放在尽可能小的范围内。在这种情况下,将answermax移动到main并将它们作为参数传递给其他函数。这样可以更容易地跟踪谁设置了什么变量以及何时设置。它还有助于防止意外的Variable Shadowing

© www.soinside.com 2019 - 2024. All rights reserved.