Windows上的字符串大小与Linux上的不同

时间:2012-10-06 14:16:24

标签: c++ windows linux string size

我偶然发现了 string :: substr 的奇怪行为。通常我在Eclipse + MinGW中的 Windows 7 上编码,但是当我在笔记本电脑上工作时,在 Linux (Ubuntu 12.04)中使用Eclipse时,我发现结果有所不同。

我正在使用 vector<字符串> 填充了文本行。其中一个步骤是从行中删除最后一个字符。

在win7 Eclipse中我做了:

for( int i = 0; i < (int)vectorOfLines.size(); i++ )
{
    vectorOfTrimmedLines.push_back( ((string)vectorOfLines.at(i)).substr(0, ((string)vectorOfLines.at(i)).size()-1) );
}

并且它按预期工作(从每行删除最后一个字符)

但在Linux中,这段代码不会修剪。相反,我需要这样做:

//  -2 instead -1 character
vectorOfTrimmedLines.push_back( ((string)vectorOfLines.at(i)).substr(0, ((string)vectorOfLines.at(i)).size()-2) );

或使用其他方法:

vectorOfTrimmedLines.push_back( ((string)vectorOfLines.at(i)).replace( (((string)vectorOfLines.at(i)).size()-2),1,"",0 ));

当然Linux方法在Windows上工作方式错误(修剪2个最后一个字符,或者在最后一个字符之前替换一个字符)。

问题似乎是myString.size()返回Windows中的字符数,但在Linux中它返回的字符数+ 1。 可能是新的行字符在Linux上被计算在内吗?

作为C ++和编程方面的新手,我想知道为什么会这样,以及如何做到与平台无关。

我想知道的另一件事是:哪种方法更好(更快) substr 替换

编辑: 用于填充字符串的方法我写的这个函数:

vector< string > ReadFile( string pathToFile )
{
    //  opening file
    ifstream myFile;
    myFile.open( pathToFile.c_str() );

    //  vector of strings that is returned by this function, contains file line by line
    vector< string > vectorOfLines;

    //  check if the file is open and then read file line by line to string element of vector
    if( myFile.is_open() )
    {
        string line;    //  this will contain the data read from current the file

        while( getline( myFile, line ) )    //  until last line in file
        {
            vectorOfLines.push_back( line );    //  add current line to new string element in vector
        }

        myFile.close(); //  close the file
    }

    //  if file does not exist
    else
    {
        cerr << "Unable to open file." << endl; //  if the file is not open output
        //throw;
    }

    return vectorOfLines;   //  return vector of lines from file
}

3 个答案:

答案 0 :(得分:8)

不同操作系统上的文本文件不相同。 Windows使用双字节代码标记行的结尾:0x0D,0x0A。 Linux使用一个字节0x0A。 getline(以及大多数其他输入函数)知道为其编译的操作系统的约定;当它读取操作系统用来表示一行结束的字符时,它会用'\ n'替换字符。因此,如果您在Windows下编写文本文件,则行以0x0D,0x0A结尾;如果您在Linux下读取该文本文件,getline看到0x0D并将其视为普通字符,则它会看到0x0A,并将其视为该行的结尾。

因此,当您将文本文件从一个系统移动到另一个系统时,必须将文本文件转换为本机表示。 ftp知道如何做到这一点。如果您在虚拟框中运行,则必须在切换系统时手动执行转换。使用Unix命令行中的tr非常简单。

答案 1 :(得分:4)

这是因为在Windows中,换行符由两个字符CR + LF表示,而在Linux上它只是LF,而在Mac上(在OSX之前)它只是CR。

只要您只使用Linux系统上的Linux上生成的文件或Windows系统上的Windows上生成的文件,您就不用担心了。但是,只要您需要在Windows上使用Linux上生成的文件,反之亦然,就需要正确处理换行。

作为第一步,您需要以二进制模式std::ofstream infile( "filename", std::ios_base::binary);打开文件,然后您有三个选项:

  1. 您需要为所有平台决定一个新行约定并一致地使用它,
  2. 您需要能够检测当前文件中使用的换行符约定(通常通过检查第一行使用的换行符来实现),将其保存在变量中,并将其传递给需要处理的字符串函数换行,
  3. 告诉用户将文件转换为正确的换行符,例如使用dos2unix和unix2dos,或者如果文件传输涉及FTP,请使用ASCII模式
  4. 或者,如前所述,使用Boost。

答案 2 :(得分:0)

Windows和Linux / Unix中的行结尾不一样 - Windows使用两个字节而Linux使用一个字节。 Google如何在.nix命令行中使用tr,您将看到如何转换它们。

祝你好运!