【问题标题】:Read from file (ifstream) and write to file (ofstream) - problems with encoding从文件读取(ifstream)并写入文件(ofstream) - 编码问题
【发布时间】:2016-03-31 08:55:12
【问题描述】:

注意:我是一个 C++ 菜鸟。

我有以下问题:

我从一个文件中读取并想用其他字符串部分替换字符串部分。简单的任务,应该很容易做到。我用 setmode 做了一些实验,但没有成功。我也用谷歌搜索过,但它也没有帮助我。

可能存在轻微的代码问题,但请关注问题。转换测试数据如下:

int main(int argc, char** argv) {
    stringstream strs;

    //Choose output file
    ofstream ofile;
    string filename;
    cout << "Ausgabepfad eingeben" << endl;
    cin >> filename;
    ofile.open(&filename[0]);

    //Choose input file
    ifstream ifile;
    cout << "Quellpfad eingeben" << endl;
    cin >> filename;
    ifile.open(&filename[0]);

    //Choose decoding - doesnt work, I know - That was for experiments
    int mode = 0;
    cout << "Decoding wählen\n1 für _O_TEXT\n2 für _O_BINARY\n3 für _O_U16TEXT\n4 für _O_U8TEXT\n5 für _O_WTEXT" << endl;
    cin >> mode;
/*    switch(mode){
        case 1:
            _setmode (_fileno(ifstream), _O_TEXT);
        break;
        case 2:
            _setmode (_fileno(ifstream), _O_BINARY);
        break;
        case 3:
            _setmode (_fileno(ifstream), _O_U16TEXT);
        break;
        case 4:
            _setmode (_fileno(ifstream), _O_U8TEXT);
        break;
        case 5:
            _setmode (_fileno(ifstream), _O_WTEXT);
        break;
        default:
            cerr << "ungültige Codierung gewählt"
    }
*/    

    //Choose search string and replacement string
    ifile.seekg(0); //not necessary, I know
    string searchstr = "";
    cout << "Suchstring eingeben" << endl;
    cin >> searchstr;
    string fillstr;
    cout << "Ersetzungsstring eingeben" << endl;
    cin >> fillstr;
    cout << fillstr;
    int marker = 0;
    if(searchstr.length()<1){
        return 0;
    }

    //actual program
    while(!ifile.eof()){
        int counter = 0;
        ifile.seekg(marker);
        char current = ifile.get();
        if(current==searchstr[0]){ //if the first search letter matches, seet, if the others do.
            marker++;
            counter++;
            for(int i = 1; i < searchstr.length(); i++){
                ifile.seekg(marker);
                if(ifile.get()==searchstr[i]){
                    counter++;
                    marker++;
                }else{
                    marker-i;
                    break;
                }
            }
            if(counter == searchstr.length()){
                ofile << fillstr;
                cout << endl;
            }
        }else{
            ofile << ifile.get();
            cout << ifile.get();
        }
        marker++;

    }

    ifile.close();
    ofile.close();
    cout << endl;
    return 1;
}

以下字符串

|-

应该替换为

\n

文本(示例)是:

|[[Allgemeines Deutsches Kommersbuch:1|1]] 
|1 
|[[Abend wird's, des Tages (Körner)]] 
|[[Die Eichen (Körner)]]
|-
|[[Allgemeines Deutsches Kommersbuch:2|2]] 
|2 

程序运行,但它不起作用。输出是很多没有任何意义的数字。

【问题讨论】:

  • marker-i; 看起来不对。
  • 见标准编解码器。另外,看看 wchar_t、wcin、wcout 等。
  • marker - i 是对的。我匹配并通过标记++(i 为 1)转到下一个字母,如果字母匹配,我会更进一步,如果不匹配,i 会后退。最后我去marker++。如果没有marker-i||- 将被跳过。
  • 输出应该是什么?我无法理解其中的逻辑。

标签: c++ file input output


【解决方案1】:

输出是大量没有任何意义的数字。

调用ifile.get() 返回一个int_type 类型的值。因此&lt;&lt; 输出所有这些整数值。

替换

ofile << ifile.get();

(对整数进行格式化输出)

ofile << char( ifile.get() );

或(首选,使用未格式化的输入输出)

ofile.put( ifile.get() );

【讨论】:

  • 我会选择getput,因为两者都用于未格式化的输入/输出。
【解决方案2】:

用标准流、迭代器和算法来表达问题几乎总是一个更好的主意:

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>

// lets get the logic right in terms of streams


void replace_all(std::ostream& dest, std::istream& source, 
                 const std::string& search_for, const std::string& replace_with)
{
    std::string line;
    while (std::getline(source, line)) {
        auto ipos = line.begin();
        while (ipos != line.end())
        {
            ipos = std::search(ipos, line.end(), search_for.begin(),
                               search_for.end());
            if (ipos != line.end())
            {
                auto start_index = std::distance(line.begin(), ipos);
                line.replace(ipos, std::next(ipos, search_for.length()), 
                             replace_with);
                ipos = std::next(line.begin() + start_index + replace_with.length());
            }
        }
        dest.write(line.data(), line.size());
        dest.put('\n');
    }

}

// now test
int main()
{
    std::string search_for = "|-";
    std::string replace_with = "";

    std::istringstream source_stream("|[[Allgemeines Deutsches Kommersbuch:1|1]]\n"
                                     "|1\n"
                                     "|[[Abend wird's, des Tages (Körner)]]\n"
                                        "|[[Die Eichen (Körner)]]\n"
                                        "|-\n"
                                        "|[[Allgemeines Deutsches Kommersbuch:2|2]]\n"
                                     "|2\n");

    std::ostringstream dest_stream;

    replace_all(dest_stream, source_stream, search_for, replace_with);

    std::cout << dest_stream.str();

    return 0;
}

// todo: write a new main which asks for filenames, builds ifstreams and ofstreams, and calls replace_all()

预期输出:

|[[Allgemeines Deutsches Kommersbuch:2|2]]
|2
Jewels-MacBook-Pro:play richardh$ ./replace.cpp
|[[Allgemeines Deutsches Kommersbuch:1|1]]
|1
|[[Abend wird's, des Tages (Körner)]]
|[[Die Eichen (Körner)]]

|[[Allgemeines Deutsches Kommersbuch:2|2]]
|2

【讨论】:

  • 我在这里看到的问题是,如果字符串是lalala\nblabla,它将不起作用。因为总是读整行。无法搜索跨越换行符的字符串。
  • @MaestroGlanz 我没有意识到这是一个要求。你能更明确地定义算法的要求吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 2012-11-14
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
相关资源
最近更新 更多