我有以下代码:
qstn:
cout << "Input customer's lastname: ";
getline(cin, lname);
if (lname.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ") != string::npos) {
cout << "You can only input alpha here!\n";
cin.clear();
goto qstn;
} else if (lname.empty()) {
cout << "Please enter your firstname!\n";
cin.clear();
goto qstn;
}
int lnamel = lname.length();
int strl = str.length();
int is = 0;
for (int i = 1; i < strl;) {
i++;
is++;
if (lname[i] == lname[is] && lname[i] == ' ' || lname[0] == ' ') {
cin.clear();
cout << "Please input your lastname properly!\n";
goto qstn;
}
}
// next question here
我很难想到什么是避免这种情况的正确逻辑 goto声明,自从我上大学以来我一直在使用它,但有人在这里说 根本不使用它可能会破坏我的代码。
我尝试使用do while循环,但它不像goto那样流畅。
请帮忙!
答案 0 :(得分:5)
这是我喜欢使用的成语:
int i;
if (std::cin >> prompt("enter an integer: ", i))
{
std::cout << "Read user input: " << i << "\n";
} else {
std::cout << "Input failed (too many attempts). Eof? " << std::boolalpha << std::cin.eof() << "\n";
}
这里,prompt
是一个智能输入操纵器,负责处理解析错误或流故障并重试。
它非常通用,所以实际上做了很多事情,但你不需要指出所有选项。当操纵器插入流中时,它会转发到do_manip
成员:
template <typename Char, typename CharT>
friend std::basic_istream<Char, CharT>& operator>>(std::basic_istream<Char, CharT>& is, checked_input<T, Prompter>& manip) {
return manip.do_manip(is);
}
do_manip
处理所有逻辑而没有任何goto
s :):
std::istream& do_manip(std::istream& is) {
auto attempt = [this] { return infinite() || retries_ > 0; };
while (attempt()) {
if (!infinite())
retries_ -= 1;
prompter_(out_);
if (is >> value_) {
if (!run_validators(out_))
is.setstate(is.rdstate() | std::ios::failbit);
else
break;
} else {
out_.get() << format_error_ << "\n";
}
if (attempt()) {
is.clear();
if (flush_on_error_)
is.ignore(1024, '\n');
}
}
return is;
}
您可以看到在接受输入之前可以运行验证。
这是一个有点全面的演示:
<强> Live On Coliru 强>
int main() {
using namespace inputmagic;
int i;
if (std::cin >> prompt("enter an integer: ", i)
.retries(3)
.flush_on_error(false)
.format_error("I couldn't read that (Numbers look like 123)")
.output(std::cerr)
.validate([](int v) { return v > 3 && v < 88; }, "value not in range (3,88)")
.validate([](int v) { return 0 == v % 2; })
.validate([](int v) { return v != 42; }, "The Answer Is Forbidden")
.multiple_diagnostics())
{
std::cout << "Read user input: " << i << "\n";
} else {
std::cout << "Input failed (too many attempts). Eof? " << std::boolalpha << std::cin.eof() << "\n";
}
}
你可以看到它只接受有效的整数
在后续重试中输入数字21,42和10时,您会得到: live
enter an integer: 21
Value not valid
enter an integer: 42
The Answer Is Forbidden
enter an integer: 10
Read user input: 10
但是,如果您一直输入1: live
enter an integer: 1
value not in range (3,88)
Value not valid
enter an integer: 1
value not in range (3,88)
Value not valid
enter an integer: 1
value not in range (3,88)
Value not valid
Input failed (too many attempts). Eof? false
或者如果您从单行文件中读取: live
enter an integer: value not in range (3,88)
Value not valid
enter an integer: I couldn't read that (Numbers look like 123)
enter an integer: I couldn't read that (Numbers look like 123)
Input failed (too many attempts). Eof? true
答案 1 :(得分:2)
使用功能:
bool getLastName(string & lname,
string & str)
{
cout << "Input customer's lastname: ";
getline(cin, lname);
if (lname.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ")
!= string::npos)
{
cout << "You can only input alpha here!\n";
cin.clear();
return false;
}
else if (lname.empty())
{
cout << "Please enter your firstname!\n";
cin.clear();
return false;
}
int lnamel = lname.length();
int strl = str.length();
int is = 0;
for (int i = 1; i < strl;)
{
i++;
is++;
if (lname[i] == lname[is] && lname[i] == ' ' || lname[0] == ' ')
{
cin.clear();
cout << "Please input your lastname properly!\n";
return false;
}
}
return true;
}
我在这里完成的所有工作都是用goto
替换return false
s。如果程序到达函数的末尾,return true
。在while循环中调用函数:
while (!getLastName(lname, str))
{
// do nothing
}
这不仅会破坏代码,而且会将其分解为漂亮,小巧,易于管理的部分。这称为procedural programming。
答案 2 :(得分:0)
While循环看起来是你最好的选择。您可以使用continue关键字重做循环。
int incorrect = 0;
while(!incorrect) {
cout<<"Input customer's lastname: ";
getline(cin,lname);
if(lname.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ")!=string::npos)
{
cout<<"You can only input alpha here!\n";
cin.clear();
continue;
}
else if(lname.empty())
{
cout<<"Please enter your firstname!\n";
cin.clear();
continue;
}
int lnamel=lname.length();
int strl=str.length();
int is=0;
for(int i=1; i<strl;)
{
i++;
is++;
if(lname[i]==lname[is]&&lname[i]==' '||lname[0]==' ')
{
cin.clear();
cout<<"Please input your lastname properly!\n";
continue;
}
incorrect = 1;
}
答案 3 :(得分:0)
你需要使用一些do while循环 例如:
qstn:
cout<<"Input customer's lastname: ";
getline(cin,lname);
if(lname.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ")!=string::npos)
{
cout<<"You can only input alpha here!\n";
cin.clear();
goto qstn;
}
else if(lname.empty())
{
cout<<"Please enter your firstname!\n";
cin.clear();
goto qstn;
}
可以重写为:
int flag;
do{
flag = 1;
cout<<"Input customer's lastname: ";
getline(cin,lname);
if(lname.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ")!=string::npos)
{
flag = 0;
cout<<"You can only input alpha here!\n";
}
else if(lname.empty())
{
flag = 0;
cout<<"Please enter your firstname!\n";
}
cin.clear();
} while( flag !=1 );
随意使用布尔类型标志,它并不重要
答案 4 :(得分:0)
在我看来,你的代码缺乏明确的目的。
您显然不希望输入的字符串包含前导空格,也不希望包含多个连续空格。除此之外,只接受字母字符。
如果用户确实输入了多个连续的空格,我可能会忽略除第一个之外的所有空格。我可能会编写类似这样的代码:
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <sstream>
bool non_alpha(std::string const &s) {
return !std::all_of(s.begin(), s.end(), [](unsigned char c) { return std::isalpha(c) || std::isspace(c); });
}
std::string get_name(std::string const &prompt) {
std::string result;
std::string line;
do {
std::cout << prompt;
std::getline(std::cin, line);
} while (non_alpha(line));
std::istringstream words(line);
std::string word;
while (words >> word)
result += word + ' ';
return result;
}
int main() {
auto res = get_name("Please enter last name, alpha-only\n");
if (res.empty())
std::cout << "Oh well, maybe some other time";
else
std::cout << "Thanks Mr(s). " << res << "\n";
}
我很想考虑对非字母字符大致相同 - 而不是要求用户从头开始重新输入,假设这是一个错误而忽略它。