终于有了间茅草棚

——我走时,会否有随风飘散的痕迹?

外面的风好大,雨也淅淅沥沥的。

世间种种的诱惑不惊不扰我清梦,山高路远不绝我追踪你绝美的笑容,登高一呼时才懂始终在为你心痛,俯首对花影摇动都是东风在捉弄

世间种种的迷惑都是因你而猜错,水光月光又交融描述这朗朗的夜空,生死到头的相从似狂花落叶般从容,当一切泯灭如梦就在远山被绝
随笔 - 42, 文章 - 2, 评论 - 269, 引用 - 3

导航

<2010年3月>
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

留言簿(10)

随笔档案

文章档案

收藏夹

其它的我

友情连接

网页连接

搜索

最新评论

  • 1. re: 陈刚
  • 中间件主要的好处在于便于整合,就像一个接口规范和标准。像游戏开发中3D图形技术有两套,有的游戏直接基于D3D或OenGL开发,现在更多的是基于一些图形引擎,像Ogre,Irrlicht等,在这些图形引擎下面去和具体的图形API打交道,从这个意义上来说Ogre和Irrlicht拥有一定的中间件的涵义(这些图形引擎不只是中间层,还包含有场景管理、渲染逻辑等更多内容)。加了这样一层后,当支持新的D3D10和D3D11时,中间层作出修改,原应用不需要修改就可运行,还有移植到支持OpenGLES的设备时,也是可行的。
  • --清风雨
  • 2. re: linux常见开发问题,.JPEG parameter struct mismatch
  • 你说的3.JPEG parameter struct mismatch没看明白,我现在也遇到了同样的问题,
    ”编译libjpeg的make文件里定位输出生成jpeg的地方“指的是哪啊,
    “打印出相关参数”也不明白
    “前台运行同样的./configure”什么意思?
    帮帮我了,谢谢!我邮箱litao_hao@16.com   qq;40362095
  • --haolitao
  • 3. re: linux移植建议
  • 这个学习了
  • --陈刚
  • 4. re: 软件开发模式猜测
  • 脚本在其可配置性、可扩展性上性能应该是已经超越了中间件技术。

    中间件在对其扩展、更新、配置时不知是否能做到依赖它的程序不中断运行呢
  • --陈刚
  • 5. re: 软件开发模式猜测
  • 对 “中间件模式” 还真不太了解。 

    不知 “中间件模式” 是否会影响运行、调试以及维护成本,以及如何能抽象出中间层?
  • --陈刚
  • 6. re: void *几用
  • class Sample
    {
    public:
        void draw( void *g );
    };

    我个人其实并不太认同这种做法,虽然实现了抽象但会加大维护代价
  • --陈刚
  • 7. re: 用自己的话浅谈封装
  • 封装也是一个不断完善的过程,当然再经过一段时间后随着技术的进步思想的成熟,也会推翻重来。
  • --陈刚
  • 8. re: linux常见开发问题
  • xargs不错,蛮有用的。
  • --hATEmATH的网上田园
  • 9. re: 关于“元编程”的浅思考
  • --免费打工仔
  • 10. re: 关于质数(素数)的算法

  • 是AKS方法。
    http://mathworld.wolfram.com/AKSPrimalityTest.html


  • --perry
  • 11. re: 关于质数(素数)的算法
  • 为了在数字比较小时计算得快些,可以应用一些初等数论的结论:

    1]
    仅计算6n+1和6n+5(n=1,2,3,...)形式的数。易知6n+2和6n+4是2的倍数,6n+3是3的倍数。因为2和3的倍数最多。
    2]
    根据“合数的最大的素因数都不大于它的平方根”定理,每次分解仅算到被分解的平方根为止即可。
    证明(一般的证明都不完整):
    设N=P*Q,P和Q是N的不少于1个素因数的乘积(指出这点很重要)。反证法可证P和Q都小于或等于N的平方根(否则P*Q>N)。等号当且仅当P=Q=N的平方根时成立(这时N是一个素数的平方)。

    1]可减少2/3的计算量,2]可再减少1/2的计算量。即为原计算量的1/6。

    几百位数位的数,建议采用ASK方法。





  • --perry
  • 12. re: 关于质数(素数)的算法

  • 素因数分解是一个NP问题。
  • --perry
  • 13. re: 关于质数(素数)的算法
  • 1121=19*59
  • --李圆欢
  • 14. re: void *几用
  • 方法都不错
  • --员工生日礼物
  • 15. re: void *几用
  • to oshj:
    最近才悟道这个用法,没想到你都用了很多了。

    to brent:
    不是为了玩才玩,这里每种用法在特定的情况下,都有他相应的好处。不过,我是做为自己记录的,指不定什么时候就忘记了,还可以这么用。
    1. 可以使得头文件简单,而且出于实现保密的需要,还是很有用处的。
    2. 很多时候对象本身应该简洁,但往往应对不同的需要,通常需要数据对应。举个例子,比如玩家在哪个房间,在哪个房间最好不要直接记在玩家身上,用数据注入的方式,能够很快的获得该信息。
    3. 因为是做为库暴露头文件的,使用者并不关心void *的实际意义,而且能够加快编译速度。真正要关心时,就Graphics.h这个头文件是不够的,通常会需要了解整底层个实现,才能较好的扩充。
  • --清风雨

阅读排行榜

评论排行榜

关于几个C字符串库函数的思考

今天很偶然的注意到int sprintf( char *buffer,const char *format [,argument] ... );这个定义。

我们知道:
1.char *str;就是定义一个字符指针,一般用来表示字符串(它指向字符串的首字符);
2.字符串都是以'\0'结尾表示的;
3.C里面表示内存块指针一般用void *;


第一个问题:
那么,如果单从函数来看buffer应该是是一个字符串,但是实际使用仅仅只是一个用来存结果数据的缓存(内存块)。也即:
char buf[16];///仅仅是一块缓存
sprintf( buf,”%s”,”content” );
而不是
char buf[16] =””;///字符串,有'\0'结尾
sprintf( buf,”%s”,”content” );
那么是不是应该这样定义更好?——int sprintf( void *buffer,const char *format [,argument] ... );
类似的函数还有strcpy、strncpy。



第二个问题:
char *strncpy( char *strDest,const char *strSource,size_t count );将源字符串copy多少个到缓存strDest。如果count大于strSource的长度,会自动给strDest补零;但是,如果小于等于strSource的长度呢?那么就没有补零的操作了,也就是返回的并不是一个'\0'结尾的字符串了。
如果仅仅这个功能,完全可以memset了0,然后再memcpy的,而且这样的效率也要比用strncpy的高。
为什么不是要求strDest的大小必须大于等于count+1呢?那么当copy了count个字符后,自动尾上补零,确保肯定是一个字符串。这才肯定是字符串操作,而且功能也不重复。

posted on 2005-06-21 20:43 终于有了间茅草棚 阅读(3682) 评论(15)  编辑 收藏

评论

# re: 关于几个C字符串库函数的思考

第一个:
sprintf最终会给那个buf补\0使它从成为一个名副其实的字符串。
第二个:
个人几乎没用过strncpy,感觉这是个类似replace的功能,把字符串的某个部分有限制的替换为另一个,而串的其他部分保持不变。
2005-06-21 21:05 | pAnic

# 不是你的这个意思

第一个:
作为char *参数时,就会被理解为要传递的参数是字符串,也就'\0'的,但是传递的并没有这个要求。
但是char *strcat( char *strDestination,const char *strSource );的第一个参数就必须是'\0'的字符串。
所以,我觉得它有点混淆。
第二个:
不是replace的功能,是strcpy的补充(不知道我这么说,有没人反对)。要替换字符串里面某个字符好像只能strstr或strchr的返回来修改指针所指内存的值(strlwr和strupr也会修改):
char *source = "abchefg";
char *tmp = strchr( source,'h' );
tmp[0] = 'd';
2005-06-21 21:18 | 清风雨

# 我的看法如下:

1) sprintf()主要目的是用来构造字符串的,这样构造出的字符串可以用于输入给输入输出流、传给串口、传给其他字符串处理函数。用void * buffer到也确实能够使用,但是每次传给其他字符串处理函数之后,都要先显式转型为(char*)才能使用,岂不是很麻烦?况且,从构造字符串的目的来说,使用void * buffer倒是走了弯路,设计的太不精巧。

2) memcpy()使用字符数组的方式来操作对象,主要目的是提供一个高效的函数接口。因此memcpy()中认为传递的参数都不会越界,对count也不做检查。对比一下两个函数的实现:

// vc6.0 source
void * __cdecl memcpy (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;
        /*
         * copy from lower addresses to higher addresses
         */
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }
        return(ret);
}
// vc6.0 source
char * __cdecl strncpy (
        char * dest,
        const char * source,
        size_t count
        )
{
        char *start = dest;

        while (count && (*dest++ = *source++))    /* copy string */
                count--;

        if (count)                              /* pad out with zeroes */
                while (--count)
                        *dest++ = '\0';

        return(start);
}

strncpy()设计的更复杂,也更通用,所以通常的字符串操作应该用它。memcpy()则一般用于大块的内存复制,高效而不安全。如果要使memcpy()执行的安全,而又达到strncpy()的功能,势必要在使用前比较strlen(strDest)、strlen(strSource)和count三者的大小。strlen()要遍历整个字符串才能确定它的长度,效率低下,所以使用memset()和memcpy()来实现strncpy()实属不智。

2005-06-21 22:58 | 乾坤一笑

# re: 关于几个C字符串库函数的思考

1。sprintf的作用就是构造一个字符串,那么当然它传出(注意这个"出")的也应该是一个字符串。
2。如果你定义一些持久存储结构,或为其他设备写数据接口,你就会经常遇到这个问题。C++中定义的字符串是以'\0'结尾的字符数组,但这个定义不适合持久存储结构,比方就说数据库,比如8位的字符串,用它自己的字符串定义(注1),它最多可以保存8个字符,而用C++中字符串的定义,它最多只能保存7个字符。我经常为其他设备写数据接口,这就是我的工作嘛,从未发现有过非注1之外的特例。仔细看一下注1,和strncpy的行为是不是一致。

[注1]字符串就是从第一个字符起到'\0'或空间结束之间的字符数组,比如char[8],
如果是"123"那么保存内容为 31 32 33 00 ?? ?? ?? ?? ,
如果是"12345678"那么保存内容为 31 32 33 34 35 36 37 38 。
2005-06-22 09:52 | 周星星

# 就一笑的看法

1.我知道这个是个[in,out]参数。
做为使用者,看到char *肯定认为传入'\0'的字符串;做为设计者,更应该考虑使用者的想法。
至于使用场合,更应该是缓存的使用,也即char buf[32],直接传递给sprintf()就不需要转型。
同事有个说法:大家都已经习惯这个(我觉得倒是是我们很少看这个参数申明),即使这个说法恰当(当然,他不这样认为),也不具备意义。哈哈,我记录这个,是为了以后自己或者参考者设计接口时,可以借鉴。
2.一般来说strncpy的使用情况是指定具体的长度(冲的就是这个n去使用的),也就是不需要strlen时。一般需要strlen时,基本都是使用strcpy的。
这里的源码,实际上是编译器实现的思想(注释里叫算法),而不是实际的源码。事实上,memset、memcpy是可能采用DMA加速的(由测试软件对块copy等的测试可知),所以,得出效率要较strncpy高。
2005-06-22 10:09 | 清风雨

# 就星星的说法

第一个,好像基本大家都是焦点放在out上,我却放在in上了。感觉使用接口时,得符合接口的要求(char *就像隐性要我'\0');传出是接口的能力,所以它给我的缓存放了个char *。
第二个,就7、8的问题,直接memcpy也行吧。不'\0',在C里他就不是字符串嘛,我就只作为一个字符数组数据存到数据库嘛!
2005-06-22 10:18 | 清风雨

# to 清风雨:

1。不是[in,out],而是[out]。
明白为什么是char*,而不是void*了吗?

2。效率高低我不知道,我只是想告诉你strncpy为什么“如果count大于strSource的长度,会自动给strDest补零;但是,如果小于等于strSource的长度呢?那么就没有补零的操作了”。
2005-06-22 10:20 | 周星星

# re: to 清风雨:

对的,不是[in,out]参数,只是[out]。不好意思!
2005-06-22 10:47 | 清风雨

# to 清风雨:

从你的话里面看出你还没有看懂我的话。按照你说的,用memset()、memcpy()实现一下strncpy()函数,完成它的全部功能,你就明白我说的意思了。不要用脑子光用想,你亲自做做看,感觉做的没错了放在这里让大家瞧瞧你的代码,最好。
2005-06-22 22:24 | 乾坤一笑

# 好吧!

你上次就说了我表达能力差,理解能力也不好的。^_^

写一下吧!
1:
char buf[32];
const char name[32] = "a name";

strncpy( buf,name,4 );
对应
memcpy( buf,name,4 );
2:
char buf[32];
const char name[32] = "a name";

strncpy( buf,name,8 );
对应
memset( buf,0,32 );
memcpy( buf,name,8 );
///这种确实不是原来的功能了,必需有strlen才能做到
3:
char buf[32];
const char *name = "a name";

strncpy( buf,name,8 );
对应
memset( buf,0,32 );
memcpy( buf,name,8 );
///这种要出错的

除了表达能力差,理解能力也不好,还加两条:懒惰、不深入思考问题!

顺便,你觉得如果第二个问题的方式自己写那一个strncpyEx有意义吗?
2005-06-23 09:18 | 清风雨

# 多谢指出

阁下这句话,我就好意思以后,也贴贴到你那里:感觉做的没错了放在这里让大家瞧瞧你的代码,最好!

虽然,你是不会放我这么低级的错误的。
2005-06-23 09:23 | 清风雨

# to 清风雨 :

让你写出一个strncpy()函数,用memset()、memcpy()去实现,而不是让你分情况、举例子。你举了N种情况,规根到底没有写出你所谓的strncpy()函数,只是空谈而已。

并且从上面你列举的情况,至少有下面三种strncpy()处理情况你没有考虑到:
char dst[8];
const char src1[] = "12345678";
const char src2[] = "1234";

//---- 1
strncpy( dst, src1, 8);
//---- 2
strncpy( dst, src1, 9);
//---- 3
strncpy( dst, src2, 9);


我的观点就是:strncpy()能够简化我们的日常工作,除非是特殊场合,一般来说不应该用memset()、memcpy()来替代它。否则就是出力不讨好——一不小心就出错。
2005-06-23 23:51 | 乾坤一笑

# 你说的很有道理

自己写时就发现了不是自己开始所“空想”的那样了。也就是你说的确实是memset和memcpy去替代是替代不了的(简单、方便、高效的实现而言)。—— 不是实现strncpy。
另外,你认为自己写那一个strncpyEx有意义吗? 也就是我说的,如果copy后自己在结尾补零,有意义吗?就你的认为,实际需要这样的可能性有多大?哪些场合需要?—— 我现在的“空想”是,还是有用,至少对自己的习惯而言是有用。
2005-06-24 09:30 | 清风雨

# re: 关于几个C字符串库函数的思考

如果实际中有这方面的需要做一下也无妨,做通用的库就不必要了吧。:)
2005-06-24 23:34 | 乾坤一笑

# 呵呵!谢谢!

开始自己把这两个函数想错了,进入死角。—— 就觉得它设计有问题了。所以,丢出来看大家有什么意见。
倒是char *strncpy一般我就认为必须返回'\0'的串了(缓存的问题,基本C/C++程序都会注意),然后,又一想,memset/memecpy不是就0和内容了嘛(感觉效率还高)!——还有个长度问题被我一不小心忽略了。
2005-06-25 09:43 | 清风雨
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]