[英]Why am I getting a timeout(using sstream to parse list of integers separated by commas)?
给我一个由n个整数组成的输入字符串,用逗号分隔(例如“ 23,4,56”)。 我需要设置一个字符串流来表示此字符串,然后使用它来将每个整数扫描到向量中。 向量的元素(列表中的整数)最终将逐行输出。 我得到了main(),并且只负责编写parseInts(string str)。 由于某种原因,我一直在超时。 我猜想这是我的while循环中的事情,特别是关于我如何使用str()操纵sstream的事情,但是我无法弄清楚到底发生了什么。 我是sstream和C ++的新手,所以我们将不胜感激!
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
vector<int> parseInts(string str) {
int a; //will use this to hold the value of the 1st int in the sstream
stringstream list_initial; //will iterate over this sstream
list_initial.str(str); //set sstream to represent input str
vector<int> list_final; //will return this final vector for output in main
while (!list_initial.str().empty()){ //stop iterating at end of string
list_initial>>a; //store leading int value in a
list_final.push_back(a); //add a to end of vector
while (!ispunct(list_initial.str()[0])){ //get to next int in list
list_initial.str(list_initial.str().erase(0,1));
};
list_initial.str(list_initial.str().erase(0,1)); //erase leading comma
};
return list_final;
};
int main() {
string str;
cin >> str;
vector<int> integers = parseInts(str);
for(int i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
return 0;
}
您的函数实现可以得到真正的改善,但是如果您替换第二个while
行,请遵循您的逻辑:
while (!ispunct(list_initial.str()[0])){ //get to next int in list
通过这一点,添加一个长度检查:
while (list_initial.str().size() && !ispunct(list_initial.str()[0])){ //get to next int in list
,然后运行,运行良好并退出良好。
该循环永不中断,因为在过程结束时, ispunct()
函数从未将其参数!list_initial.str()[0]
识别为true:字符串list_initial.str()
目前为空,则0
索引不存在。
请查看cplusplus.com上的文档:
如果pos等于字符串长度,则const版本不会抛出异常(无抛出保证)。
否则,它将导致未定义的行为。
您的程序被冻结,因为它没有找到可能导致退出上述循环的正确条件。
谈论您的问题的重要一件事是: 为什么您自己找不到答案? 这个问题的答案如下:您没有尝试调试代码。
为了回答您的问题,我调试了您的代码,并通过在代码周围添加以下几行代码来快速发现问题,以查看发生了什么:
cout << "list_initial: " << list_initial.str() << endl;
您的代码示例,其中添加了调试语句::
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
vector<int> parseInts(string str) {
cout << "begin parseInts()" << endl; // ###### DEBUG ######
int a; //will use this to hold the value of the 1st int in the sstream
stringstream list_initial; //will iterate over this sstream
list_initial.str(str); //set sstream to represent input str
vector<int> list_final; //will return this final vector for output in main
cout << "begin while 1" << endl; // ###### DEBUG ######
while (!list_initial.str().empty()){ //stop iterating at end of string
list_initial >> a; //store leading int value in a
list_final.push_back(a); //add a to end of vector
cout << "a: " << a << endl; // ###### DEBUG ######
cout << "begin while 2" << endl; // ###### DEBUG ######
while (!ispunct(list_initial.str()[0])){ //get to next int in list
cout << "list_initial: " << list_initial.str() << endl; // ###### DEBUG ######
list_initial.str(list_initial.str().erase(0,1));
};
cout << "endwhile 2" << endl; // ###### DEBUG ######
list_initial.str(list_initial.str().erase(0,1)); //erase leading comma
};
cout << "endwhile 1" << endl; // ###### DEBUG ######
cout << "end parseInts()" << endl; // ###### DEBUG ######
return list_final;
};
int main() {
string str;
cin >> str;
vector<int> integers = parseInts(str);
cout << "begin for" << endl; // ###### DEBUG ######
for(int i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
cout << "end for" << endl; // ###### DEBUG ######
return 0;
}
这种(非常基础的)调试技术使您可以快速发现代码中的错误; 只需添加一些cout << ... << endl;
代码中的几行指出了一些重要信息,例如:“哪个循环导致冻结?”或“此变量的当前内容是什么?”。
如果你把cout << "Entering While loop 1" << endl;
之前,和cout << "Exiting While loop 1" << endl;
在每个可疑的循环之后,您可能会学到很多有关程序执行期间发生的情况的信息。
添加了此调试行后,您可以轻松地发现第二个循环永远循环着。 那么您可以将错误调查范围缩小到此循环。
流是一个抽象文件。 仅仅是一堆文字,例如cin >> n
就能将数字转换为整数,因此可以理解。
这是有关如何使用流的想法:
#include <cctype>
#include <ciso646>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
vector<int> parse_ints( const string& s )
{
vector<int> ints; // resulting list of ints
istringstream ss(s); // stream of ints separated by (non-digits)
int n; // each int extracted from the stream
// while input an int
while (ss >> n)
{
// save the int
ints.push_back(n);
// skip to next digit
while (ss and !isdigit(ss.peek())) ss.get();
}
return ints;
}
int main()
{
vector<int> xs = parse_ints( "2, 3 ,5; 7 : 11.13\t17abc21" );
for (int x : xs)
cout << x << " ";
cout << "\n";
}
这将产生:
2 3 5 7 11 13 17 21
注意我们如何简单地跳过我们不感兴趣的字符? 在这种情况下,我们跳过所有非数字字符。
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.