在c中连接多个字符串的更好方法?

时间:2011-05-04 21:07:10

标签: c

有没有更好的方法在c中连接多个字符串,而不是连续多次调用strcat(),如下所示?

char prefix[100] = "";
strcat(prefix, argv[0]);
strcat(prefix, ": ");
strcat(prefix, cmd_argv[0]);
strcat(prefix, ": ");
strcat(prefix, cmd_argv[1]);
perror(prefix);

8 个答案:

答案 0 :(得分:20)

sprintf(prefix,"%s: %s: %s",argv[0],cmd_argv[0],cmd_argv[1]);

snprintf以防止缓冲区溢出。

答案 1 :(得分:10)

snprintf将是最好和最容易使用的选项,虽然它可能不是“快”。你没有说明你的标准是什么。简单来说,这绝对是这样的:

snprintf(prefix, sizeof(prefix), "%s: %s: %s", argv[0], cmd_argv[0], cmd_argv[1]);

答案 2 :(得分:4)

我可能会因此受到重击,但是到底是什么。可能发生的最糟糕的事情是我会学到一些东西。

这些天我真的不使用C,而且我通常不会在C ++中使用C风格的字符串。但我有一个想法是编写一个修改后的strcpy(),它返回字符串的结尾:

char* my_strcpy(char*dest, const char* src)
{
    while ((*dest = *src++))
        ++dest;
    return dest;
}

现在Shlemiel可以随身携带他的水桶:

char prefix[100] = "";
char* bucket = my_strcpy(prefix, argv[0]);
bucket = my_strcpy(bucket, ": ");
bucket = my_strcpy(bucket, cmd_argv[0]);
bucket = my_strcpy(bucket, ": ");
bucket = my_strcpy(bucket, cmd_argv[1]);
perror(prefix);

我没有测试过这个。评论

编辑:删除了不必要的my_strcat()函数。此外,它与stpcpy()相同,截至2008年,它显然是POSIX的一部分。请参阅http://www.manpagez.com/man/3/stpcpy/

答案 3 :(得分:4)

我会像其他人建议的那样使用sprintf(),但这是为了完整性:

如果你有stpcpy(),那么你可以这样做:

char prefix[100] = "";
stpcpy(stpcpy(stpcpy(sptcpy(stpcpy(prefix, argv[0]), ": "),
        cmd_argv[0]), ": "), cmd_argv[1]);
perror(prefix);

stpcpy()的便利之处在于它可以被“链接”,如上所述。此外,由于stpcpy()返回指向结果字符串末尾的指针,因此后续的stpcpy()调用不需要一次又一次地查看旧数据。因此,它比多个strcat()更有效,并且可能比sprintf()更有效。 stpcpy()是POSIX:2008。

答案 4 :(得分:2)

如果你试图从其他字符串构建一个字符串(你的例子建议),那么你可以使用snprintf。

char prefix[100] = "";
snprintf( prefix, sizeof(prefix), "%s: %s: %s", argv[0], cmd_argv[0], cmd_argv[1]);

如果您正在尝试连接现有字符串,在那里您无法使用格式方法,那么您可能会遇到多次调用strcat,尽管我强烈建议您可能要考虑使用 strncat 并检查以确保您没有缓冲区溢出。

答案 5 :(得分:2)

您可以使用snprintf功能

char prefix[100];
snprintf(prefix, 100, "%s: %s: %s", argv[0], cmd_argv[0], cmd_argv[1]);

答案 6 :(得分:2)

假设你有一个char [fixed_size]作为已发布的而不是char *,你可以使用一个单一的创意宏一次性完成所有操作,使用类似cout的顺序而不是脱节的printf样式格式。如果您正在使用嵌入式系统,这种方法将允许您省略大型printf系列函数,如snprintf()(这使得dietlibc不会抱怨),甚至不需要malloc()或任何函数来自<string.h>

#include <unistd.h> //for write
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset<(int)sizeof(buf))) \
            *bp++=*s++; \
    if (offset!=sizeof(buf))*bp=0; \
}while(0)

char buf[100];
int len=0;
strcpyALL(buf,len, argv[0],": ", cmd_argv[0],": ",cmd_argv[1]);
if (len==sizeof(buf))write(2,"error\n",6);
else write(1,buf,len); 
  • 注1,您可以使用任何输出char *的函数,包括像itoa()这样的非标准函数,用于将整数转换为字符串类型。
  • 注意2,如果您正在使用共享库或者已经在静态构建的程序中的任何位置使用了printf样式函数,那么不使用snprintf()的唯一原因(因为使用此方法编译的代码会更大)因为它是内联的,并且不调用任何外部函数,所以它应该相对较快。

答案 7 :(得分:0)

您不能使用宏。

#include <stdio.h>
#include <string.h>

#define a argv[0]
#define b argv[1]
#define c argv[2]
#define strcat1(a,b,c) strcat(prefix, a);\
                       strcat(prefix, ": ");\
                       strcat(prefix, b);\
                       strcat(prefix, ": ");\
                       strcat(prefix, c);\
                       perror(prefix);\



int main(int argc, char *argv[]){
    char prefix[100] = "";
    strcat1(a,b,c);
    return 0;
}