免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 64042 | 回复: 33
打印 上一主题 下一主题

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

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-07-07 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-19 11:18 |只看该作者 |正序浏览
有人说这事Unix上最标准的做法,但我觉得会不会有问题?
FreeBSD+gcc3.4.2
$FreeBSD: src/lib/libc/string/strcat.c,v 1.7 2002/09/06 11:24:06 tjr Exp $

#include <string.h>

char *
strcat(char * __restrict s, const char * __restrict append)
{
char *save = s;

for (; *s; ++s);
while ((*s++ = *append++));
return(save);
}
       
按照这种做法,如果在char *svae结束后的内存中有数据,是不是就被覆盖了?

论坛徽章:
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
34 [报告]
发表于 2009-10-16 13:01 |只看该作者
原帖由 yulihua49 于 2009-10-14 14:07 发表

技术处理方法,谈不上公平不公平。两种方法,适用不同场合,我也没说不用strcat啊!
你的例子当然是strcat好,我在那样一种需求下当然用效率最高的方法,谁会为了公平采用低效方法呢?

还有,你的例子,l ...

找到一个函数:stpcpy(),返回尾。
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=stpcpy( p, a);
             *p++='|';
             *p=0;
#endif
        }
    }
    return 0;
}



real    0m3.413s
user    0m3.412s
sys     0m0.000s


比sprintf快3倍多。

打听一下,不用sprintf,有什么办法把整数或浮点数转换成字符串?

[ 本帖最后由 yulihua49 于 2009-10-16 14:24 编辑 ]

论坛徽章:
0
33 [报告]
发表于 2009-10-14 15:39 |只看该作者
原帖由 ecjtubaowp 于 2009-10-12 12:47 发表

strlcat不知是何物?

http://linux.die.net/man/3/strlcat

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

恩,这个我同意,C语言设计的时候就认为这些问题程序员应该自己去解决,这也是很多人认为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
31 [报告]
发表于 2009-10-14 14:07 |只看该作者
原帖由 deadlylight 于 2009-10-14 11:03 发表
你这种做法明显是错误的,你对sprintf程序做了优化,但是strcat程序却没有优化

strcat的时候,每次都要找到src的结尾,然后再拼接,这样的话时间花在找到src的长度上
而你的sprintf程序确是每次给p直接指向 ...

技术处理方法,谈不上公平不公平。两种方法,适用不同场合,我也没说不用strcat啊!
你的例子当然是strcat好,我在那样一种需求下当然用效率最高的方法,谁会为了公平采用低效方法呢?

还有,你的例子,len1,len2事先算出来了,纯粹是为了比试,实际上,每个记录的每个字段是不等长的。
既然串尾都知道了,strcpy就行了,何必strcat?

建议,不是针对你,提供返回串尾的strcpy。

回贴主,各种场合各自有不同的最优方法,没有一定之规。

[ 本帖最后由 yulihua49 于 2009-10-14 14:17 编辑 ]

论坛徽章:
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 编辑 ]

论坛徽章:
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 编辑 ]

论坛徽章:
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不知是何物?

论坛徽章:
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

论坛徽章:
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 编辑 ]
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP