[英]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.