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 问题的主要内容,如果未能解决你的问题,请参考以下文章