我有一些我无法弄清楚的奇怪问题。当我运行下面的代码时,file.txt
将它逐行读入vector<string>
,然后将每个索引与字符串"--"
进行比较,它不会进入比较阶段。
此外,在for循环字符串m下的convert_file()中,有一些奇怪的行为:string m = "1"; m+= "--";
(&#39; - &#39;内部向量)m+= "2";
将打印到console 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
答案 0 :(得分:1)
根据行为和讨论,使用"\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()
来确定读取的字符数,以便快速找到字符串的结尾。但请注意,该数字包含bewline字符,即您要检查str[file.gcount() - 2]
并可能将其设置为'\0'
(如果计数大于或等于2,当然)。
答案 1 :(得分:0)
正如DietmarKühl所说,问题在于\r\n
行结尾。
但是,您不需要修改源代码。 C ++中的默认行为应该是以文本模式打开文件。文本模式意味着无论何时找到行结尾,“行结束”取决于您正在使用的平台,它都会被翻译,以便您的程序只看到一个\n
。您应该从程序中明确请求“二进制模式”以禁用此行结束转换。这是Windows系统上长期存在的做法,C ++标准很好地支持这种行为,并且是本机Windows编译器的预期行为,但是为了兼容POSIX和现有的Unix程序,它们不打扰正确设置文件模式, Cygwin忽略了这一点并默认以二进制模式打开文件,除非明确请求自定义Cygwin特定文本模式。
这包括in the Cygwin FAQ。那里提供的第一个解决方案(使用O_TEXT
或"t"
,取决于您打开文件的方式)是非标准的,因此在其他环境中破坏您的代码,并且它们不易于使用C ++ { {1}}文件访问。
但是,提供的下一个解决方案甚至可以用于C ++程序:
您还可以通过将其他对象文件链接到可执行文件来避免更改源代码。 Cygwin在/ usr / lib目录中提供各种目标文件,当链接到可执行文件时,它会更改在已执行进程本身内打开的任何文件的默认打开模式。文件是
binmode.o - Open all files in binary mode. textmode.o - Open all files in text mode. textreadmode.o - Open all files opened for reading in text mode. automode.o - Open all files opened for reading in text mode, all files opened for writing in binary mode.
确实,将编译器和链接器调用从<fstream>
更改为g++ -o a -std=c++11 test.cpp
,您的程序无需更改源代码即可运行。与g++ -o a -std=c++11 test.cpp /usr/lib/textmode.o
链接基本上意味着您的I / O将按照默认情况下的工作方式运行。