![](/img/trans.png)
[英]Why does taking large input from stdin using getline truncate my input?
[英]String read in from stdin by getline using redirection command “<” from input file does not append correctly
問題陳述
我想附加一個字符串“真棒!” ,使用getline函數從stdin讀取到另一個字符串“ Ice creams” 。
因此產生“冰淇淋很棒!”
如果輸入是手動鍵入的,則附加操作將正常進行。
但是,如果輸入是通過重定向命令“ <”從文件中獲取的,則追加操作的行為不會類似。
因此制作很棒! 冰淇淋 。
碼
讓我通過代碼演示問題。
#include<iostream>
int main()
{
// err : will be read from stdin using getline
// err : is expected to fail in appending
std::string err;
// ok : will be modified internally
// ok : is expected to succeed in appending
std::string ok = "Pancakes";
std::cout<<"Before executing std::getline..."<<std::endl;
std::cout<<"err \t:\t"<<err<<std::endl;
std::cout<<"ok \t:\t"<<ok<<std::endl;
std::cout<<"-------------------"<<std::endl;
// we now use getline to read in string value for err
// stdin can have any string , let's assume it is "Ice creams"
std::cout<<"-------------------"<<std::endl;
std::cout<<"Please enter string manually or < from file "<<std::endl;
std::getline(std::cin,err);
std::cout<<"-------------------"<<std::endl;
std::cout<<"After executing std::getline..."<<std::endl;
std::cout<<"err \t:\t"<<err<<std::endl;
std::cout<<"ok \t:\t"<<ok<<std::endl;
std::cout<<"-------------------"<<std::endl;
//-------------------------------------------//
// THE PROBLEM //
//-------------------------------------------//
// we try to append to err
err += " are awesome !";
// we try to append to ok
ok += " are awesome !";
std::cout<<"After executing append operation..."<<std::endl;
std::cout<<"Where,the '+=' operator is used..."<<std::endl;
std::cout<<"err \t:\t"<<err<<std::endl;
std::cout<<"ok \t:\t"<<ok<<std::endl;
std::cout<<"-------------------"<<std::endl;
return 0;
}
終端輸出
借助WSL功能在Windows 10計算機上運行的g ++進行編譯。
C:\test>wsl g++ test.cpp -o a.out -std=c++11
C:\test>wsl ./a.out
Before executing std::getline...
err :
ok : Pancakes
-------------------
-------------------
Please enter string manually or < from file
Ice creams
-------------------
After executing std::getline...
err : Ice creams
ok : Pancakes
-------------------
After executing append operation...
Where,the '+=' operator is used...
err : Ice creams are awesome !
ok : Pancakes are awesome !
-------------------
C:\test>wsl ./a.out < in-test.in
Before executing std::getline...
err :
ok : Pancakes
-------------------
-------------------
Please enter string manually or < from file
-------------------
After executing std::getline...
err : Ice creams
ok : Pancakes
-------------------
After executing append operation...
Where,the '+=' operator is used...
are awesome ! Ice creams
ok : Pancakes are awesome !
-------------------
C:\test>
結果
注意: in-test.in文件包含帶有字符串“ Ice creams ”的一行。
注意:如果很難注意到該錯誤,請允許我指出。
這是行真棒! 冰淇淋位於終端輸出的尾部。
問題
請注意,該行甚至不包含所謂的前導"err \\t:\\t"
輸出,但是err
的輸出顯示了它應該在哪里?
那只能是因為輸入文件包含一個前導的回車符'\\r'
。
知識點
一些程序員的好人提到字符串中可以包含'\\r'
。
問題來源
有意義的是,Linux,Macintosh和Windows具有不同的行終止符,因此當我們要將文件從一個系統傳輸到另一個系統並期望它們正常工作時,可能會遇到一些問題。
這個問題的解釋很漂亮: CR LF,LF和CR換行類型之間的區別? 。
就是這樣。 我使用Notepad.exe創建了文件,因此自動為它分配了CRLF行終止符。 但是,由於我使用Linux的Windows子系統(WSL) (本質上是在Windows 10中運行的Ubuntu )編譯程序,因此a.out
創建的可執行文件是linux可執行文件。
將帶有CRLF行終止符的文件重定向到可執行文件stdin中導致了此問題。
使用MinGW或MSYS2后,遷移到WSL的用戶可能會遇到此特定問題。
既然如此,MinGW和MSYS2可以很好地與CRLF編碼配合使用,而WSL則不能。
固定
只需使用稱為unix2dos
或dos2unix
的工具更改行終止符unix2dos
。
顧名思義,它們會將文本文件轉換為與基於dos和unix的OS兼容。
unix2dos
。 dos2unix
。 演示版
C:\test>wsl g++ test.cpp -o a.out -std=c++11
C:\test>wsl unix2dos in-test.in
unix2dos: converting file in-test.in to DOS format ...
C:\test>wsl file in-test.in
in-test.in: ASCII text, with CRLF line terminators
C:\test>wsl ./a.out < in-test.in
Before executing std::getline...
err :
ok : Pancakes
-------------------
-------------------
Please enter string manually or < from file
-------------------
After executing std::getline...
err : Ice creams
ok : Pancakes
-------------------
After executing append operation...
Where,the '=' operator overloading is used...
are awesome ! Ice creams
ok : Pancakes are awesome !
-------------------
C:\test>wsl dos2unix in-test.in
dos2unix: converting file in-test.in to Unix format ...
C:\test>wsl file in-test.in
in-test.in: ASCII text
C:\test>wsl ./a.out < in-test.in
Before executing std::getline...
err :
ok : Pancakes
-------------------
-------------------
Please enter string manually or < from file
-------------------
After executing std::getline...
err : Ice creams
ok : Pancakes
-------------------
After executing append operation...
Where,the '=' operator overloading is used...
err : Ice creams are awesome !
ok : Pancakes are awesome !
-------------------
結果
WSL創建的可執行文件最初不適用於帶有CRLF行終止符的輸入文件,然后
使用工具dos2unix
將文件的行終止符更改為與Linux兼容,從而與WSL兼容,從而使程序成功運行。 因此,修復程序起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.