【问题标题】:Append Char To String in C?将字符附加到C中的字符串?
【发布时间】:2012-04-23 11:33:51
【问题描述】:

如何在 C 中将单个字符附加到字符串?

char* str = "blablabla";
char c = 'H';
str_append(str,c); /* blablablaH */

【问题讨论】:

  • 附带条件是您在第 1 行中对字符串的定义需要是一个分配了足够内存的 char 数组(如答案中所述),请尝试 strncat(str,&c,1);用于实际附加。

标签: c string


【解决方案1】:
char* str = "blablabla";     

您根本不应该修改此字符串。它驻留在实现定义的只读区域中。修改它会导致 Undefined Behavior

您需要一个 char 数组而不是字符串文字。

好读:
What is the difference between char a[] = "string"; and char *p = "string";

【讨论】:

    【解决方案2】:

    要在 C 中将 char 附加到字符串,首先必须确保包含该字符串的内存缓冲区足够大以容纳额外的字符。在您的示例程序中,您必须分配一个新的额外内存块,因为无法修改给定的文字字符串。

    这是一个示例:

    #include <stdlib.h>
    
    int main()
    {
        char *str = "blablabla";
        char c = 'H';
    
        size_t len = strlen(str);
       
        /* one for extra char, one for trailing zero */
        char *str2 = malloc(len + 1 + 1);
    
        strcpy(str2, str);
        str2[len] = c;
        str2[len + 1] = '\0';
    
        printf("%s\n", str2); /* prints "blablablaH" */
    
        free(str2);
    }
    

    首先,使用malloc 分配一块足够大的新内存块,以容纳输入字符串的所有字符、要附加的额外字符 - 以及最后的零。然后调用strcpy 将输入字符串复制到新缓冲区中。最后,更改新缓冲区中的最后两个字节以添加要添加的字符以及尾随零。

    【讨论】:

    • 关于使用 sizeof 的注释不正确。 sizeof str 是 4 还是 8,具体取决于您是编译 32 位还是 64 位代码。
    • 另外,总是在 printf 中使用格式说明符。想象一下,如果str 中包含一个%s 字符序列。
    • @JeremyP sizeof 评论确实不准确。我的意思是你可以调用sizeof("blablablah"),我将完全删除评论,因为编译器可能足够聪明,可以注意到它可以对调用进行 const 折叠。至于格式说明符 - 你当然是正确的,这是一个非常尴尬的错误。我会更新我的答案。
    【解决方案3】:

    如果您关心 Linux,附加两个字符串的最简单方法:

    char * append(char * string1, char * string2)
    {
        char * result = NULL;
        asprintf(&result, "%s%s", string1, string2);
        return result;
    }
    

    这不适用于 MS Visual C。

    注意:你必须free()asprintf()返回的内存

    【讨论】:

    • 如果你有非标准的asprintf函数;它不是由 C 语言或 POSIX 定义的。
    • 你不返回对局部变量的引用吗?
    • 我从来没有遇到过问题,也许 asprintf 分配了内存。
    • @Abhishek asprintf malloc 有足够的空间将结果字符串放入其中。显然,它在 GNU glibc 和大多数 BSD 版本中都可用(将 OS X 算作 BSD 的一个版本)。
    【解决方案4】:

    我认为你不能在 c 中声明这样的字符串。您只能对 const char* 执行此操作,当然您不能修改 const char *,因为它是 const。

    您可以使用动态字符数组,但您必须注意重新分配。

    编辑:实际上这种语法编译正确。如果 str 以您的方式初始化(​​来自字符串文字),您仍然不能修改它所指向的内容

    【讨论】:

    • char *ptr = "string" 在 C 中完全有效。
    • @Als - 是的,没错。我以为不是,但似乎没关系。但是你仍然不能修改数组。
    • 是的,你不能修改 字符串字面量它不是一个数组开头。
    • @Als 我再次同意 - 这是一个文字:)
    • @AlokSave 字符串文字是数组。
    【解决方案5】:

    原海报不是故意写的:

      char* str = "blablabla";
    

    但是

      char str[128] = "blablabla";
    

    现在,添加单个字符似乎比使用 strcat 添加整个字符串更有效。 采用 strcat 方式,您可以:

      char tmpstr[2];
      tmpstr[0] = c;
      tmpstr[1] = 0;
      strcat (str, tmpstr);
    

    但您也可以轻松编写自己的函数(就像我之前的几个人所做的那样):

      void strcat_c (char *str, char c)
      {
        for (;*str;str++); // note the terminating semicolon here. 
        *str++ = c; 
        *str++ = 0;
      }
    

    【讨论】:

      【解决方案6】:

      创建一个新字符串(字符串+字符)

      #include <stdio.h>    
      #include <stdlib.h>
      
      #define ERR_MESSAGE__NO_MEM "Not enough memory!"
      #define allocator(element, type) _allocator(element, sizeof(type))
      
      /** Allocator function (safe alloc) */
      void *_allocator(size_t element, size_t typeSize)
      {
          void *ptr = NULL;
          /* check alloc */
          if( (ptr = calloc(element, typeSize)) == NULL)
          {printf(ERR_MESSAGE__NO_MEM); exit(1);}
          /* return pointer */
          return ptr;
      }
      
      /** Append function (safe mode) */
      char *append(const char *input, const char c)
      {
          char *newString, *ptr;
      
          /* alloc */
          newString = allocator((strlen(input) + 2), char);
          /* Copy old string in new (with pointer) */
          ptr = newString;
          for(; *input; input++) {*ptr = *input; ptr++;}
          /* Copy char at end */
          *ptr = c;
          /* return new string (for dealloc use free().) */
          return newString;
      }
      
      /** Program main */
      int main (int argc, const char *argv[])
      {
          char *input = "Ciao Mondo"; // i am italian :), this is "Hello World"
          char c = '!';
          char *newString;
      
          newString = append(input, c);
          printf("%s\n",newString);
          /* dealloc */
          free(newString);
          newString = NULL;
      
          exit(0);
      }
      
                    0   1   2   3    4    5   6   7   8   9  10   11
      newString is [C] [i] [a] [o] [\32] [M] [o] [n] [d] [o] [!] [\0]
      

      请勿在不知道其确切大小的情况下更改数组大小([len +1] 等),否则可能会损坏其他数据。 alloc 具有新大小的数组并将旧数据放入其中,请记住,对于 char 数组,最后一个值必须是 \0; calloc() 将所有值设置为 \0,这对于 char 数组非常有用。

      我希望这会有所帮助。

      【讨论】:

        【解决方案7】:

        C 本身没有字符串——你拥有的是一个 char 指针,指向一些包含字符“blablabla\0”的只读内存。为了在此处附加一个字符,您需要 a) 可写内存和 b) 为新形式的字符串提供足够的空间。字符串文字 "blablabla\0" 两者都没有。

        解决办法是:

        1) 使用malloc() 等。动态分配内存。 (之后别忘了free()。)
        2) 使用 char 数组。

        在处理字符串时,请考虑使用str* 函数的strn* 变体——它们将帮助您保持在内存范围内。

        【讨论】:

        • 但永远不要使用strncpy。它不是一个字符串函数(尽管它的名字),只会造成麻烦。
        【解决方案8】:

        您可以在string.h 标准标头中使用strcat,但不要将char 作为第二个参数传递,请改用以下代码

        void append_str(char str[] , char c){
             auto char arr[2] = {c , '\0'};
             strcat(str , arr);
        }
        

        【讨论】:

          【解决方案9】:

          你可以使用 strncat()

          #include <stdio.h>
          #include <string.h>
          
          int main(void){
            char hi[6];
            char ch = '!';
            strcpy(hi, "hello");
          
            strncat(hi, &ch, 1);
            printf("%s\n", hi);
          }
          

          【讨论】:

            【解决方案10】:

            就我而言,这是我找到的最佳解决方案:

            snprintf(str, sizeof str, "%s%c", str, c);
            

            【讨论】:

            • 这对我来说似乎是未定义的行为。我认为您不允许将目标参数 str 作为格式字符串 ("%s...", str, ...) 的参数之一传递。
            • @melpomene 如果你之前声明过,当然可以
            • 不,这是未定义的行为:“如果复制发生在重叠的对象之间,则行为未定义。”(C90 中的 7.9.6.5 和 C99 中的 7.19.6.5 )
            【解决方案11】:

            就是这样,它 100% 有效

            char* appending(char *cArr, const char c)
            
            {
            
            int len = strlen(cArr);
            
            cArr[len + 1] = cArr[len];
            
            cArr[len] = c;
            
            return cArr;
            
            
            }
            

            【讨论】:

            • 只有当cArr指向的字符串是可写的并且它有足够的空间添加另一个字符时才有效。
            • -1 因为它只适用于非常小的“100”值“100%”。
            猜你喜欢
            • 2023-01-19
            • 1970-01-01
            • 1970-01-01
            • 2022-01-21
            • 2012-11-09
            • 1970-01-01
            • 2012-05-28
            • 2012-10-04
            • 1970-01-01
            相关资源
            最近更新 更多