欢迎来到 SO。
如果你说你的程序“崩溃”,你也应该说如何它崩溃了
如果可能的话,引用显示它是如何崩溃的确切输出。许多
如果他们必须工作,可能能够提供帮助的人不会打扰
找出真正的问题是什么并解决它。
如果您的问题是关于编码问题的,就像您的问题一样,这也很重要
用您所使用的编程语言的名称标记您的问题
编码 - 在你的情况下是 C++。如果你不这样做,那么大多数 C++ 程序员
可以帮助根本不会注意到您的问题。 (我现在已经标记了你的
问题 C++。)
如果您使用编译型语言(如 C++)进行编程,它也是
有助于说明您正在使用什么编译器,以及该编译器的版本,
- 例如“GCC 4.7.2”、“MS VC++ 2012”——因为那时程序员可以尝试
使用相同的问题重现问题。编码很常见
问题在某种程度上取决于编译器或编译器版本
用过。
我在 Linux 上使用 GCC 4.7.2 和 clang 3.2 构建了您的程序,它执行了测试
当我从
控制台。
这让我猜测你说它“崩溃”是什么意思,而这
是我推测的:
我想你的意思可能是在你输入“6”后,程序以
错误诊断类似于:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
Aborted
如果我对此有误,请立即停止阅读。
如果我的判断是正确的,那么诊断会告诉您,在您的
调用a.substr(j,a.size()-1),索引j超出范围。
如果此时j 超出范围,那么它一定超出范围
上一行 j=a.find(" on ") 的结果。这只能意味着
a.find(" on ") 在a 的任何地方都找不到" on "。
查找std::string::find 的文档,例如
here
并阅读返回值:
如果未找到匹配项,则该函数返回 string::npos。
这是(size_t)-1,肯定超出范围。
接下来,如果a.find(" on ") 失败,那只能意味着
前一行getline(cin,a) 无法从cin 读取一行
包含" on "。我们知道这是真的!因为你说程序
在读取“6”并打印所需的换行符后立即崩溃。
所以getline(cin,a) 必须从控制台读取一行之后
“6”但之前“从旧马德拉斯路开始”。一个空行。这就是
如果你碰巧按下[Enter] 有点太长了
输入“6”,以便键盘缓冲区包含“6\n\n”,或者可能
“6\n\n\n”,而不仅仅是“6\n”。阅读后致电cin.ignore()
整数,只会消耗 一个 跟随字符,因为你是
接受以下默认参数:
std::istream& std::istream::ignore(std::streamsize n = 1, int delim = EOF)
正如我所说,您的程序对我来说很好。但我可以让它在
我在进入测试时按[Enter] 描述的方式太长了
case line-count - 第一次或第二次 - 或按
在我这样做之后再次[Enter]。无论哪种方式,我都在输入一个空行
到getline(cin,a)。
如果到目前为止我是对的,那么您的代码中的一个严重错误是 您不是
检查std::string::find() 在输入字符串上是否成功并且只是
假设它是。即使我说的不对,那也是严重的错误。
当用户的手指也停留时,您可以阻止程序崩溃
通过确保 cin 忽略 all 它可以忽略的换行符,长期坚持 [Enter]
在cin>>n 之后阅读。你必须看看下一个字符,如果有的话,
不提取它;检查它是否是换行符,如果是则提取它
并重复。将cin.ignore() 替换为:
for ( ;cin.peek() == '\n'; cin.ignore()){}
但是,这不会阻止您的程序以同样的方式崩溃,如果
用户碰巧错误地输入了不包含" on " 的路由行:
试试“Left On Domlur Flyover”。
要修复此错误,您必须检查 j=a.find(" on ") 是否成功并且
处理情况,当它不是。这是我认为是问题的完整解决方案,使用 GCC 4.7.2 构建
和铿锵3.2:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
vector <string> dr,rd;
string a,b;
size_t i,j,n;
cin>>n;
for ( ;cin.peek() == '\n'; cin.ignore()){}
for(i=0;i<n;i++)
{
a.clear(),b.clear();
getline(cin,a);
j=a.find(" on ");
if (j == string::npos) {
cout << "Invalid direction. Try again" << endl;
--i;
continue;
}
b=a.substr(j,a.size()-1);
a.resize(j);
dr.push_back(a);
rd.push_back(b);
}
for(i=0,j=rd.size()-1;i<rd.size();i++,j--)
{
cout<<dr[i]<<rd[j]<<endl;
}
cout<<endl;
}
return 0;
}
请注意,我还纠正了几个小缺陷:-
不需要任何全局变量。避免全局变量是一个好习惯
如果可能,并在尽可能小的范围内声明变量。
我已将i,j,n 的类型从int 更改为size_t。变量
用于保存some_class::some_method() 的返回值或
some_function() 的返回值,或与该返回值进行比较,
最好使用与返回值相同的类型声明以避免错误和
编译器警告:string::find() 和 vector::size() 返回 size_t,
这与int 不同。
P.S. 调查问题所在,无论是使用您的原始程序还是
我的,如果用户错误地输入整数输入之一,例如,
“y”或“6y”而不是“6”。你怎么能解决这个问题?