我要输入一个文件,其中有一堆看起来像(* blah blah 4324 blah*) 23
的行。我试图删除括号之间的所有内容,并保留右括号后面的数字。
ifstream infile{"nums.txt"};
istream_iterator<string> infile_begin_iter {infile};
istream_iterator<string> eof;
vector<string> cleanNums {infile_begin_iter, eof};
for(int i=0; i<cleanNums.size(); i++){
int openParen=cleanNums[i].find("(*");
int closeParen=cleanNums[i].find("*)");
int distance=openParen-closeParen;
cleanNums[i].erase(closeParen, distance);
}
那段代码一直导致我的程序崩溃。我一直在这里寻找不同的东西,比如getline但我发现它只显示分隔符之前的所有内容
由于没有给出声明,我假设cleanNums
是std::vector<std::string>
。
现在到问题的代码片段:std::string::find()
返回size_type
(即通常是一些整数类型),用于找到给定字符串的位置。因此,openParen
和closeParen
将是找到左圆括号和右圆括号的索引——如果能找到它们的话。当使用size_type
类型的参数调用std::string::erase()时,将这些参数解释为要擦除的部分的起始索引和长度。然而,你叫它好像它在开始索引和最后索引的部分,将被删除。所以你要做的就是在传递给erase()之前,使用这两个索引来计算要删除的部分的长度。
还有另一个问题,可能是导致你的程序崩溃的问题:你没有检查两个std::string::find()
调用是否真的找到了一些东西。因为如果没有,那么它们返回std::string::npos
,这通常比大多数字符串的大小都大。这导致索引超出范围,并且std::string::erase()
抛出std::out_of_range
异常。砰,程序崩溃了!
那么,这里的教训是什么呢?如果你不确定,不要假设函数/方法需要什么样的参数,但是可以在你最喜欢的c++参考中查找。如果编译器不阅读它使用/编译的函数的文档,这是可以的,但是程序员应该阅读他/她至少使用一次的函数的文档。
您可以使用std::getline读取结束的')'
字符,然后您知道下一次读取将是您的号码:
int main()
{
std::ifstream ifs("test.txt");
std::string skip; // read in parts you want to skip
int value; // the value you want to keep
// skip data upto and past ')', then read number
while(std::getline(ifs, skip, ')') >> value)
std::cout << "found: " << value << 'n'; // output just the number
}