如何不使用循环回到代码顶部?Flames程序goto输入异常问题
解决Flames程序中goto跳转后无法输入姓名的问题
我明白你遇到的困扰了——用goto实现重复输入功能后,第二次循环时用户没法正常输入姓名,直接被跳过了。这其实是输入缓冲区残留的换行符在捣乱,咱们一步步把问题解决掉:
问题根源
当你用cin>>t读取用户的Y/N选择时,用户输入完会按回车,这个回车对应的换行符\n会留在输入缓冲区里。下一次循环调用getline(cin, fname1)时,getline会把这个残留的换行符当作空行输入,直接跳过了用户的真实输入,看起来就像没法输入姓名了。
解决方案
在cin>>t之后,手动清理输入缓冲区里的残留字符,特别是那个换行符。可以用cin.ignore(numeric_limits<streamsize>::max(), '\n')来实现,它会把缓冲区里直到换行符的所有字符都清除干净。
另外,你的代码里还有几个小细节可以优化:
- 遍历字符串时,
i<=fname1.length()会导致越界(字符串索引是从0到length()-1),应该改成i<fname1.length() - "Aquaintance"拼写有误,正确拼写是"Acquaintance"
- 处理
total为0或取模后为0的情况,避免输出错误结果
下面是修复后的完整代码:
#include <iostream> #include <string> #include <limits> // 需包含此头文件使用numeric_limits using namespace std; int main() { start: system("cls"); char t; string fname1,fname2; int i,x,y,name1len=0,name2len=0,b,total,name1spc=0,name2spc=0; cout<<"Enter your full name: "; getline(cin,fname1); cout<<"Enter partners name: "; getline(cin,fname2); cout<<endl; // 转大写时修复越界问题 for(i=0;i<fname1.length();i++ ) { fname1[i]=toupper(fname1[i]); } for(i=0;i<fname2.length();i++) { fname2[i]=toupper(fname2[i]); } x=fname1.length(); y=fname2.length(); // 统计空格 for(i=0;i<x;i++) { if(fname1[i]==' ') { name1spc++; } } for(i=0;i<y;i++) { if(fname2[i]==' ') { name2spc++; } } // 计算共同字符(保留原有逻辑) for(i=0;i<fname1.length();i++) { for(b=0;b<fname2.length();b++) { if(fname1[i]==fname2[b]) { name1len++; break; } } } for(i=0;i<fname2.length();i++) { for(b=0;b<fname1.length();b++) { if(fname2[i]==fname1[b]) { name2len++; break; } } } name1len=name1len-name1spc; name2len=name2len-name2spc; total=name1len+name2len; // 处理特殊情况,避免错误输出 if(total == 0) { cout<<"No valid characters entered"<<endl; } else { if(total>6) { total=total%6; // 取模后为0对应FLAMES的第6个结果(Sweethearts) if(total == 0) total =6; } switch(total) { case 1: cout<<fname1<<" and "<<fname2<<" are Friends"<<endl; break; case 2: cout<<fname1<<" and "<<fname2<<" are Lovers"<<endl; break; case 3: cout<<fname1<<" and "<<fname2<<" are Acquaintance"<<endl; break; case 4: cout<<fname1<<" and "<<fname2<<" are Married"<<endl; break; case 5: cout<<fname1<<" and "<<fname2<<" are Enemies"<<endl; break; case 6: cout<<fname1<<" and "<<fname2<<" are Sweethearts"<<endl; break; } } cout<<"Would you like to enter another name? Y/N?"; cin>>t; // 清理输入缓冲区,清除残留的换行符 cin.ignore(numeric_limits<streamsize>::max(), '\n'); if(t=='Y' || t=='y') { goto start; } else if(t=='N' || t=='n') { cout<<"THANKS"<<endl; system("pause"); } else{ return 0; } }
关键修改点说明
- 添加
<limits>头文件,用于调用numeric_limits实现缓冲区清理 - 在
cin>>t之后添加cin.ignore(...),彻底清除输入缓冲区的残留内容 - 修复字符串遍历的越界问题(
i<=改为i<) - 修正"Acquaintance"的拼写错误
- 处理
total为0或取模后为0的情况,避免错误输出
这样修改后,goto跳转后用户就能正常输入姓名了。虽然goto能满足你不能用循环的需求,后续如果想优化代码,也可以考虑用函数封装输入和计算逻辑,用递归代替goto(这个场景下递归不会有栈溢出问题),不过目前的方案完全符合你的需求。
内容的提问来源于stack exchange,提问作者Sans
相关产品推荐
相关产品推荐

