C中带有指针的自定义concat函数

时间:2016-01-31 13:53:46

标签: c string pointers

我尝试在没有库的情况下在C中编写我自己的连接函数,但是我有问题,我不知道它来自哪里。 为了完成我的功能,我使用了char的指针。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

int longueur(char *str)
{
    int i =0;
    while(str[i] != '\0')
    {
        i++;
    }
    return i;
}

void concat(char* source, char* dest)
{
    int longStr1 = (longueur(source));
    int longStr2 = (longueur(dest));
    int i=0, j=0;
    char* temp = dest;
    free(dest);
    dest = (char*) realloc(dest, ((longStr1 + longStr2)* sizeof(char)));

    /*dest[0] = temp[0]; <------  If I do this it will generate issue, so the bellow code too*/
    while(temp[i] != '\0')
    {
        dest[i] = temp[i];
        i++;
    }
    while(source[j] != '\0')
    {
        dest[i] = source[j];
        i++;
        j++;
    }
   dest[i] = '\0';
}

int main()
{
    char *str1 = "World";
    char *str2 = "Hello";
    concat(str1, str2);
    printf("-------------\n%s", str2);
    return 0;
}

修改

我读了你所有的答案,所以我将concat函数改为:

void concat(char* source, char* dest)
{
    int longStr1 = (longueur(source));
    int longStr2 = (longueur(dest));
    int i=0, j=0;

    dest = (char*) malloc((longStr1 + longStr2)* sizeof(char) + sizeof(char));

    while(dest[i] != '\0')
    {
        dest[i] = dest[i];
        i++;
   }
   while(source[j] != '\0')
   {
       dest[i] = source[j];
       i++;
       j++;
   }
   dest[i] = '\0';
}

现在我没有问题,但我的代码只显示“你好”

4 个答案:

答案 0 :(得分:1)

在您的代码中

free(dest);

dest = (char*) realloc(dest, ((longStr1 + longStr2)* sizeof(char)));

调用undefined behavior,因为它们都不使用先前由malloc()或家族分配的指针。

大多与您的方法一致,您需要使用另一个指针,分配动态内存并返回该指针。不要试图改变作为参数接收的指针,因为你已经传递了字符串文字。

那就是说,你需要首先明确一些基本概念。

  1. 除非通过free()系列分配,否则不需要malloc()内存。
  2. 您需要额外分配char来保留终止空值。
  3. Please see this discussion on why not to cast the return value of malloc() and family in C.
  4. 如果你的串联函数分配了内存,那么调用者需要处理free()内存,否则会导致内存泄漏。

答案 1 :(得分:1)

除了所有好的评论和解决方案:realloc可以为您提供不同的指针,您必须返回该指针。所以你的函数签名应该是:

void concat(char* source, char** dest)
{
    int longStr1 = (longueur(source));
    int longStr2 = (longueur(dest));
    int i=0, j=0;
    char* temp = *dest, *temp2;
    if ((temp2 = realloc(dest, ((longStr1 + longStr2)+1))==NULL) return;
    *dest= temp2;

    while(temp[i] != '\0')
    {
        *dest[i] = temp[i];
        i++;
    }
    while(source[j] != '\0')
    {
        *dest[i] = source[j];
        i++;
        j++;
    }
   *dest[i] = '\0';
}

..并且此假设该函数将使用dest分配的malloc进行调用。并且sizeof(char)始终为1.(此结果函数不是最优的。)

- 编辑 -

低于正确的优化版本:

void concat(char* source, char** dest)
{
    int longSrc = longueur(source);
    int longDst = longueur(dest);
    char *pDst, *pSrc;

    if ((pDst = realloc(*dest, longSrc + longDst + 1))==NULL) return;

    if (pDst != *dest) *dest= pDst;

    pDst += longSrc;
    pSrc= source;

    while(pSrc)
        *pDst++ = *pSrc++;

    *pDst = '\0';
}

答案 2 :(得分:0)

在此处释放dest之后:

free(dest);

在跟随realloc的调用时,您无法使用此指针:

dest = (char*) realloc(dest, ((longStr1 + longStr2)* sizeof(char)));

/*dest[0] = temp[0]; <------  If I do this it will generate issue, so the bellow code too*/

man realloc

  

void * realloc(void * ptr,size_t size);

     

realloc()函数会更改内存块的大小   ptr指向size字节。 (...)

但是这个指针现在无效,你不能再使用它了。当您调用free(dest)时,指向的内存dest将被释放,但dest的值保持不变,使得dest成为悬空指针。访问已释放的内存会产生未定义的行为

注意: 即使free(dest)在调用指向由malloc分配的内存的指针时技术上有效(在函数中调用free(dest)不是错误),在指针上使用它是不正确的与示例中的文字字符串一样(因为str2指向字符串文字,将此指针传递给函数调用free是错误的。)

答案 3 :(得分:0)

鉴于您的原始用途,也许您会找到一个像这样有用的变体

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

size_t longueur ( const char * str ) {               /* correct type for string lengths */
    size_t len = 0;

    while (*str++ != '\0') ++len;
    return len;
}

char * concat ( const char * first, const char * second ) {
    const char * s1 = first  ? first  : "";          /* allow NULL input(s) to be */
    const char * s2 = second ? second : "";          /* treated as empty strings */
    size_t ls1 = longueur(s1);
    size_t ls2 = longueur(s2);
    char * result = malloc( ls1 + ls2 + 1 );         /* +1 for NUL at the end */
    char * dst = result;   

    if (dst != NULL) {
        while ((*dst = *s1++) != '\0') ++dst;        /* copy s1\0 */
        while ((*dst = *s2++) != '\0') ++dst;        /* copy s2\0 starting on s1's \0 */
    }
    return result;
}

int main ( void ) {
    const char *str1 = "Hello";
    const char *str2 = " World";
    char * greeting = concat(str1, str2);

    printf("-------------\n%s\n-------------\n", greeting);
    free(greeting);
    return 0;
}

在此变体中,连接两个输入并返回连接的结果。两个输入保持不变。