问题是,正如标题所说,当我尝试将第二个向量元素传递给函数“solveSide”时。此向量包含两个字符串标记,从具有用户定义函数的较大字符串中获取。
该程序的工作方式如下:
问题出现在第二次调用“solveSide”中,因为程序在进入函数体之前崩溃。
如果我删除对“solveSide”函数的第二次调用,程序运行就好了。 如果我尝试输出vector的两个元素而不删除该行,它不会删除任何内容,但删除它后,它会输出两个元素。
在调试模式下,它会调用SIGSEGV,当它调用“std :: string :: _ M_mutate(unsigned int,unsigned int,unsigned int)”时(如调用堆栈所示)。
崩溃代码:
ifstream fin("ecuatii.in");
string ecuatie;
vector<string> sideSplit;
fin>>ecuatie;
sideSplit = stringSplit(ecuatie, "=");
fout<<sideSplit[0]<<"="<<sideSplit[1]<<"\n";
solveSide(sideSplit[0], leftCoeffSum, leftSum);
solveSide(sideSplit[1], rightCoeffSum, rightSum);
stringSplit函数:
vector<string> stringSplit(string str, const char *delim){
char *strCopy = new char [str.size()+1];
char *token;
char **tokens = new char* [(str.size()+1)*2];
unsigned tokenCount = 0;
strcpy(strCopy, str.c_str());
token = strtok(strCopy, delim);
while(token != NULL){
tokens[tokenCount++] = token;
token = strtok(NULL, delim);
}
vector<string> splits(tokenCount);
for(unsigned i = 0; i < tokenCount; ++i){
splits[i] = "";
splits[i] += tokens[i];
}
delete[] strCopy;
for(unsigned i = 0; i < tokenCount; ++i){
delete[] tokens[i];
}
delete[] tokens;
return splits;
}
stringChunkToFloat函数(应该使用“substr()”,现在我知道了):
float stringChunkToFloat(string str, unsigned posStart, unsigned posEnd){
char numberStr[20];
for(unsigned i = posStart; i <= posEnd; ++i){
numberStr[i-posStart] = str[i];
}
numberStr[posEnd-posStart+1] = '\0';
float number = atof(numberStr);
return number;
}
solveSide功能:
void solveSide(string &side, float &coeffSum, float &sum){
coeffSum = 0;
sum = 0;
unsigned posStart = side.find_first_of("+-", 1);
unsigned posEnd;
float currentNumber;
if(side.size() == 1){
if(side[0] == 'x'){
coeffSum = 1;
}else{
sum = atof(side.c_str());
}
return;
}
if(side[0] == 'x'){
coeffSum += 1;
}else if(side[1] == 'x' && side[0] == '-'){
coeffSum -= 1;
}else if(side[posStart-1] == 'x'){
currentNumber = stringChunkToFloat(side, 0, posStart-2);
coeffSum += currentNumber;
}else{
currentNumber = stringChunkToFloat(side, 0, posStart-1);
sum += currentNumber;
}
while(posStart != string::npos && posStart != side.size()){
posEnd = side.find_first_of("+-", posStart+1);
if(posEnd == string::npos){
posEnd = side.size();
}
if(side[posStart+1] == 'x'){
if(side[posStart] == '+'){
coeffSum += 1;
}else{
coeffSum -= 1;
}
}else if(side[posEnd-1] == 'x'){
currentNumber = stringChunkToFloat(side, posStart, posEnd-2);
coeffSum += currentNumber;
}else{
currentNumber = stringChunkToFloat(side, posStart, posEnd-1);
sum += currentNumber;
}
posStart = posEnd;
}
}
输入字符串:2.0x-4+5x+300=98x
答案 0 :(得分:4)
这个块不仅没有必要,而且带给你未定义行为的乐趣:
for(unsigned i = 0; i < tokenCount; ++i){
delete[] tokens[i];
}
考虑一下:你为tokens
分配了内存,而不是为自己的代币分配内存。毕竟,它们是指向您的标记化字符串的指针(std::strtok
具有破坏性)。
更好的是,如果可以避免,请不要使用原始内存:
vector<string> stringSplit(const string& str, const char *delim){
// Note: if you use C++11, you can use std::string::data()
// and don't need a copy to a vector, just take the string by value
vector<char> strCopy(str.begin(), str.end());
strCopy.push_back('\0');
vector<char*> tokens;
{
char * token = strtok(strCopy.data(), delim);
while(token != NULL){
tokens.push_back(token);
token = strtok(NULL, delim);
}
}
vector<string> splits(tokens.size();
for(unsigned i = 0; i < tokens.size(); ++i){
splits[i] = "";
splits[i] += tokens[i];
}
return splits;
}
答案 1 :(得分:1)
我发现了问题,这更像是一个思考错误:
当使用第二个字符串作为具有值solveSide
的参数调用函数98x
时,它会在搜索后搜索"+"
或"-"
个符号{ {1}}因为它找不到它,并且在startPos = npos
之前就进入了这种情况:
while
当它尝试从位置}else{
currentNumber = stringChunkToFloat(side, 0, posStart-1);
sum += currentNumber;
}
获取数字到0
时,它会抛出SIGSEGV(分段错误),因为它尝试从传递给npos
的字符串中访问未分配的内存
答案 2 :(得分:0)
使用vector更安全的方法是使用splits.pushback()方法和大小更安全得到spits.size()。始终在赋值给vector'成员之前检查vector.size()。