C ++交叉编译不处理换行输入文本文件

时间:2015-04-25 12:48:45

标签: c++ newline cross-compiling

为清楚起见:

这不是Getting std :: ifstream to handle LF, CR, and CRLF?

的副本

这是C++ cutting off character(s) when read lines from file

的扩展

我预先说明了这一点,因为当我在C++ cutting off character(s) when read lines from file发布问题时,它被标记为Getting std :: ifstream to handle LF, CR, and CRLF?的潜在副本。我尝试了一个简化版本(直接读取而不是缓冲区以保持简单)所提出的解决方案在另一篇文章中它对我不起作用,即使我编辑了我的问题和代码来证明这一点,也没有回复。乔纳森建议我重新发布一个单独的问题,所以我在这里。

我还尝试了许多其他解决方案,最后得到了下面的代码,但是虽然代码按预期处理了标签和普通文本,但它仍然没有像预期的那样处理新行字符差异所以我需要帮助。

我想:

  • 读入txt文件的内容
  • 对内容进行一些验证检查
  • 将报告输出到另一个txt文件

在这个原型代码中,我只是从一个文件中读取文本并将编辑后的文本输出到另一个文件。在我开始工作后,我会担心运行验证测试,......

我正在Linux Mint Maya(基于Ubuntu 12.04)的盒子上进行编译和测试,然后使用mingw32进行交叉编译,以便在Windows PC上运行。

当我:

时,一切正常
  • 使用linux创建的文本文件在Linux机器上编译并运行
  • 在Linux上进行交叉编译,并在Windows上使用Linux创建的文本文件运行

然而,当我:

  • 在Linux上交叉编译并使用Windows创建的文本文件在Windows上运行

结果不符合预期;跳过前几个字符。

我需要该程序来处理Windows创建或Linux创建的文本文件。

(我现在用作测试的傻内容)输入文件我在所有情况下使用(一个在linux盒子上创建;一个在Windows上使用记事本创建)是:

A new beginning
just in case
the file was corrupted
and the darn program was working fine ...
at least it was on linux

当我读入文件并使用该程序(如下所示的代码)时,linux创建的文本文件会产生正确的输出:

Line 1: A new beginning
Line 2: just in case
Line 3: the file was corrupted
Line 4: and the darn program was working fine ...
Line 5: at least it was on linux

当我使用Windows创建的文本文件并在Windows PC上运行程序时,输出为:

Line 1: A new beginning
Line 2: t in case
Line 3: e file was corrupted
Line 4: nd the darn program was working fine ...
Line 5: at least it was on linux

正如您所看到的,2,3,4行中缺少字符,而不是1,5:

  • 第1行开头缺少0个字符
  • 第2行开头缺少3个字符
  • 第3行开头缺少2个字符
  • 第4行开头缺少1个字符
  • 第5行开头缺少0个字符

我希望这与linux和Windows文本文件中处理换行符的差异有关,但我已经阅读了其他帖子并尝试了解决方案,但它似乎没有解决问题。我确信我错过了一些非常基本的东西并提前道歉,如果是这样,但我已经在这一段时间内敲打了一个多星期并需要帮助。

我使用的代码是:

int main(int argc, char** argv)
{


    /*
     *Program to:
     *  1) read from a text file
     *  2) do some validation checks on the content of that text file
     *  3) output a report to another text file
     */

    std::string rc_input_file_name = "rc_input_file.txt";
    std::string rc_output_file_name = "rc_output_file.txt";

    char *RC_INPUT_FILE_NAME = new char[ rc_input_file_name.length() + 1 ];
    strcpy( RC_INPUT_FILE_NAME, rc_input_file_name.c_str() );
    char *RC_OUTPUT_FILE_NAME = new char[ rc_output_file_name.length() + 1 ];
    strcpy( RC_OUTPUT_FILE_NAME, rc_output_file_name.c_str() );

    std::ifstream rc_input_file_holder;
    rc_input_file_holder.open( RC_INPUT_FILE_NAME , std::ios::in );

    if ( ! rc_input_file_holder.is_open() )
    {
        std::cout << "Error - Could not open the input file" << std::endl;
        return EXIT_FAILURE;
    }
    else
    {
        std::ofstream rc_output_file_holder;
        rc_output_file_holder.open( RC_OUTPUT_FILE_NAME , std::ios::out | std::ios::trunc );

        if ( ! rc_output_file_holder.is_open() )
        {
            std::cout << "Error - Could not open or create the output file" << std::endl;
            return EXIT_FAILURE;
        }
       else
        {
            std::streampos char_num = 0;

            long int line_num = 0;
            long int starting_char_pos = 0;

            std::string file_line = "";

            while ( getline( rc_input_file_holder , file_line ) )
            {
                line_num = line_num + 1;
                long unsigned file_line_length = file_line.length();

                std::string string_to_find = "\r";
                std::string string_to_insert = "\n";
                long unsigned num_char_in_string_to_find = string_to_find.length();
                long unsigned character_position;
                while ( ( character_position = file_line.find( string_to_find ) ) != std::string::npos )
                {
                    if ( character_position == file_line_length - num_char_in_string_to_find )
                    {
                        // If the \r character is found at the end of the line, 
                        //   it is the old Mac style newline, 
                        //   so replace it with \n
                        file_line.replace( character_position , num_char_in_string_to_find , string_to_insert );
                        file_line_length = file_line.length();
                    }
                    else
                    {
                        // If the \r character is found but is not the last character in the line
                        //   it could be the second-last character meaning it is a Windows newline pair \r\n
                        //   or it could be somewhere in the middle of the line
                        //   so delete it
                        file_line.erase( character_position , num_char_in_string_to_find  );
                        file_line_length = file_line.length();
                    }
                }

                int field_display_width = 4;

                rc_output_file_holder << "Line " << line_num << ": " << file_line << std::endl;

                starting_char_pos = rc_input_file_holder.tellg();

            }

            rc_input_file_holder.close();
            rc_output_file_holder.close();
            delete [] RC_INPUT_FILE_NAME;
            RC_INPUT_FILE_NAME = 0;
            delete [] RC_OUTPUT_FILE_NAME;
            RC_OUTPUT_FILE_NAME = 0;
        }
    }
}

任何和所有建议都赞赏......

2 个答案:

答案 0 :(得分:1)

好的,感谢Martin Schlott在他的编译器上尝试了我的程序,并使用了来自Windows或Linux源的文本文件。

这指出了编译器的差异,这是关键。

apt-get install mingw32安装的交叉编译器为交叉编译安装了较旧的编译器(v4.2.1),但apt-get install g ++将linux编译器放在v 4.6.2。

所以我在sourceforge上为交叉编译器的v4.6.3找到了一个旧的列表 Mingw with G++ v4.6.3
并安装它。

我必须包含新安装的路径,我必须在编译命令中添加两个选项

  • -static-libgcc
  • -static-libstdc ++

防止2“丢失dll”错误消息。

之后,交叉编译工作得很干净,新行差异处理没问题。

我喜欢科技:花一个多星期的时间以为我做错了什么,交叉编译器已经过时了。哦,我在此期间学到了很多关于C ++的知识,并希望将来可以帮助其他人。

再次感谢 [R

答案 1 :(得分:-1)

如果您想手动设置换行符,则必须以二进制模式打开文件。