[英]std::vector<string> odd behavior
我有一些無法解決的怪異問題。 當我運行下面的代碼時,該文件將使用file.txt
逐行將其讀取到vector<string>
,然后將每個索引與字符串"--"
進行比較,但這不會使其進入比較階段。
此外,在for循環字符串m下的convert_file()中,具有一些怪異的行為: string m = "1"; m+= "--";
string m = "1"; m+= "--";
('-'在向量內部) m+= "2";
將打印到控制台2--
; 這讓我認為某些東西正在干擾向量。 2正在替換第一個字符1。 這使得矢量看起來像是臭蟲。
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<string> get_file(const char* file){
int SIZE=256, ln=0;
char str[SIZE];
vector<string> strs;
ifstream in(file, ios::in);
if(!in){
return strs;
} else {
while(in.getline(str,SIZE)){
strs.push_back(string(str));
ln++;
}
}
in.close();
return strs;
}
void convert_file(const char* file){
vector<string> s = get_file(file);
vector<string> d;
int a, b;
bool t = false;
string comp = "--";
for(int i=0; i<s.size(); i++){
string m = "1";
m+= string(s.at(i));
m+= "2";
cout << m << endl;
if(s.at(i) == comp){
cout << "s[i] == '--'" << endl;
}
}
}
int main(){
convert_file("test.txt");
return 0;
}
現在,當我運行測試文件以檢查類似程序時:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
vector<string> s;
s.push_back("--");
s.push_back("a");
for(int i=0; i<s.size(); i++){
cout << "1" << s.at(i) << "2" << endl;
if(s.at(i) == "--"){
cout << i << "= --" << endl;
}
}
return 0;
}
打印出1--2
0= --
, 1a2
。 它可以正常工作,可以正確打印並進行比較。 這使我認為將線拉成字符串時發生了某些事情。
Windows 7, cygwin64
g++ version 4.9.3
compile: D:\projects\test>g++ -o a -std=c++11 test.cpp
根據行為和討論,使用"\\r\\n"
序列終止文件中的行。 處理其余'\\r'
的最簡單方法是在讀取一行后將其刪除。 例如:
for (std::string line; std::getline(file, line); ) {
if (!line.empty() && line.back() == '\r') {
line.resize(line.size() - 1u);
}
strs.push_back(line);
}
如果您堅持要讀入char
數組,則可以使用file.gcount()
確定讀取的字符數,以快速找到字符串的結尾。 但是請注意,該數字包含斜線字符,即,您需要檢查str[file.gcount() - 2]
並可能將其設置為'\\0'
(如果計數大於或等於2,當然)。
正如DietmarKühl已經回答的那樣,問題在於\\r\\n
行尾。
但是,您不需要修改源代碼。 C ++中的默認行為應該是在文本模式下打開文件。 文本模式意味着只要找到行尾,“行尾”取決於您使用的平台,它就會被翻譯,因此您的程序只會看到一個\\n
。 您應該從程序中明確請求“二進制模式”以禁用此行結束翻譯。 這是Windows系統上的長期實踐,是C ++標准很好地支持的行為,也是本機Windows編譯器的預期行為,但是為了與POSIX和現有的Unix程序兼容,它們不會費心設置文件模式, Cygwin會忽略此設置,並且默認情況下以二進制模式打開文件,除非明確請求了特定於Cygwin的自定義特定文本模式。
Cygwin常見問題解答對此進行了介紹。 那里提供的第一個解決方案(使用O_TEXT
或"t"
,取決於您打開文件的方式)是非標准的,因此會在其他環境中破壞您的代碼,並且與C ++ <fstream>
文件訪問一樣不容易使用。
但是,那里提供的下一個解決方案甚至對C ++程序也有效:
您還可以通過將其他目標文件鏈接到可執行文件來完全避免更改源代碼。 Cygwin在/ usr / lib目錄中提供了各種目標文件,當這些文件鏈接到可執行文件時,它們將更改在已執行進程本身中打開的任何文件的默認打開模式。 這些文件是
\n binmode.o-以二進制模式打開所有文件。\n textmode.o-以文本模式打開所有文件。\n textreadmode.o-打開所有以文本模式讀取的文件。\n automode.o-以文本模式打開所有要閱讀的文件,\n 所有打開的文件以二進制模式寫入。\n
確實,將您的編譯器和鏈接器調用從g++ -oa -std=c++11 test.cpp
為g++ -oa -std=c++11 test.cpp /usr/lib/textmode.o
,您的程序無需更改您的源代碼。 基本上,與textmode.o
鏈接意味着您的I / O將按照默認情況下已經可以正常工作的方式工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.