c++ getline cin 问题

Posted

技术标签:

【中文标题】c++ getline cin 问题【英文标题】:c++ getline cin issue 【发布时间】:2011-07-07 04:36:22 【问题描述】:
 while (true)
 
    int read = recvData(clientSocket, buf, sizeof(buf));
    if(read == SOCKET_ERROR)
    
        cout<<"Connection with the server is lost. Do you want to exit?" << endl;
        string input;
        getline(cin,input);
        if(input == "yes")
            cout<<"test";
    
    if(read == SHOW )
    
        char *p = strtok(buf, " ");
        while (p) 
        
            cout<<p<<endl;
            p = strtok(NULL, " ");
        
    

    else if(read == SEND )
    
        UDPinfo* info = new UDPinfo;
        char *p = strtok(buf, " ");
        info->_IP = p;
        p = strtok(NULL, " ");
        info->_Port= p;
        info->_filePath = filePath;
        info->_UPDsock = UDPSocket;
        //Starting UDP send thread.
        _beginthread(UDPsendThread, 0, (void*)info);
    
  

在这个例子中,如果我得到一个套接字错误,我会问用户他是否想通过获取输入来退出程序。然后将该输入与其他值进行比较,在这种情况下,它是一个“是”字符串。但由于某种原因,即使我输入“是”,它也会跳过 if 检查。并打印“与服务器的连接丢失。您要退出吗?”再次。奇怪的是,如果我再次输入“是”,它就会起作用。我试图通过使用 cin.ignore(); 来修复它。和所有这些东西,但没有解决方案。

【问题讨论】:

这段代码至少在 gcc 上运行良好。你需要提供更多的东西。这是getline 在循环内吗? 对不起,我忘记了 while 循环。我编辑问题。 【参考方案1】:

好吧,如果您输入yes,您似乎没有任何退出循环的方法,它只是打印test 并继续其愉快的方式,试图读取更多数据。

如果你的意思是第一次输入yes时不打印test那么你需要临时改一下:

getline(cin,input);

到:

getline (cin, input);
cout << "[" << input << "]" << endl;

当您比较它时,尝试找出实际 in 缓冲区的内容。


不管怎样,这段代码(和你的非常相似)工作得很好:

#include <iostream>

int main (void) 
    while (true) 
        int read = -1;
        if (read == -1) 
            std::cout << "Connection lost, exit?" << std::endl;
            std::string input;
            getline (std::cin, input);
            std::cout << "[" << input << "]" << std::endl;
            if (input == "yes") 
                std::cout << "You entered 'yes'" << std::endl;
                break;
            
        
        std::cout << "Rest of loop" << std::endl;
    
    return 0;


您还应该意识到,您的逻辑存在漏洞。当您在缓冲区上执行 strtok 时,它会修改缓冲区并为您提供指向它的指针(即实际缓冲区)。它不会为您制作副本。

如果您随后将这些指针保存在 info 中并将其传递给另一个线程,同时您返回并将 more 信息读入该缓冲区然后是您的主线程,并且您将信息传递给的线程将发生冲突。很糟糕。

如果您必须使用strtok 获取信息,请确保您使用strdup 并将副本 传递给您的其他线程(记住在完成后释放它们)。大多数 C 实现都会有一个strdup(尽管它不是 ISO 标准)。如果您没有,请参阅here。

这个洞很有可能会导致你的奇怪行为。

解决此问题的最佳方法是更改​​这两行:

    info->_IP = p;
    info->_Port= p;

进入:

    info->_IP = strdup (p);
    info->_Port= strdup (p);

并记住 free 在你的另一个线程中完成这些内存分配(通常我不会提倡 C++ 的 malloc-type 操作,但是,因为你已经在使用字符缓冲区而不是字符串,这似乎是最简单的解决方案)。

【讨论】:

是的。我第一次输入“是”时,它没有打印“测试”。它还会跳过您发布的 cout 声明。 无论我尝试什么,它总是在第一次 getline 之后跳过下一行。 这真的很奇怪。它与我的代码完全相同,但由于某种原因我的代码不起作用。 记住标准输出是缓冲的。因此,仅将“测试”写入 cout 并不一定意味着它将被写入终端。在打印后刷新标准输出,或者使用标准错误 (cerr),因为它通常是无缓冲的。 @Sodved,是的,cout 被缓冲了。但是,OP 表示 connection lost 正在被再次打印,而没有干预 test。没有多少缓冲会导致:-)【参考方案2】:

或许可以试试:

cin.clear(); 
cin.ignore(INT_MAX,'\n');

因为听起来你可能有一个 \n 坐在 cin 缓冲区中(可能来自之前的 cin 操作)。上面的代码应该为 getline() 刷新 cin。

【讨论】:

我尝试了 cin.ignore、cin.clear、fflush 的所有可能组合,但仍然无法正常工作。 我不认为这可能是因为缓冲区......如果是它不会提示他输入......它会直接提取任何分隔符......并且循环会运行再次清除 cin 流...【参考方案3】:

它如何再次打印消息?我在这里看不到 while 循环。您在循环中发布的代码 sn-p 吗?

【讨论】:

好的,现在很清楚了。即使答案是“是”,您也不会退出循环。如果答案是肯定的,请使用 break 或 exit(0)。 不,这不是问题。问题是无论我尝试什么,它总是在第一次 getline 之后跳过下一行。所以即使我输入 if(input == "yes") break;它跳过了休息时间;【参考方案4】:

当人们发布代码时 - 想知道为什么它不起作用 - 我总是根据他们正在调用的函数的文档化 API 来查找他们对失败进行的检查。我很少找到它们。也没有任何努力追踪变量中的值。这里也一样。

string input;
getline(cin,input);
if (input == "yes")
    cout<<"test";

请考虑将其更改为:

string input;
if (getline(std::cin, input))
    std::cerr << "input [" << input.size() << "] '" << input << "'\n";
else
    std::cerr << "getline() was unable to read a string from std::cin\n";

那么,告诉我们你看到了什么......

【讨论】:

以上是关于c++ getline cin 问题的主要内容,如果未能解决你的问题,请参考以下文章

C++ 中 cin.getline() 的意外返回

c++ getline cin 问题

在 getline 之后在 C++ 中输入

关于 getline(cin, string) 的 C++ 快速问题

C++ getline() 不结束输入

cin,cin.get(),cin.getline(),getline()