【问题标题】:How to concatenate char and string / How to make char to string如何连接 char 和 string / 如何将 char 制作成字符串
【发布时间】:2016-12-17 03:37:08
【问题描述】:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define MAX_SIZE 20

void main()
{
   int i, j;
   char *str1, *str2, *str3, *str_mid;
   bool **lcs1, **lcs2;
   int len1, len2, len3, len_mid;
   char *ch = (char*)malloc(sizeof(char) * 3);


   str1     = (char*)malloc(sizeof(char)*MAX_SIZE); //applicatian
   str2     = (char*)malloc(sizeof(char)*MAX_SIZE); //apiasn
   str3     = (char*)malloc(sizeof(char)*MAX_SIZE); //apun
   str_mid  = (char*)malloc(sizeof(char)*MAX_SIZE); //apn

   str_mid = "";

   scanf("%s", str1);
   scanf("%s", str2);
   scanf("%s", str3);

   len1 = strlen(str1);
   len2 = strlen(str2);
   len3 = strlen(str3);

   //str2, str3 ->str_mid (lcs1)
   lcs1 = (bool**)malloc(sizeof(bool*)*(len3 + 1));
   for (i = 0; i < len3 + 1; i++)
      lcs1[i] = (bool*)malloc(sizeof(bool)*(len2 + 1));

   for (i = 0; i < len3 + 1; i++)
      for (j = 0; j < len2 + 1; j++)
         lcs1[i][j] = false;

   for (i = 1; i < len3 + 1; i++)
      for (j = 1; j < len2 + 1; j++)
         if (str3[i-1] == str2[j-1])
            lcs1[i][j] = true;

   for (i = 1; i < len3 + 1; i++)
   {
      for (j = 1; j < len2 + 1; j++)
         if (lcs1[i][j])
         {
            //<--- error
            ch = str3[i - 1];
            strcat(str_mid, ch);
            //--->
            break;
      }
   }

   //printf("%s", str_mid);
   //str_mid, str1 (lcs2)

}

在部分,
我想连接 str3[i-1]str_mid 但是,str3[i-1] 是字符类型。
因此,将临时字符串设为 ch 并执行 concatenate
但是,出现了访问错误。
如何将char转为string或者,如何将char和string连接起来?

【问题讨论】:

  • 高级语言中的字符串是缓冲区的抽象——它可以是不可变的、固定大小的、预分配的或扩展的(所有这些都带有或不带有通道内标记值,通常是 \0 aka “以空字符结尾的字符串”)。 C 没有定义自己的字符串类型,尽管大多数库使用固定大小的缓冲区。这需要您自己处理。
  • OT: sizeof(char)1be 定义。
  • OT^2:不要在 C 中强制转换 malloc 和朋友,它只是没用。

标签: c


【解决方案1】:

只要MAX_SIZE 足够大以至于str_mid 能够容纳额外的字符,您就可以使用strcat() 和复合文字(对于C99 或更高版本):

strcat(str_mid, (char[2]){ str3[i - 1], '\0' });

请注意,在您的代码中,str3[i - 1]char,而您已将 ch 声明为指向 char 的指针。

【讨论】:

  • 这假设 ch 是一个 char ,但根据 OP 的代码它不是。
  • @alk-- 谢谢。我没有注意到 OP 已将 ch 声明为指向 char 的指针。
  • 虽然这种方法不必要地(调用strcat())昂贵,但它仍然是使用复合文字的一个很好的例子:1+
  • @alk-- 谢谢。我更喜欢你的解决方案,但 OP 试图使用strcat(),所以我想我会朝那个方向发展。另外,复合文字很整洁:)
【解决方案2】:

如何连接字符和字符串

根本不需要调用任何库函数,也不需要动态分配任何内存。

假设str_mid 足够大,只需这样做:

{
  size_t tmp_len = strlen(str_mid);
  str_mid[tmp_len] = str3[i - 1];
  str_mid[tmp_len + 1] = '\0';
}

要仍然有使用功能的感觉,您可能需要将上述代码包装成这样的宏:

#define STRCATCHAR(s, c) \
do { \
  assert(s != NULL); \
  size_t tmp_len = strlen(s); \
  (s)[tmp_len] = (c); \
  (s)[tmp_len + 1] = '\0'; \
} while (0)

并像这样使用它:

STRCATCHAR(str_mid, str3[i - 1]);

【讨论】:

    【解决方案3】:

    要连接字符和字符串(第一个字符,然后是字符串):

    const char* conc_char_string(const char ch, const char* str, int len) {
        const char* out = malloc(len + 2); /* 1 char from ch, len chars from str, and zero character, totally len+2 */
        out[0] = ch; /* copy the character */
        strcpy(out+1, str); /* copy the string */
        return out;
    }
    

    这里len应该是strlen(str)

    【讨论】:

    • 长度值应输入为size_t,而不是int
    【解决方案4】:

    str_mid = ""; 语句将常量字符串"" 的地址分配给指针str_mid,这将在以后导致segmentfault。请改用str_mid[0] = '\0';

    在语句ch = str3[i - 1]; 中,您将char 分配给char pointer,这将导致segmentfault

    如果您只是简单地在字符串中附加一个字符,您可以跟踪字符串的长度,如下所示:

    len_mid = strlen(str_mid);
    for (i = 1; i < len3 + 1; i++)
    {
      for (j = 1; j < len2 + 1; j++)
         if (lcs1[i][j])
         {
    
            str_mid[len_mid++] = str3[i - 1];
            str_mid[len_mid] = '\0';
            break;
         }
    }
    

    【讨论】:

    • 会导致段错误。”不一定,不会。
    • @alk,将另一种类型转换为指针并在以后取消引用指针几乎总是导致段错误。
    • @smilingwang--未定义的行为不一定是段错误。
    • @alk,哪一个是未定义的行为?
    • @smilingwang-- ch = str3[i - 1]; 甚至不能用 gcc 编译,因为 ch 是一个指针,str3[i - 1] 是一个 char。我阅读标准的方式是,尝试修改 str_mid 指向的字符串文字是违反约束的:“赋值运算符应具有可修改的左值作为其左操作数。” (ISO/IEC 2011 6.5.16/2)。虽然这里没有明确将其称为未定义行为,但它似乎是一个公平的解释。
    【解决方案5】:

    C-club 的第一条规则,创建自己的字符串缓冲区,C-club 的第二条规则创建自己的字符串缓冲区。 每个程序员都有自己的字符串缓冲区。最低要求是:

     #define STRINGSTRTSZ 256
     typedef struct string
     {
         char *str;
         size_t n;
         size_t buf_sz;
    
      }String,*pString;
    
      pString new_string()
      {
          pString res;
          res=malloc(sizeof(String)); ///i leave to you the error handling
          res->bus_sz=STRINGSTRSZ;
          res->n=0;
          res->str=malloc(res->bus_sz); 
      }
      char*concatbase(pString *string,char*s,size_t len)
      {
          if(len+1>=string->buf_sz-string->n)
          {
               res->buf_sz+=len+res->buf_sz; 
               char *tmp=realloc(string->str,res->buf_sz);
                if(tmp)
                   string->str=tmp;
                else
                  ...
          }
         memcpy(string->str+string->n,s,len);
         string->n+=len;
         *(string->str+string->n)='\0';
         return string->str;  
      }
    
      #define concatNllPtr(string,nllptr) concatbase(string,nllptr,strlen(nllptr))
      #define concatString(string,str2) concatbase(string,(str2)->str,(str2)->n)
    

    以此类推……

    【讨论】:

    • 我将 strcpy() 更改为 memcpy() 以便您也可以连接子字符串;
    • 注意不要错过0-然后终止结果。
    • "每个程序员都有自己的字符串缓冲区。"我对此表示怀疑。
    • 是的,你是对的,不是“每个程序员”都有自己的字符串缓冲区,但“每个程序员”都有自己的字符串缓冲区。带有“P”的国会大厦。因此,为了提名最后一个 API,我处理“RedisModule_String”、postgres 的“varlena”、来自 wxWidgets 的“wxString”、来自 Windows 的 LPTSTR……等等。它的语言是如此恰当,以至于没有人会解释它们的范围,并且这些函数被称为“concat_buffer”“concat_string”等等......
    • 至少LPTSTR 只不过是一个指针而已。那里没有缓冲区!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多