我偶然发现了 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
}
答案 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);
打开文件,然后您有三个选项:
或者,如前所述,使用Boost。
答案 2 :(得分:0)
Windows和Linux / Unix中的行结尾不一样 - Windows使用两个字节而Linux使用一个字节。 Google如何在.nix命令行中使用tr,您将看到如何转换它们。
祝你好运!