Переопределение dos2unix и unix2dos в C ++;'\ r' и '\ n' не отображаются в hexdump? - PullRequest
0 голосов
/ 08 октября 2019

Я пытаюсь переопределить dos2unix и unix2dos в C ++. Вот мои dos2unix:

dos2unix

#include <stdio.h>
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

// save as d2u.cpp, compile '$ g++ d2u.cpp -o d2u'
// execute '$ ./d2u sample.txt'
int main(int argc, char** argv) {
    string fn ="";
    char c;
    if (argc == 2) { fn = argv[1]; }
    ifstream is(fn.c_str());
    ofstream os("temp.txt");
    while (is >> c) {
        switch(c) {
            // 0x0D = '\r', 0x0A = '\n'
            case 0x0D: break;
            case 0x0A: os << (char)0x0A; break;
            default: os << c; break;
        }
    }
    is.close(); os.close();
    string command = "mv temp.txt " + fn;
    system(command.c_str());
    return EXIT_SUCCESS;
}

Так как текстовые файлы DOS будут иметь переводы строк, заканчивающиеся на \r\n, я хочу игнорировать \r и выводить только \n вновый файл. Тестирование его с помощью текстового файла и сравнение hexdumps, однако, показывает, что ничего не сделано, за исключением того, что все \r и \n удалены:

Hexdump ввода

74 65 73 74 0d 0a 74 65 73 74 32 0d 0a 74 65 73 74 33
t  e  s  t  \r \n t  e  s  t  2  \r \n t  e  s  t  3

Hexdump вывода

74 65 73 74 74 65 73 74 32 74 65 73 74 33
t  e  s  t  t  e  s  t  2  t  e  s  t  3

Hexdump ожидаемого выхода

74 65 73 74 0a 74 65 73 74 32 0a 74 65 73 74 33
t  e  s  t  \n t  e  s  t  2  \n t  e  s  t  3

Почему это происходит? Я получаю похожее поведение с моей реализацией unix2dos.

1 Ответ

1 голос
/ 08 октября 2019

Чтобы исключить >> для устранения пробелов в вводе, самое простое изменение - просто использовать is.get(c) вместо is >> c. std :: basic_istream :: get ведет себя как Неформатированная функция ввода и обеспечивает посимвольное чтение всего в файле. Оператор std :: basic_iostream >> обеспечивает ввод Форматированный , который устраняет пробелы.

Изменение на istream. get() обеспечивает поведение, которое вы описываете,

#include <iostream>
#include <fstream>
#include <string>

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

    std::string fn {};
    char c;

    if (argc < 2) { /* validate filename provided */
        std::cerr << "error: filename required.\n";
        return 1;
    }

    fn = argv[1];

    std::ifstream is (fn.c_str());
    std::ofstream os ("temp.txt");

    while (is.get(c))
        if (c != '\r')
            os.put(c); 

    string command = "mv temp.txt " + fn;
    system(command.c_str());

}

Пример входного файла

$ cat dat/fleas2line.txt
my dog has fleas
my cat has none

Пример использования / выходной файл

Вы можете увидеть '\n' isсохранены в вашем вводе.

$ hexdump -Cv temp.txt
00000000  6d 79 20 64 6f 67 20 68  61 73 20 66 6c 65 61 73  |my dog has fleas|
00000010  0a 6d 79 20 63 61 74 20  68 61 73 20 6e 6f 6e 65  |.my cat has none|
00000020  0a                                                |.|

temp.txt

$ cat temp.txt
my dog has fleas
my cat has none

Наконец, избегайте использования 0XD и 0XA в вашем коде и вместо этого используйте сами символы, например '\r' и '\n'. Это делает код намного более читабельным. Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

...