免费注册 查看新帖 |

Chinaunix

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

[C] C语言连接两个字符串最好的方法是什么? [复制链接]

论坛徽章:
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
21 [报告]
发表于 2009-10-08 15:52 |只看该作者
原帖由 deadlylight 于 2009-10-8 12:45 发表


明显sprintf更低效

看跟谁比。sprintf不仅是一个串接函数,更重要的是格式转换,效率稍低,我们也试图找一些能够取代它的方法。
但是,非常奇怪,我也没想到,它竟然比strcat和strlen效率高,因此在这里通告大家试试看,先不要想当然。

我们这里有一位资深老弟,特喜欢说:。。。。那绝对是。。。。。。。
可是事情真的不那么绝对。

[ 本帖最后由 yulihua49 于 2009-10-8 15:55 编辑 ]

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-07-07 06:20:00
22 [报告]
发表于 2009-10-09 08:35 |只看该作者
不知道sprintf是怎么执行的
有没有人贴下sprintf和strcat的源码,对比下看看

论坛徽章:
1
寅虎
日期:2014-11-30 21:25:54
23 [报告]
发表于 2009-10-09 11:12 |只看该作者
看看 Linux 的实现代码 lib/string.c
char *strcat(char *dest, const char *src)
{
    char *tmp = dest;

    while (*dest)
        dest++;
    while ((*dest++ = *src++) != '\0')
        ;
    return tmp;
}

论坛徽章:
0
24 [报告]
发表于 2009-10-09 11:18 |只看该作者
最高效的
char *strcat(char *d, char *s)
{
    char *d0 = d;
    strcpy(d + strlen(d), s);
    return d0;
}

论坛徽章:
0
25 [报告]
发表于 2009-10-09 16:55 |只看该作者
原帖由 yulihua49 于 2009-10-8 15:52 发表

看跟谁比。sprintf不仅是一个串接函数,更重要的是格式转换,效率稍低,我们也试图找一些能够取代它的方法。
但是,非常奇怪,我也没想到,它竟然比strcat和strlen效率高,因此在这里通告大家试试看,先不要 ...


这真的是非常奇怪
你是怎么证明sprintf更高效的呢?或者你是从哪里看来得呢

论坛徽章:
0
26 [报告]
发表于 2009-10-09 17:26 |只看该作者
glic中

#define vsprintf(s, f, a) INTUSE(_IO_vsprintf) (s, f, a)

/* Write formatted output into S, according to the format string FORMAT.  */
/* VARARGS2 */
int
__sprintf (char *s, const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = vsprintf (s, format, arg);
  va_end (arg);

  return done;
}

# define INTUSE(name) name##_internal

int
__IO_vsprintf (char *string, const char *format, _IO_va_list args)
{
  _IO_strfile sf;
  int ret;

#ifdef _IO_MTSAFE_IO
  sf._sbf._f._lock = NULL;
#endif
  _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
  _IO_JUMPS ((struct _IO_FILE_plus *) &sf._sbf) = &_IO_str_jumps;
  _IO_str_init_static_internal (&sf, string, -1, string);
  ret = INTUSE(_IO_vfprintf) ((_IO_FILE *) &sf._sbf, format, args);
  _IO_putc_unlocked ('\0', (_IO_FILE *) &sf._sbf);
  return ret;
}

看不懂。

[ 本帖最后由 wangdan1600 于 2009-10-9 17:28 编辑 ]

论坛徽章:
0
27 [报告]
发表于 2009-10-12 12:09 |只看该作者
原帖由 yulihua49 于 2009-10-8 15:52 发表

看跟谁比。sprintf不仅是一个串接函数,更重要的是格式转换,效率稍低,我们也试图找一些能够取代它的方法。
但是,非常奇怪,我也没想到,它竟然比strcat和strlen效率高,因此在这里通告大家试试看,先不要 ...


事实证明你的说法是错误的
sha-iptv-lnx1:/tmp$ cat test1.c
#include<stdio.h>

int main()
{
    int i;
    char a[10] = "abcd";
    char b[10] = "1234";
    char buf[50];
    for( i = 0; i < 0xffffff; i++ )
    {
        buf[0] = 0;
#ifdef STR
        strcat( buf, a );
        strcat( buf, b );
#else
        sprintf( buf, "%s%s", a, b );
#endif
    }
    return 0;
}
sha-iptv-lnx1:/tmp$ gcc test1.c -o pri ; gcc -DSTR test1.c -o str
sha-iptv-lnx1:/tmp$ time ./str

real    0m0.363s
user    0m0.362s
sys     0m0.001s
sha-iptv-lnx1:/tmp$ time ./pri

real    0m3.224s
user    0m3.215s
sys     0m0.001s

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
28 [报告]
发表于 2009-10-12 12:47 |只看该作者
原帖由 langue 于 2009-9-20 00:44 发表
通常说来,C 假定程序员具有自理能力。像预先控制好缓冲区大小一类的事,C 程序员应该是驾轻就熟的。
所以,strcat(dest, src); 这样的用法应该是常态。
如果你实在担心,倒是可以用 strncat(),或者 strlcat()。

strlcat不知是何物?

论坛徽章:
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
29 [报告]
发表于 2009-10-13 15:50 |只看该作者
原帖由 deadlylight 于 2009-10-12 12:09 发表


事实证明你的说法是错误的

事实证明你的说法是片面的:
tuxticket@jgbticket:~/log> vi t.c
#include<stdio.h>
#include<string.h>
//#define STR
int main()
{
    int i,j;
    char a[] = "abcdwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";
    char buf[50000];
    char *p;

    for( i = 0; i < 0xfffff; i++ )
    {
        buf[0] = 0;
        p=buf;
        for(j=0;j<50;j++)  {
#ifdef STR
             strcat(buf,a);
             strcat(buf,"|");
#else
             p+=sprintf( p, "%s|", a);
#endif
        }
    }
    return 0;
}

~
~
~
~
~
~
~
"t.c" 26L, 501C written                                                                                    
tuxticket@jgbticket:~/log> cc t.c
tuxticket@jgbticket:~/log> time ./a.out
sprintf:

real    0m12.307s
user    0m12.305s
sys     0m0.004s

strcat:
real    1m41.789s
user    1m41.786s
sys     0m0.000s



这里模拟了读1000000记录,每个记录50个字段,这些内容打包。
还有更惨的,我们不断realloc,不断增加结果的长度,把所有记录打包在一个串里,sprintf仍然12秒左右,而strcat出不来了,死兜不知到什么时候。

[ 本帖最后由 yulihua49 于 2009-10-13 15:59 编辑 ]

论坛徽章:
0
30 [报告]
发表于 2009-10-14 11:03 |只看该作者
你这种做法明显是错误的,你对sprintf程序做了优化,但是strcat程序却没有优化

strcat的时候,每次都要找到src的结尾,然后再拼接,这样的话时间花在找到src的长度上
而你的sprintf程序确是每次给p直接指向结尾,这样就不需要找到长度
如果公平,你应该用sprintf(p, "%s|%s", p, a)

或者改进一下strcat程序
cat test.c ;gcc  test.c -o 1; gcc -DSTR test.c -o 2;time ./1 ; time ./2
#include<stdio.h>
#include<string.h>
int main()
{
    int i,j;
    char a[] = "abcdwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";
    char buf[50000];
    char *p;
    int len = 0;
    int len1 = strlen( a );
    int len2 = strlen( "|" );

    for( i = 0; i < 0xfffff; i++ )
    {
        buf[0] = 0;
        p=buf;
        for(j=0;j<50;j++)  {
#ifdef STR
            strcat(p,a);
            p += len1;
            strcat(p,"|");
            p += len2;
#else
            p+=sprintf( p, "%s|", a);
#endif
        }
    }
    return 0;
}

real    0m8.432s
user    0m8.431s
sys     0m0.000s

real    0m2.780s
user    0m2.778s
sys     0m0.002s


[ 本帖最后由 deadlylight 于 2009-10-14 11:05 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP