std :: vector <string>奇怪的行为

时间:2015-11-28 21:49:42

标签: c++ string c++11 vector

我有一些我无法弄清楚的奇怪问题。当我运行下面的代码时,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--20= --1a2。它工作正常,打印正确,并进行比较。这让我想到当我将线条拉成一个字符串时会发生一些事情。

Windows 7, cygwin64
g++ version 4.9.3
compile: D:\projects\test>g++ -o a -std=c++11 test.cpp

2 个答案:

答案 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将按照默认情况下的工作方式运行。