[英]Using istringstream in C++
我有一些代碼使用 fork、execlp 和 wait 來創建兩個進程。 目標是能夠重復打印提示並讓用戶輸入命令,該命令最多包含 4 個參數/選項。
int main()
{
string command, argument;
istringstream iss(argument);
do
{
//prompt user for command to run
cout << "Enter command: ";
cin >> command >> argument;
int pid, rs, status;
//fork will make 2 processes
pid = fork();
if(pid == -1) { perror("fork"); exit(EXIT_FAILURE); }
if(pid == 0) {
//Child process: exec to command with argument
//C_str to get the character string of a string
rs = execlp(command.c_str(), command.c_str(), argument.c_str(), (char*) NULL);
.
if (rs == -1) { perror("execlp"); exit(EXIT_FAILURE); }
} else {
//Parent process: wait for child to end
wait(&status);
}
} while(command != "exit");
return 0;
}
我知道我擁有的當前代碼只能支持命令的一個參數,但我不確定使用什么來指定 1 到 4 個參數。 那時我的朋友提到了std::istringstream
,但在研究它時,我不明白如何將它用於程序其余部分的輸入。 有沒有辦法設置它或者是否有不同的方法來滿足要求?
帶有用戶輸入的std::istringstream
最常見的使用模式是接受單行文本然后處理它。 這可以避免在輸入與您期望的不匹配或無法預測時可能出現的問題。
這是一個簡單的示例,它一次從 STDIN 讀取一行,並將其處理為一個命令,后跟一個字符串向量作為參數。
for(std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
std::string command;
if (iss >> command)
{
std::vector<std::string> args;
for (std::string arg; iss >> arg; )
{
args.push_back(arg);
}
std::cout << "Received '" << command << "' with " << args.size() << " arguments\n";
}
else
{
std::cerr << "Invalid input" << std::endl;
}
}
當然,您不需要讀入字符串或將內容存儲在向量中。 這只是為了說明目的。
基本點是避免人們遇到的陷阱,其中最常見的是期望之前的流操作成功。 當該假設為假時,天真的程序員會發現自己試圖解析應該在前一行中傳遞的內容。
破碎的例子:
#include <iostream>
int main() {
std::string command;
while (std::cin >> command)
{
std::cout << "Got command: " << command << std::endl;
if (command == "foo")
{
// 'foo' expects two integer arguments:
int arg1, arg2;
std::cin >> arg1 >> arg2;
std::cout << command << ": " << arg1 << ", " << arg2 << std::endl;
}
else if (command == "bar")
{
// 'bar' expects one float argument:
float arg1;
std::cin >> arg1;
std::cout << command << ": " << arg1 << std::endl;
}
}
return 0;
}
在上面,假設用戶感到困惑並使用一個浮點參數“調用” foo命令,那么下一個命令是一個有效的bar命令:
foo 42.0
bar 3.14
這是發生的事情:
foo處理程序將 arg1 讀取為 42,然后無法讀取下一個參數。 流現在出錯了。
在該處理程序期間沒有對輸入進行錯誤檢查,因此現在有未定義的行為輸出arg2
的值。
當嘗試讀取下一個命令時,流已經處於錯誤狀態,因此循環終止。
因此,該程序的輸出可能如下所示:
Got command: foo
foo: 42, -149017896
在沒有istringstream
的情況下解決這個問題是可能的,但這很痛苦。 流可能進入錯誤狀態的原因有很多,為了解決這個問題而清除特定錯誤狀態的錯誤標志會產生丑陋且可能容易出錯的代碼。 您不僅需要清除錯誤標志,還需要告訴流忽略該行中的任何剩余字符。 您可能已經開始在不知情的情況下閱讀下一行。
更健壯的例子:
#include <iostream>
#include <sstream>
int main() {
std::string command;
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
if (!(iss >> command))
continue;
std::cout << "Got command: " << command << std::endl;
if (command == "foo")
{
// 'foo' expects two integer arguments:
int arg1, arg2;
if (iss >> arg1 >> arg2)
{
std::cout << command << ": " << arg1 << ", " << arg2 << std::endl;
}
}
else if (command == "bar")
{
// 'bar' expects one float argument:
float arg1;
if (iss >> arg1)
{
std::cout << command << ": " << arg1 << std::endl;
}
}
}
return 0;
}
現在,來自上一個示例的相同輸入將給出輸出:
Got command: foo
Got command: bar
bar: 3.14
區別在於:
使用istringstream
,處理我們輸入的任何錯誤都不會影響源流,因此前一行的失敗不會導致問題。
讀取參數時正確檢查字符串流,允許可選的錯誤處理。
如果在某些解析失敗后,您決定嘗試以不同方式處理輸入行,那么使用另一個字符串流很容易做到。
如果我正確理解您的任務,那么您的明顯問題就在這里:
cin >> command >> argument;
您需要一個包含整個命令行(getline?)的字符串。 然后您需要一個綁定到包含整個命令行的字符串的 istringstream。
然后你需要做類似的事情
iss >> command >> arg1 >> arg2 >> arg3 >> arg4 ;
在這一點上,我對你的任務要求一無所知。 但是,您可能想要執行以下操作:
iss >> command >> arg1 >> arg2 >> arg3 >> arg4 >> arg5 ;
用於錯誤檢查。 如果 arg5 不是空字符串,則指定的參數過多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.