在不使用getline的情况下在c ++中读取stdin
Reading stdin in c ++ without using getline
我正在尝试转换程序(它是 vscode 和调试之间的桥梁)
这个程序是用C#写的。
它基于 o vscode-mono-debug
(https://github.com/Microsoft/vscode-mono-debug/blob/master/src/Protocol.cs)
嗯,
在 C# 中,我可以将标准输入作为流读取:
byte[] buffer = new byte[BUFFER_SIZE];
Stream inputStream = Console.OpenStandardInput();
_rawData = new ByteBuffer();
while (!_stopRequested) {
var read = await inputStream.ReadAsync(buffer, 0, buffer.Length);
if (read == 0) {
// end of stream
break;
}
if (read > 0) {
_rawData.Append(buffer, read);
ProcessData();
}
}
我试试这个:
#define _WIN32_WINNT 0x05017
#define BUFFER_SIZE 4096
#include<iostream>
#include<thread>
#include <sstream>
using namespace std;
class ProtocolServer
{
private:
bool _stopRequested;
ostringstream _rawData;
public:
void Start()
{
char buffer[BUFFER_SIZE];
while (!cin.eof())
{
cin.getline(buffer,BUFFER_SIZE);
if (cin.fail())
{
//error
break;
}
else
{
_rawData << buffer;
}
}
}
};
int main()
{
ProtocolServer *server = new ProtocolServer();
server->Start();
return 0;
}
输入:
Content-Length: 261\r\n\r\n{\"command\":\"initialize\",\"arguments\":{\"clientID\":\"vscode\",\"adapterID\":\"advpl\",\"pathFormat\":\"path\",\"linesStartAt1\":true,\"columnsStartAt1\":true,\"supportsVariableType\":true,\"supportsVariablePaging\":true,\"supportsRunInTerminalRequest\":true},\"type\":\"request\",\"seq\":1}
这正确地读取了前两行。由于协议没有把 \n 放在最后,它在 3 交互中卡在 cin.getline.
切换到 read() 会导致它停在 cin.read (),并且根本不读取任何内容。
我发现了一些类似的问题:
Whosebug Question
及例子:
Posix_chat_client
但我不需要它一定是异步的,但它适用于 windows 和 linux。
对不起我的英文
谢谢!
你想要的是无格式输入操作。
这是仅使用 std::iostream 的 1:1 翻译。唯一的 "trick" 是使用和尊重 gcount()
:
std::vector<char> buffer(BUFFER_SIZE);
auto& inputStream = std::cin;
_rawData = std::string {}; // or _rawData.clear(), e.g.
while (!_stopRequested) {
inputStream.read(buffer.data(), buffer.size());
auto read = inputStream.gcount();
if (read == 0) {
// end of stream
break;
}
if (read > 0) {
_rawData.append(buffer.begin(), buffer.begin() + read);
ProcessData();
}
}
我个人建议放弃 read == 0
检查以支持更准确的检查:
if (inputStream.eof()) { break; } // end of stream
if (!inputStream.good()) { break; } // failure
请注意 !good()
也捕获 eof()
,因此您可以
if (!inputStream.good()) { break; } // failure or end of stream
现场演示
#include <iostream>
#include <vector>
#include <atomic>
struct Foo {
void bar() {
std::vector<char> buffer(BUFFER_SIZE);
auto& inputStream = std::cin;
_rawData = std::string {};
while (!_stopRequested) {
inputStream.read(buffer.data(), buffer.size());
auto read = inputStream.gcount();
if (read > 0) {
_rawData.append(buffer.begin(), buffer.begin() + read);
ProcessData();
}
if (!inputStream.good()) { break; } // failure or end of stream
}
}
protected:
void ProcessData() {
//std::cout << "got " << _rawData.size() << " bytes: \n-----\n" << _rawData << "\n-----\n";
std::cout << "got " << _rawData.size() << " bytes\n";
_rawData.clear();
}
static constexpr size_t BUFFER_SIZE = 128;
std::atomic_bool _stopRequested { false };
std::string _rawData;
};
int main() {
Foo foo;
foo.bar();
}
打印(例如当读取它自己的源文件时):
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 92 bytes
我正在尝试转换程序(它是 vscode 和调试之间的桥梁) 这个程序是用C#写的。
它基于 o vscode-mono-debug
(https://github.com/Microsoft/vscode-mono-debug/blob/master/src/Protocol.cs)
嗯, 在 C# 中,我可以将标准输入作为流读取:
byte[] buffer = new byte[BUFFER_SIZE];
Stream inputStream = Console.OpenStandardInput();
_rawData = new ByteBuffer();
while (!_stopRequested) {
var read = await inputStream.ReadAsync(buffer, 0, buffer.Length);
if (read == 0) {
// end of stream
break;
}
if (read > 0) {
_rawData.Append(buffer, read);
ProcessData();
}
}
我试试这个:
#define _WIN32_WINNT 0x05017
#define BUFFER_SIZE 4096
#include<iostream>
#include<thread>
#include <sstream>
using namespace std;
class ProtocolServer
{
private:
bool _stopRequested;
ostringstream _rawData;
public:
void Start()
{
char buffer[BUFFER_SIZE];
while (!cin.eof())
{
cin.getline(buffer,BUFFER_SIZE);
if (cin.fail())
{
//error
break;
}
else
{
_rawData << buffer;
}
}
}
};
int main()
{
ProtocolServer *server = new ProtocolServer();
server->Start();
return 0;
}
输入:
Content-Length: 261\r\n\r\n{\"command\":\"initialize\",\"arguments\":{\"clientID\":\"vscode\",\"adapterID\":\"advpl\",\"pathFormat\":\"path\",\"linesStartAt1\":true,\"columnsStartAt1\":true,\"supportsVariableType\":true,\"supportsVariablePaging\":true,\"supportsRunInTerminalRequest\":true},\"type\":\"request\",\"seq\":1}
这正确地读取了前两行。由于协议没有把 \n 放在最后,它在 3 交互中卡在 cin.getline.
切换到 read() 会导致它停在 cin.read (),并且根本不读取任何内容。
我发现了一些类似的问题: Whosebug Question
及例子: Posix_chat_client
但我不需要它一定是异步的,但它适用于 windows 和 linux。
对不起我的英文
谢谢!
你想要的是无格式输入操作。
这是仅使用 std::iostream 的 1:1 翻译。唯一的 "trick" 是使用和尊重 gcount()
:
std::vector<char> buffer(BUFFER_SIZE);
auto& inputStream = std::cin;
_rawData = std::string {}; // or _rawData.clear(), e.g.
while (!_stopRequested) {
inputStream.read(buffer.data(), buffer.size());
auto read = inputStream.gcount();
if (read == 0) {
// end of stream
break;
}
if (read > 0) {
_rawData.append(buffer.begin(), buffer.begin() + read);
ProcessData();
}
}
我个人建议放弃 read == 0
检查以支持更准确的检查:
if (inputStream.eof()) { break; } // end of stream
if (!inputStream.good()) { break; } // failure
请注意 !good()
也捕获 eof()
,因此您可以
if (!inputStream.good()) { break; } // failure or end of stream
现场演示
#include <iostream>
#include <vector>
#include <atomic>
struct Foo {
void bar() {
std::vector<char> buffer(BUFFER_SIZE);
auto& inputStream = std::cin;
_rawData = std::string {};
while (!_stopRequested) {
inputStream.read(buffer.data(), buffer.size());
auto read = inputStream.gcount();
if (read > 0) {
_rawData.append(buffer.begin(), buffer.begin() + read);
ProcessData();
}
if (!inputStream.good()) { break; } // failure or end of stream
}
}
protected:
void ProcessData() {
//std::cout << "got " << _rawData.size() << " bytes: \n-----\n" << _rawData << "\n-----\n";
std::cout << "got " << _rawData.size() << " bytes\n";
_rawData.clear();
}
static constexpr size_t BUFFER_SIZE = 128;
std::atomic_bool _stopRequested { false };
std::string _rawData;
};
int main() {
Foo foo;
foo.bar();
}
打印(例如当读取它自己的源文件时):
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 128 bytes
got 92 bytes