我在 C++ 中正确使用 isalpha() 函数吗?
Am I using isalpha() function in c++ correctly?
我正在开发一个具有注册系统的程序,您可以在其中注册新成员。
为了提供一些上下文,您注册的名称必须与现有名称不同,只能是一个单词,并且在保存到文件之前变成全部大写。为了避免文件处理中可能出现的错误,我只希望用户名是字母,没有数字或特殊字符。
因为我想避免前导和尾随白色space用户可能不小心输入,所以我决定将正在注册的新用户名存储到一个字符数组中newName
,但我就是想不通如何正确地遍历 char 数组以检查任何数字或特殊字符,以便我可以要求用户输入正确的用户名。我已经尝试使用 isalpha()
函数的不同循环变体,但还没有找到任何东西。
这是我的代码部分,无论我输入包含 numbers/special 个字符还是仅包含字母的用户名,它现在只显示 "sorry, wrong username"
:
char newName[80];
bool valid;
do {
valid = true;
std::cin >> newName;
std::cin.sync();
for (int i = 0; i < 80; i++) {
if (!std::isalpha(newName[i]))
valid = false;
else
valid = true;
}
if (!valid)
std::cout << "Sorry, wrong username." << std::endl;
} while (!valid);
for (int i = 0; i < 80; i ++) {
if (newName[i] != '[=10=]')
newName[i] = toupper(newName[i]);
else
break;
}
for (int i = 0; i < nameList.size(); i++) {
if (nameList.at(i) == newName) {
std::cout << "Sorry, this name already exists. If you are registering a new member, please enter a new name for them." << std::endl;
validName = false;
break;
}
if (nameList.at(i) != newName)
validName = true;
}
主要问题是您对字符串使用了 C-Style char[]
。在 C++ 中,我们对字符串使用 std::string
数据类型。 std::string
与-Style 字符串相比更优越,很难理解,为什么有人仍然想使用旧的东西。
因此,您遇到了现在面临的问题。您正在使用魔术常量 80 来定义 char 数组。您还在循环中使用硬编码的数字 80,这样如果您在一个地方更改了 80,您可能会在其他地方忘记它。 运行 惹上麻烦了。
然后,接下来,这就是您问题的根本原因,如果您输入短于 80 个字符的名称,将会发生什么。
示例:您输入 'Mike'。这是 4 个字母和一个尾随 0。因此,总共 5 个字符。在这 5 个字母之后,在这 5 个相关字母之后的剩余数组位置将出现随机垃圾。
但是你的循环 运行 总是直到 80。所以,在检查了前几个正确的字符之后,你将继续检查垃圾。然后你在第一个循环中得到随机结果。
如果你想解决这个问题,那么你还应该使用 C 风格的 strlen
函数来获取字符串的长度。然后你应该循环到这个值。
类似于:
int length = strlen(newName);
for (int i = 0; (i < length) and (i < 80); i++) {
这将解决您的问题。
但再次推荐:请考虑使用std::string
我正在开发一个具有注册系统的程序,您可以在其中注册新成员。
为了提供一些上下文,您注册的名称必须与现有名称不同,只能是一个单词,并且在保存到文件之前变成全部大写。为了避免文件处理中可能出现的错误,我只希望用户名是字母,没有数字或特殊字符。
因为我想避免前导和尾随白色space用户可能不小心输入,所以我决定将正在注册的新用户名存储到一个字符数组中newName
,但我就是想不通如何正确地遍历 char 数组以检查任何数字或特殊字符,以便我可以要求用户输入正确的用户名。我已经尝试使用 isalpha()
函数的不同循环变体,但还没有找到任何东西。
这是我的代码部分,无论我输入包含 numbers/special 个字符还是仅包含字母的用户名,它现在只显示 "sorry, wrong username"
:
char newName[80];
bool valid;
do {
valid = true;
std::cin >> newName;
std::cin.sync();
for (int i = 0; i < 80; i++) {
if (!std::isalpha(newName[i]))
valid = false;
else
valid = true;
}
if (!valid)
std::cout << "Sorry, wrong username." << std::endl;
} while (!valid);
for (int i = 0; i < 80; i ++) {
if (newName[i] != '[=10=]')
newName[i] = toupper(newName[i]);
else
break;
}
for (int i = 0; i < nameList.size(); i++) {
if (nameList.at(i) == newName) {
std::cout << "Sorry, this name already exists. If you are registering a new member, please enter a new name for them." << std::endl;
validName = false;
break;
}
if (nameList.at(i) != newName)
validName = true;
}
主要问题是您对字符串使用了 C-Style char[]
。在 C++ 中,我们对字符串使用 std::string
数据类型。 std::string
与-Style 字符串相比更优越,很难理解,为什么有人仍然想使用旧的东西。
因此,您遇到了现在面临的问题。您正在使用魔术常量 80 来定义 char 数组。您还在循环中使用硬编码的数字 80,这样如果您在一个地方更改了 80,您可能会在其他地方忘记它。 运行 惹上麻烦了。
然后,接下来,这就是您问题的根本原因,如果您输入短于 80 个字符的名称,将会发生什么。
示例:您输入 'Mike'。这是 4 个字母和一个尾随 0。因此,总共 5 个字符。在这 5 个字母之后,在这 5 个相关字母之后的剩余数组位置将出现随机垃圾。
但是你的循环 运行 总是直到 80。所以,在检查了前几个正确的字符之后,你将继续检查垃圾。然后你在第一个循环中得到随机结果。
如果你想解决这个问题,那么你还应该使用 C 风格的 strlen
函数来获取字符串的长度。然后你应该循环到这个值。
类似于:
int length = strlen(newName);
for (int i = 0; (i < length) and (i < 80); i++) {
这将解决您的问题。
但再次推荐:请考虑使用std::string