由于 getline(cin,s) 导致的 SIGABRT 错误

SIGABRT error due to getline(cin,s)

此代码在我的电脑上运行良好,但在在线判断 (Spoj) 上显示 SIGABRT。为什么?我认为问题在于 getline 它在我使用时被接受:

input format: 52 + 81 = machula or 5machula + 81 = 133

string s1,s2,s3;
cin>>s1;
cin.ignore(3);
cin>>s2;
cin.ignore(3);
cin>>s3;

但我想早点使用 substr 这需要我使用 getline

string s,s1,s2,s3;
//cin.ignore(INT_MAX,'\n');
getline(cin,s);
int p1=0,p2,p3,l1,l2,l3;
l1=s.find("+")-1;
p2=s.find("+")+2;
l2=s.find("=")-s.find("+")-3;
p3=s.find("=")+2;
l3=s.length()-s.find("=")-2;
s1=s.substr(p1,l1);
s2=s.substr(p2,l2);
s3=s.substr(p3,l3);

problem the OP are trying to solve 的输入规范指出:

The first line of the input file contains an integer T specifying the number of test cases. Each test case is preceded by a blank line.

OP对其的处理尝试可以概括为:

int t;
cin >> t;
cin.ignore(INT_MAX,'\n');
for(int u=0; u<t; u++)
{
    // ...
    std::string s;
    // cin.ignore(INT_MAX,'\n'); <-- another attempt
    getline(cin, s);
    // ... various operations involving s
}

这种方法的问题在于,虽然第一个 ignore 消耗了 cin >> t; 留在流缓冲区中的尾随换行符,但所有其他空行(仅包含换行符的行) getline 读取结果为空字符串,以下代码无法处理此类字符串。

比如std::basic_string::find找不到传过来的子串,就returnsstd::basic_string::npos,定义为

static const size_type npos = -1;

所以 p2 最终成为 1 并且调用 s.substr(p2,l2); 抛出一个 std::out_of_range 异常,因为我们正试图从一个零大小的字符串中提取一个子字符串, 从位置 1 开始.

添加注释掉的 ignore 行可以解决问题,但重写整个循环可能更好:

int t;
std::cin >> t;

int u = 0;
while ( u < t )
{
    // ...
    std::string s;
    getline(cin, s);
    if ( s.empty() )
        continue;
    // ... various operations involving s
    ++u;
}