在 C++ 中重新实现 dos2unix 和 unix2dos; '\r' 和 '\n' 没有出现在 hexdump 中?

Reimplementing dos2unix and unix2dos in C++; '\r' and '\n' not appearing in hexdump?

我正在尝试用 C++ 重新实现 dos2unixunix2dos。这是我的 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 之外什么也没做:

输入的十六进制转储

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

输出的十六进制转储

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

预期输出的十六进制转储

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.

的实现中得到了类似的行为

为了避免 >> 从您的输入中删除空格,最简单的更改就是使用 is.get(c) 而不是 is >> cstd::basic_istream::get behaves as an Unformatted input function and will provide a character-by-character read of everything in the file. The std::basic_iostream operator >> 提供 Formatted 消除空格的输入。

更改为 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

示例Use/Output文件

您可以看到 '\n' 保留在您的输入中。

$ 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

最后,避免在代码中使用 0XD0XA,而是使用字符本身,例如'\r''\n'。它使代码更具可读性。检查一下,如果您还有其他问题,请告诉我。