免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Patagonia
打印 上一主题 下一主题

[C++] 关于C语言,我喜欢和讨厌的十件事 [复制链接]

论坛徽章:
0
61 [报告]
发表于 2013-11-25 14:55 |只看该作者
本帖最后由 u010402865 于 2013-11-25 15:02 编辑
yulihua49 发表于 2013-11-25 14:21
这不,问题来了:
http://bbs.chinaunix.net/thread-4112117-1-1.html


这个问题很好解决啊,我在前面也说了,以结构体大小为单元写入二进制文件,读取时再以结构体大小为单元读到结构体变量里就行啊。如果担心不同系统的字节对齐差异,就用#pragma pack设置为同样的字节对齐。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
62 [报告]
发表于 2013-11-25 19:55 |只看该作者
本帖最后由 yulihua49 于 2013-11-25 20:02 编辑
u010402865 发表于 2013-11-25 14:55
这个问题很好解决啊,我在前面也说了,以结构体大小为单元写入二进制文件,读取时再以结构体大小为单元 ...

还是改在这里讨论把:
跨平台只是举个例子,还有方方面面的工作与通用结构处理有关。
你用数据库吗?对每个SQL语句都要做一大套类似的繁琐的操作,反感吗?
如果每个SQL语句都对应一个结构,里边有结果集变量,查询条件变量,要插入或修改数据库的变量,用一个公用的程序处理这些变量是不是会方便许多?
那么这个公用程序怎么写呢?他怎么知道你结构里有啥?SQL语句里哪个变量对应结构的哪个变量?这个又需要反射了。
看看我这个帖,虽然挨了不少骂,但是工作进展到现在是极为成功的。
http://www.itpub.net/thread-1088197-1-1.html
将数据库的使用简化到极致,性能也高到极致。

论坛徽章:
0
63 [报告]
发表于 2013-11-25 21:39 |只看该作者
yulihua49 发表于 2013-11-13 12:22
转帖的吧?
最有感触的是:C没有反射。


只要在struct 的固定位置包含一个函数指针即可,很容易实现的。

typedef *struct2json_fun(void *);

typedef
struct stA
{
    void * struct2json_fun;
    int var1;
    int var2;
} A;

typedef
struct stB
{
    void * struct2json_fun;
    int var3;
    int var4;
} B;

char * A2json(A* a)
{
     ....;
}

A* createA()
{
     A *p = malloc(sizeof(A));
    p->struct2json_fun= A2json;
    return p;
}


char * B2json(B* a)
{
     ....;
}

B* createB()
{
     B *p = malloc(sizeof(B));
    p->struct2json_fun= B2json;
    return p;
}

char * struct2json(void * st)
{
     struct2json_fun p = *(struct2json_fun *)st;
     return p(st);
}

论坛徽章:
0
64 [报告]
发表于 2013-11-26 10:32 |只看该作者
yulihua49 发表于 2013-11-25 19:55
如果每个SQL语句都对应一个结构,里边有结果集变量,查询条件变量,要插入或修改数据库的变量,用一个公用的程序处理这些变量是不是会方便许多?
那么这个公用程序怎么写呢?他怎么知道你结构里有啥?SQL语句里哪个变量对应结构的哪个变量?这个又需要反射了。 ...


不合理的需求导致蹩脚的设计。把SQL语句再用结构体封装,有这个必要么?看你的这个需求,我认你应该好好考虑用函数把SQL语句封装,而不是用结构体和所谓的反射。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
65 [报告]
发表于 2013-11-26 11:52 |只看该作者
本帖最后由 yulihua49 于 2013-11-26 12:01 编辑
boyatchinaunix 发表于 2013-11-25 21:39
只要在struct 的固定位置包含一个函数指针即可,很容易实现的。

typedef *struct2json_fun(void *); ...

可以啊,面向对象。
但是,这形不成通用程序,依然是每种结构两个程序,一个序列化,一个反序列化。
如果只是简单的按成员处理,未尝不可。

但是,复杂的,如与SQL互相映射,这个法子等于没有给用户任何帮助。(你没有提供通用的SQL处理解决方案,还是每个都自己写)。

下题,你怎么做:
  1.         for(rows=0;!ferror(ifd);rows++) {
  2.                 fgets(buf,buflen,ifd);//读出一行
  3.                 if(feof(ifd)) break;
  4.                  ret=DAU_pkg_dispack(&_DAU,buf,dlmt);//反序列化到DAU里的struct
  5.                 *buf=0;
  6.                 ret=DAU_insert(&_DAU,buf);// 将数据插入数据库,buf用于产生SQL语句
  7. //......
复制代码
那个插入数据库的函数,你怎么做?
数据库表是运行时指定的,文件是与之匹配的。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
66 [报告]
发表于 2013-11-26 12:04 |只看该作者
本帖最后由 yulihua49 于 2013-11-26 12:40 编辑
u010402865 发表于 2013-11-26 10:32
不合理的需求导致蹩脚的设计。把SQL语句再用结构体封装,有这个必要么?看你的这个需求,我认你应该好好 ...

这个值得讨论。
SQL面对的不是一个数据,是二维数据集,由行和列组成。
他的处理比较繁琐。我们希望能够写一组通用处理,能够处理任何表和多表的SQL。
这些个函数,你不可能使用离散的变量在函数内外传递数据。因为你连运行时人家用那个表,那个语句,要多少变量都不知道。
例如,楼上的那个DAU_insert,它是要绑定变量的,哪个表?有多少变量?各什么类型,多大,在哪?
所以,要使用集合型数据接口。
C有哪些集合型数据?一个数组,一个结构,你说用哪种接口?
参照JAVA的Hibernate,一个ORM,建议你了解一下这个东东。它采用Object接口,Object,其实就是扩展的struct。
数据库,读出来是要用的,你用struct接口,就很方便,就跟你说的二进制文件接口一样,读出即可用。
其实当年所想,跟你是一模一样的,像读写记录文件一样的读写数据库。
现在,我做到了。
那个DAU_insert,与write,是否异曲同工?这个需求不合理妈?
实际上,那个DAU,Data Access Unit,就是把模板和结构组装在一起,你理解,就是一个可反射的结构。
看看上贴的4,6行,反射,方便吗,设计,蹩脚吗?
前边给你的链接就是它的开发历程。没有提及内部例程,太多,太复杂。有反射,何至于此?
此后,我们,所有的关于数据库的应用项目,一律DAU,再也不用写SQL语句了。
方便快捷的开发效率,和几近极限的运行效率,使我们受益匪浅。




论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
67 [报告]
发表于 2013-11-26 12:51 |只看该作者
本帖最后由 yulihua49 于 2013-11-26 13:28 编辑
u010402865 发表于 2013-11-26 10:32
不合理的需求导致蹩脚的设计。把SQL语句再用结构体封装,有这个必要么?看你的这个需求,我认你应该好好 ...

给你看一个我最近的项目,还没有完的。
把一个,你所说的,包装SQL的应用,改造成DAU的应用。
原因是,原来的性能太低,内存泄漏,不能移植到其他数据库。新的解决这3个问题。
注释的部分是原来的程序,可对比一下:
  1. bool CDataParameter::loadCardType()
  2. {
  3. CD_YKT_APPLICATION_MODE_stu rec;
  4. CD_YKT_FARE_CARD_TYPE_stu f_rec;
  5. int ret;
  6. char stmt[4096],*p;
  7. DAU q_DAU,f_DAU;

  8.         DAU_init(&q_DAU,m_DbConnect,NULL,&rec,CD_YKT_APPLICATION_MODE_tpl);//把结构和模板组装在一起,形成可反射的‘对象’
  9.         DAU_init(&f_DAU,m_DbConnect,NULL,&f_rec,CD_YKT_FARE_CARD_TYPE_tpl);
  10. /*
  11.         //输出调试信息
  12.           CsVerbose("Begin ApplicationMode:     %s\n", "");//KTH 20101005 增加提示信息
  13.         CsDebug( YKT_DBG_CONN, ( YKT_DBG_CONN, "Query table:     '%s'.\n", "CD_YKT_APPLICATION_MODE" ) );

  14.         //查询数据
  15.         std::ostringstream sql;
  16.         sql     << "SELECT t.MODE_ID FROM afc_cd.CD_YKT_APPLICATION_MODE t "
  17.                 << AppendWhere()
  18.                 << "ORDER BY t.MODE_ID ASC";
  19.         StructuredQuery q("CD_YKT_APPLICATION_MODE");
  20.         StructuredQueryResultset r;

  21.         add_column<SQUInt>              ("MODE_ID", q);

  22.         do_query(sql.str().c_str(), q, r, *(GetConnect()->datasource()));//,GetSid());

  23.         if(r.size() > 0)
  24.         {
  25.                 for(StructuredQuery* row = r.getFirstRow(); row; row = r.getNextRow())
  26.                 {
  27.                         DataApplicationMode ApplicationMode;
  28.                         ApplicationMode.modeID = extract<uint32, SQUInt>(row->getFirstColumn());

  29.                         //根据每一个ModeID,继续查询数据
  30.                         CsDebug( YKT_DBG_CONN, ( YKT_DBG_CONN, "Query table:     '%s'.\n", "CD_YKT_FARE_CARD_TYPE" ) );
  31.                         std::ostringstream sqlCardType;
  32.                         sql.str("");
  33.                         sql     << "SELECT t.CARD_PHYSICAL_TYPE, t.CARD_LOGICAL_TYPE, t.CARD_TYPE_NAME, t.CARD_ATTRIBUTE FROM afc_cd.CD_YKT_FARE_CARD_TYPE t "
  34.                                 << AppendWhere();

  35.                         StructuredQuery qCardType("CD_YKT_FARE_CARD_TYPE");
  36.                         StructuredQueryResultset rCardType;

  37.                         add_column<SQUInt>              ("CARD_PHYSICAL_TYPE", qCardType);
  38.                         add_column<SQUInt>              ("CARD_LOGICAL_TYPE", qCardType);
  39.                         add_column<SQString>            ("CARD_TYPE_NAME",160, qCardType);
  40.                         add_column<SQUInt>              ("CARD_ATTRIBUTE", qCardType);

  41.                         do_query(sql.str().c_str(), qCardType, rCardType, *(GetConnect()->datasource()));//,GetSid());

  42.                         ApplicationMode.cardTypeNum = rCardType.size();
  43.                         if(rCardType.size() > 0)
  44.                         {
  45.                                 for(StructuredQuery* row = rCardType.getFirstRow(); row; row = rCardType.getNextRow())
  46.                                 {
  47.                                         DataCardType CardType;
  48.                                         CardType.physicalType = extract<uint32, SQUInt>(row->getFirstColumn());
  49.                                         CardType.logicalType = extract<uint32, SQUInt>(row->getNextColumn());
  50.                                         std::string name = (std::string&)extract<std::string, SQString>(row->getNextColumn());

  51.                                         //中文名进行编码转换
  52.                                         char strName[30];
  53.                                         memset(strName,0,sizeof(strName));
  54.                                         strcpy(strName,name.c_str());
  55.                                         utf8togb2312Ykt(strName,30,CardType.cardTypeName,16);
  56.                                         CardType.cardAttribute = extract<uint32, SQUInt>(row->getNextColumn());

  57.                                         ApplicationMode.vDataCardType.push_back(CardType);
  58.                                 }
  59.                         }

  60.                         m_DataApplicationMode.push_back(ApplicationMode);
  61.                 }
  62.         }
  63. */
  64.         rec.parameter_ver=(INT64)m_version;
  65.         p=mk_where("parameter_ver",stmt);
  66.         p=stpcpy(p," ORDER BY MODE_ID ASC");
  67.         ret=DAU_select(&q_DAU,stmt,0);
  68.         if(ret>0) {
  69. //根据每一个ModeID,继续查询数据 -- 笛卡尔积
  70.             DataCardType CardType;
  71.                  DataApplicationMode ApplicationMode;

  72.                 f_rec.parameter_ver=m_version;
  73.                 mk_where("parameter_ver",stmt);
  74.                 while(!DAU_next(&q_DAU)) {
  75.                         ApplicationMode.modeID = (U32_t)rec.mode_id;
  76.                         ret=DAU_prepare(&f_DAU,stmt);
  77.                         if(ret==0) while(!DAU_next(&f_DAU)) {
  78.                                 CardType.physicalType = (U32_t)f_rec.card_physical_type;
  79.                                 CardType.logicalType = (U32_t)f_rec.card_logical_type;
  80.                                 CardType.cardAttribute = (U32_t)f_rec.card_attribute;
  81. //中文名进行编码转换
  82.                                 utf8togb2312Ykt(f_rec.card_type_name,strlen(f_rec.card_type_name),
  83.                                         CardType.cardTypeName,16);
  84.                                 ApplicationMode.vDataCardType.push_back(CardType);
  85.                         }
  86.                 }
  87.         }

  88.         DAU_free(&q_DAU);
  89.         DAU_free(&f_DAU);
  90.         return true;
  91. }
  92.    
复制代码
它定义的数据结构与数据库有差异,否则我还可以减少不少语句。

论坛徽章:
0
68 [报告]
发表于 2013-11-26 13:16 |只看该作者
本帖最后由 boyatchinaunix 于 2013-11-26 13:18 编辑

回复 66# yulihua49


   
Java 用的多了,没转换过来思维吧?即便有这样的函数,那底层呢?不也还是要转换为SQL?何来高效?

C就像手动档的汽车。
Java就像自动档的汽车,不要把手动档的按自动档的方法开。

论坛徽章:
0
69 [报告]
发表于 2013-11-26 13:31 |只看该作者
yulihua49 发表于 2013-11-26 12:04
这个值得讨论。
SQL面对的不是一个数据,是二维数据集,由行和列组成。
他的处理比较繁琐。我们希望能够 ...



在性能方面Hibernate是低下的,Hibernate解决的是业务需求频繁变化,数据库频繁改动的问题。
你的函数设计的也不太好,一个函数试图解决不同层面问题,结果if for 相互嵌套了多层,看到这些我就头晕。
如果你只是要跨各种数据库平台,推荐你用apr-util,apache下的开源项目,里面封装了各种数据库的调用接口。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
70 [报告]
发表于 2013-11-26 13:32 |只看该作者
boyatchinaunix 发表于 2013-11-26 13:16
回复 66# yulihua49

no 本人玩半辈子C了,JAVA,因团队需要,不得不接触一些,生的很。不过很受启发。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP