C中字符串连接的代码太多

C中字符串连接的代码太多,c,string,C,String,我的代码中有很多strcat行。有没有更好的方法在C中连接字符串 char material[50]; // it is defined before this code. char result[10000]; strcpy(result, "// Assign new material to worldGlobe\n"); strcat(result, "shadingNode -asShader lambert -n "); strcat(result, material); strcat

我的代码中有很多strcat行。有没有更好的方法在C中连接字符串

char material[50]; // it is defined before this code.
char result[10000];
strcpy(result, "// Assign new material to worldGlobe\n");
strcat(result, "shadingNode -asShader lambert -n ");
strcat(result, material);
strcat(result, ";\n");
那怎么办

sprintf(result, "// Assign new material to worldGlobe\nshadingNode -asShader lambert -n %s;\n\0", material);
那怎么办

sprintf(result, "// Assign new material to worldGlobe\nshadingNode -asShader lambert -n %s;\n\0", material);

您可以将格式字符串与(safe与
sprintf()
)结合使用:


您可以将格式字符串与(safe与
sprintf()
)结合使用:


C语言主要是一种自己动手的语言

既然您已经知道如何压缩字符串,那么您应该编写自己的函数以使其更简单

我的建议是:

char*  str_multicat(char* result, ...);
str_mutlicat(result, "// Assign new material to worldGlobe\n",
                     "shadingNode -asShader lambert -n ",
                     material,
                     ";\n",
                     NULL);
并称之为:

char*  str_multicat(char* result, ...);
str_mutlicat(result, "// Assign new material to worldGlobe\n",
                     "shadingNode -asShader lambert -n ",
                     material,
                     ";\n",
                     NULL);

(提示,如果您不知道
语法,请查看
va_arg
va_start
va_end

C主要是一种自己动手的语言

既然您已经知道如何压缩字符串,那么您应该编写自己的函数以使其更简单

我的建议是:

char*  str_multicat(char* result, ...);
str_mutlicat(result, "// Assign new material to worldGlobe\n",
                     "shadingNode -asShader lambert -n ",
                     material,
                     ";\n",
                     NULL);
并称之为:

char*  str_multicat(char* result, ...);
str_mutlicat(result, "// Assign new material to worldGlobe\n",
                     "shadingNode -asShader lambert -n ",
                     material,
                     ";\n",
                     NULL);

(提示,如果您不知道
语法,请查看
va_arg
va_start
va_end

strcat
仅适用于非常小的字符串;对于任何非琐碎的事情,它都有几个问题,例如:

  • 由于这个问题,
    strcat
    在输入字符串的长度上是O(n),也就是说,字符串越长,每次连接所需的时间就越长。这是因为strcat必须遍历整个字符串才能找到其结尾。要解决这个问题,请将字符串的长度与字符串数据一起存储,这将允许您直接跳到字符串的末尾
  • 它不做任何边界检查。如果你
    strcat
    在字符串的末尾写得太多,它会很高兴地写过字符串的末尾,在最好的情况下会产生一个segfault,在最坏的情况下会产生一个严重的安全漏洞,并且很可能会出现一些让你头痛的bug
    strncat
    部分解决了此问题,只要您将正确大小的目标缓冲区传递给它即可
  • 如果目标缓冲区太小,则无论是
    strcat
    还是
    strncat
    都不会增加其大小:您必须自己进行此操作
在您的情况下,有两种切实可行的解决方案:

a) 河内塔算法:构建字符串堆栈。如果新字符串比堆栈顶部短,请将其推到堆栈上。如果较长,则从顶部弹出,连接,然后重复该过程并生成结果。推完后,连接堆栈上的内容。这是 STD::StReStase C++或<代码> StringBuilder <代码> .NETDO,如果您环顾四周,我确信您会在C.</P>找到合适的实现。
b) 将字符串直接写入流。输出的内容看起来很像代码——为什么不直接写入文件?

strcat
只适用于非常小的字符串;对于任何非琐碎的事情,它都有几个问题,例如:

  • 由于这个问题,
    strcat
    在输入字符串的长度上是O(n),也就是说,字符串越长,每次连接所需的时间就越长。这是因为strcat必须遍历整个字符串才能找到其结尾。要解决这个问题,请将字符串的长度与字符串数据一起存储,这将允许您直接跳到字符串的末尾
  • 它不做任何边界检查。如果你
    strcat
    在字符串的末尾写得太多,它会很高兴地写过字符串的末尾,在最好的情况下会产生一个segfault,在最坏的情况下会产生一个严重的安全漏洞,并且很可能会出现一些让你头痛的bug
    strncat
    部分解决了此问题,只要您将正确大小的目标缓冲区传递给它即可
  • 如果目标缓冲区太小,则无论是
    strcat
    还是
    strncat
    都不会增加其大小:您必须自己进行此操作
在您的情况下,有两种切实可行的解决方案:

a) 河内塔算法:构建字符串堆栈。如果新字符串比堆栈顶部短,请将其推到堆栈上。如果较长,则从顶部弹出,连接,然后重复该过程并生成结果。推完后,连接堆栈上的内容。这是 STD::StReStase C++或<代码> StringBuilder <代码> .NETDO,如果您环顾四周,我确信您会在C.</P>找到合适的实现。
b) 将字符串直接写入流。输出的内容看起来很像代码—为什么不直接将其写入文件?

您可以使用一个函数返回指向字符串结尾的指针,并在以后的调用中使用该结尾指针。这将消除一堆额外的“首先,找到字符串的结尾”的东西

使用类似于:

char result[10000];
char *end = &result[0];
result[0] = '\0';  // not strictly necessary if you cat a string, but why not
end = faster_cat(end, "// Assign new material to worldGlobe\n");
end = faster_cat(end, "shadingNode -asShader lambert -n ");
end = faster_cat(end, material);
end = faster_cat(end, ";\n");

// result now contains the whole catted string

您可以使用一个函数返回指向字符串结尾的指针,并在以后的调用中使用该结尾指针。这将消除一堆额外的“首先,找到字符串的结尾”的东西

使用类似于:

char result[10000];
char *end = &result[0];
result[0] = '\0';  // not strictly necessary if you cat a string, but why not
end = faster_cat(end, "// Assign new material to worldGlobe\n");
end = faster_cat(end, "shadingNode -asShader lambert -n ");
end = faster_cat(end, material);
end = faster_cat(end, ";\n");

// result now contains the whole catted string

构建一个字符串缓冲区结构,它将跟踪缓冲区中的当前位置,并将其与
vsprintf
相结合,得到一个
catf()
。函数
vsnprintf()
(假设它可用)与
printf
类似,只是它在格式字符串后采用
va_列表
,而不是

与其他答案相比,这种方法的优势在于,它允许您从代码中任何可以访问结构的地方“cat”,而无需显式地携带当前长度,也无需像strcat那样每次都重新计算

这是一张免费的草图

/* Note: the typedef is for the pointer, not the struct. */
typedef struct StrBufStruct { 
   char * buffer, 
   size_t size, 
   size_t pos 
} * StrBuf;

/* Create a new StrBuf. NOTE: Could statically allocate too. */
StrBuf newStrBuf(size_t size){
   StrBuf sb;
   sb = malloc( sizeof(struct StrBufStruct) );
   sb->size = size;
   sb->pos = 0;
   sb->buffer = malloc( size );
   /* TODO: ALWAYS CHECK YOUR MALLOC!!! */
}

int sbcatf( StrBuf b, char * fmt, ... )
{
   va_list ap;
   int res;
   if( b->pos < b->size )
   {  
      va_start(ap,fmt);
      res = vsnprintf( b->buffer[b->pos], b->size - b->pos, fmt, ap );
      b->pos += res;
      va_end();
   } else {
     /* If you want to get really fancy, use realloc so you don't have to worry 
       about buffer size at all.  But be careful, you can run out of memory. */
   }
}

/* TODO: Write a free/delete function */

int main(int argc, char **argv){
   int i;
   /* initialize your structure */
   StrBuf sb = newStrBuf(10000);

   /* concatenate numbers 0-999 */
   for(i=0; i < 1000; i++){
      sbcatf(sb, "I=%d\n", i);
   }

   /* TODO: whatever needs to be done with sb->buffer */

   /* free your structure */
   deleteStrBuf(sb);
}

构建一个字符串缓冲区结构,它将跟踪缓冲区中的当前位置,并将其与
vsprintf
相结合,得到一个
catf()
。函数
vsn