为了避免“Python”,我们应该避免C++中重复的代码吗?

2024-10-01 02:29:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Python和前卵子阶段的C++阶段,但我正在尽我最大的努力,特别是“不要重复你自己”的原则。在

我有一个多通道的原始文件格式要打开,有一个主要的ascii头文件,其中的字段可以表示为字符串和整数(总是用空格填充字符编码)。第二部分是N个报头,N是主报头的一个字段,每个报头本身都有更多的文本和数字字段(编码为ascii),参考构成文件其余部分的实际16位多通道流的长度和大小。在

到目前为止,我在C++中有这个工作代码:

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>

using namespace std;

struct Header {
    string version;
    string patinfo;
    string recinfo;
    string start_date;
    string start_time;
    int header_bytes;
    string reserved;
    int nrecs;
    double rec_duration;
    int nchannels;
};

struct Channel {
    string label;
    string transducertype;
    string phys_dim;
    int pmin;
    int pmax;
    int dmin;
    int dmax;
    string prefiltering;
    int n_samples;
    string reserved;
};


int main()
{
    ifstream edf("/home/helton/Dropbox/01MIOTEC/06APNÉIA/Samples/Osas2002plusQRS.rec", ios::binary);

    // prepare to read file header
    Header header;
    char buffer[80];

    // reads header fields into the struct 'header'
    edf.read(buffer, 8);
    header.version = string(buffer, 8);

    edf.read(buffer, 80);
    header.patinfo = string(buffer, 80);

    edf.read(buffer, 80);
    header.recinfo = string(buffer, 80);

    edf.read(buffer, 8);
    header.start_date = string(buffer, 8);

    edf.read(buffer, 8);
    header.start_time = string(buffer, 8);

    edf.read(buffer, 8);
    stringstream(buffer) >> header.header_bytes;

    edf.read(buffer, 44);
    header.reserved = string(buffer, 44);

    edf.read(buffer, 8);
    stringstream(buffer) >> header.nrecs;

    edf.read(buffer,8);
    stringstream(buffer) >> header.rec_duration;

    edf.read(buffer,4);
    stringstream(buffer) >> header.nchannels;

    /*
    cout << "'" << header.version << "'" << endl;
    cout << "'" << header.patinfo << "'" << endl;
    cout << "'" << header.recinfo << "'" << endl;
    cout << "'" << header.start_date << "'" << endl;
    cout << "'" << header.start_time << "'" << endl;
    cout << "'" << header.header_bytes << "'" << endl;
    cout << "'" << header.reserved << "'" << endl;
    cout << "'" << header.nrecs << "'" << endl;
    cout << "'" << header.rec_duration << "'" << endl;
    cout << "'" << header.nchannels << "'" << endl;
    */

    // prepare to read channel headers
    int ns = header.nchannels; // ns tells how much channels I have
    char title[16]; // 16 is the specified length of the "label" field of each channel

    for (int n = 0; n < ns; n++)
    {
        edf >> title;
        cout << title << endl; // and this successfully echoes the label of each channel
    }


    return 0;
};

我已经说过:

  • 我选择使用struct是因为格式规范是非常硬编码的
  • 我没有迭代主头字段,因为在我看来,要读取的字节和类型的数量相当随意
  • 现在我成功地获得了每个通道的标签,实际上我将为每个通道的字段创建结构,这些字段本身可能必须存储在一个映射中。在

我的问题是:

我是否担心抄近路使这种代码更“Python”(更抽象,更不重复),或者这不是C++中的工作方式?在

许多Python的福音传道者(就像我自己一样,因为我喜欢它)强调它的易用性和所有这些。所以,我会想一段时间,如果我做蠢事或只是做正确的事情,但不是那么“自动”,因为非常自然的C++。在

谢谢你的阅读

赫尔顿


Tags: thereadstringincludebufferstartstructint
3条回答

您是正确的:正如所写的,代码是重复的(并且没有错误检查)。您读取的每个字段实际上需要采取三到五个步骤,具体取决于要读取的数据类型:

  1. 从流中读取字段
  2. 确保读取成功
  3. 分析数据(如有必要)
  4. 确保解析成功(如有必要)
  5. 将数据复制到目标位置

您可以将这三个代码打包成一个函数,这样代码的重复性就更少了。例如,考虑以下函数模板:

template <typename TStream, typename TResult>
void ReadFixedWidthFieldFromStream(TStream& str, TResult& result, unsigned sz) 
{
    std::vector<char> data(sz);

    if (!str.read(&data[0], sz))
        throw std::runtime_error("Failed to read from stream");

    std::stringstream ss(&data[0]);
    if (!(ss >> result))
        throw std::runtime_error("Failed to parse data from stream");
}

// Overload for std::string:
template <typename TStream>
void ReadFixedWidthFieldFromStream(TStream& str, std::string& result, unsigned sz) 
{
    std::vector<char> data(sz);

    if (!str.read(&data[0], sz))
        throw std::runtime_error("Failed to read from stream");

    result = std::string(&data[0], sz);
}

现在您的代码可以更加简洁:

^{pr2}$

这段代码简单明了,易于理解。如果能用的话,别浪费时间换了。我相信有很多写得不好、复杂、难以理解(可能还有不正确)的代码需要首先修复:)

我想说没有Pythic C++代码。DRY原则适用于这两种语言,但大多数被认为是“Pythonic”的方法只是使用Python特定的构造来用Python表达逻辑的最短、最甜蜜的方式。惯用的C++是完全不同的。在

例如,P>>{CD1>}有时不被认为是非常的Pythic,并且保留在没有其他解决方案存在的情况下,而只是被添加到C++标准中。C++没有关键字参数,这是非常Pythonic。C++程序员不喜欢在不必要时构造^ {< CD2}},而Python程序员可能会在很多问题上扔^ {< CD3}},它们正好使意图比有效的替代更清晰。在

如果要保存键入,请使用the function I posted earlier,然后:

header.version = read_field(edf, 8);
header.patinfo = read_field(edf, 80);

这样可以省下不少台词。但比这几行更重要的是,你已经实现了少量的模块化:如何读取字段和要读取的字段现在是程序的独立部分。在

相关问题 更多 >