我们应该避免使用C ++中的重复代码以使其“ Pythonic”吗?如何?

如何解决我们应该避免使用C ++中的重复代码以使其“ Pythonic”吗?如何?

| 我处于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,8);
    header.start_date = string(buffer,8);
    header.start_time = string(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是因为格式规范是非常硬编码的。 我没有遍历主标头字段,因为在我看来,要读取的字节和类型的数量相当随意。 现在,我已经成功获取了每个通道的标签,实际上我将为每个通道的字段创建结构,这些结构本身可能必须存储在地图中。 我的(希望很简单)的问题是: \“我是否应该担心偷工减料,以使这类代码更加“ Pythonic”(更抽象,更少重复),或者这不是C ++的工作方式吗?” 许多Python传播者(就像我自己一样,因为我喜欢它)强调了它的易用性以及所有这些。因此,我会怀疑我是在做愚蠢的事情还是只是在做正确的事情,但是由于C ++的本质,我不会这么想“自动”。 谢谢阅读 海尔顿     

解决方法

我会说没有Pythonic C ++代码之类的东西。 DRY原理在两种语言中都适用,但是使用Python特定的构造,大多数被认为是Python语言的最简单,最甜蜜的方式就是“ Pythonic”。惯用的C ++完全不同。 例如,有时将
lambda
视为不是Python风格的,而是保留给不存在其他解决方案的情况,而只是将其添加到C ++标准中。 C ++没有关键字参数,这是非常Pythonic的。 C ++程序员在不需要时不喜欢构造
map
,而Python程序员可能会在很多问题上抛出
dict
,而恰恰是它们使意图比有效的选择更清晰。 如果要保存键入,请使用我之前发布的功能,然后:
header.version = read_field(edf,8);
header.patinfo = read_field(edf,80);
那应该节省您很多行。但是,与那几行相比,更为重要的是,您已经实现了少量的模块化:如何读取字段以及要读取的字段现在已成为程序的独立部分。     ,您是正确的:按照书面要求,该代码是重复性的(并且没有错误检查)。阅读的每个字段实际上都需要您采取三到五个步骤,具体取决于要读取的数据类型: 从信息流中读取字段 确保读取成功 解析数据(如有必要) 确保解析成功(如有必要) 将数据复制到目标位置 您可以将所有这三个函数包装到一个函数中,以使代码减少重复。例如,考虑以下功能模板:
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,sz))
        throw std::runtime_error(\"Failed to read from stream\");

    result = std::string(&data[0],sz);
}
现在,您的代码可以更加简洁:
ReadFixedWidthFieldFromStream(edf,header.version,8);
ReadFixedWidthFieldFromStream(edf,header.patinfo,80);
ReadFixedWidthFieldFromStream(edf,header.recinfo,80);
// etc.
    ,此代码简单,简单且易于理解。如果它可以正常工作,请不要浪费时间进行更改。我敢肯定,有很多写得不好,复杂且难以理解(并且可能不正确)的代码应该首先修复:)     ,Python的Zen并未明确提及DRY。
>>> import this
The Zen of Python,by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren\'t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity,refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you\'re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain,it\'s a bad idea.
If the implementation is easy to explain,it may be a good idea.
Namespaces are one honking great idea -- let\'s do more of those!
    ,要直接从字符串中读取文件,请参阅此问题,其余的是错误的。但我个人认为这是一种更好/更清洁的方法。 如果知道结构的大小不使用字符串,请使用原始C类型(并确保结构已打包)。请参阅以下链接:http://msdn.microsoft.com/zh-cn/library/2e70t5y1(v=vs.80).aspx和http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc /Type-Attributes.html 我将以这种方式进行操作(例如,不确定每个字符串的大小,但您会明白的):
struct Header {
    char version[8];
    char patinfo[80];
    char recinfo[80];
    char start_date[8];
    char start_time[8];
    int header_bytes;
    char reserved[44];
    int nrecs;
    double rec_duration;
    int nchannels;
};
一旦有了打包结构,就可以直接从文件中读取它:
struct Header h;
edf.read(&h,sizeof(struct Header));
对我来说,这是最干净的方法,但是请记住,您必须打包好结构,以确保内存中的结构与文件中保存的结构具有相同的大小-这在这段时间内很难看到测试。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res