C ++:std :: istream或sentry包围的奇怪行为 [英] C++: strange behavior with std::istream or sentry wrap around

查看:960
本文介绍了C ++:std :: istream或sentry包围的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个小型自订getline函式是以回答有关处理不同行结尾的问题。



这个函数工作得很好,直到它被编辑2天前,使它不跳过每行的前导空格。然而,在编辑之后,程序现在进入无限循环。对代码进行的唯一更改是下面这行更改了:

  std :: istream :: sentry se是)。 //当这行启用时,程序正确执行
//(没有无限循环),但是它跳过
//前导空格

到此:

  std :: istream :: sentry se (是真的); //在启用此行的情况下,程序将
//放入主函数的while循环
//内的无限循环中。

有人可以帮助我解释为什么程序无限循环,如果我们指定不跳过空格? / p>

这是完整的程序...

  std :: istream& ; safeGetline(std :: istream& is,std :: string& t)
{
t.clear

//使用std :: streambuf一个一个地读取流中的字符。
//这比使用std :: istream逐个读取它们要快。
//以这种方式使用streambuf的代码必须由sentry对象保护。
// sentry对象执行各种任务,
//如线程同步和更新流状态。

std :: istream :: sentry se(is,true);
std :: streambuf * sb = is.rdbuf();

for(;;){
int c = sb-> sbumpc();
switch(c){
case'\r':
c = sb-> sgetc();
if(c =='\\\
')
sb-> sbumpc();
return is;
case'\\\
':
case EOF:
return is;
默认值:
t + =(char)c;
}
}
}

  int main()
{
std :: string path =end_of_line_test.txt

std :: ifstream ifs(path.c_str());
if(!ifs){
std :: cout< 无法打开文件。 << std :: endl;
return EXIT_FAILURE;
}

int n = 0;
std :: string t;
while(safeGetline(ifs,t))//< ---- INFINITE LOOP发生在这里。 < ----
std :: cout<< \\\
Line< ++ n < :<< t<< std :: endl;

std :: cout<< \\\
文件包含< n<< 线。 << std :: endl;
return EXIT_SUCCESS;
}

我还试图在函数的开头添加这一行,但它没有差别...程序仍然在主函数的while循环中无限循环。

  is.setf(0, std :: ios :: skipws); 

文件 end_of_line_test.txt 是一个只包含以下内容的文本文件两行:

 1234//前导空白行
5678//引导空格


解决方案

问题是 safeGetLine 从不设置流的 eof()状态。



你使用 std :: istream :: sentry se(is); it 会尝试读取空格并发现你在结束-文件。



我相信你应该添加 is.setstate(ios_base :: eofbit)到函数的EOF条件。


This small custom getline function was given as an answer to a question about handling different line endings.

The function worked great until it was edited 2 days ago to make it not skip leading white spaces for each line. However, after the edit, the program now goes into an infinite loop. The only change done to the code was this following line which was changed from this:

std::istream::sentry se(is);  // When this line is enabled, the program executes
                              // correctly (no infinite loop) but it does skip
                              // leading white spaces

to this:

std::istream::sentry se(is, true); // With this line enabled, the program goes 
                                   // into infinite loop inside the while loop  
                                   // of the main function.

Can someone please help me explain why the program loops infinitely if we specify to not skip white spaces?

Here is the full program...

std::istream& safeGetline(std::istream& is, std::string& t)
{
    t.clear();

    // The characters in the stream are read one-by-one using a std::streambuf.
    // That is faster than reading them one-by-one using the std::istream.
    // Code that uses streambuf this way must be guarded by a sentry object.
    // The sentry object performs various tasks,
    // such as thread synchronization and updating the stream state.

    std::istream::sentry se(is, true);
    std::streambuf* sb = is.rdbuf();

    for(;;) {
        int c = sb->sbumpc();
        switch (c) {
        case '\r':
            c = sb->sgetc();
            if(c == '\n')
                sb->sbumpc();
            return is;
        case '\n':
        case EOF:
            return is;
        default:
            t += (char)c;
        }
    }
}

And here is a test program:

int main()
{
    std::string path = "end_of_line_test.txt"

    std::ifstream ifs(path.c_str());
    if(!ifs) {
        std::cout << "Failed to open the file." << std::endl;
        return EXIT_FAILURE;
    }

    int n = 0;
    std::string t;
    while(safeGetline(ifs, t))   //<---- INFINITE LOOP happens here. <----
        std::cout << "\nLine " << ++n << ":" << t << std::endl;

    std::cout << "\nThe file contains " << n << " lines." << std::endl;
    return EXIT_SUCCESS;
}

I also tried to add this line at the very beginning of the function but it made no difference... the program still looped infinitely in the while loop of the main function.

is.setf(0, std::ios::skipws);

The file end_of_line_test.txt is a text file which contains only the following two lines:

   "1234" // A line with leading white spaces
"5678"    // A line without leading white spaces

解决方案

The problem is that safeGetLine never sets the eof() state for the stream.

When you use std::istream::sentry se(is);, it will try to read whitespace and discover that you are at end-of-file. When you ask it not to look for whitespace, this never happens.

I believe you should add is.setstate(ios_base::eofbit) to the EOF condition for the function.

这篇关于C ++:std :: istream或sentry包围的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆