string copy() 函数返回被误解? (三)

问题描述 投票:0回答:3

(编辑)

从 C 中的函数更新和返回字符串时可能存在的误解

我是一名学生,刚刚开始尝试动态内存分配技术。最近,我被告知要在 .

下处理类似于 C 中的 strcpy() 函数的字符串 copy() 函数

它应该有两个参数:char c1[],char c2[]。 暂时,我关注一个约束,其中字符串 c1 的长度小于字符串 c2。在这种情况下,我们会将一个较大的字符串复制到一个较小的字符串中。因此,自然而然地,它必须扩大前一个字符串的大小。 (我定义了一个返回字符串长度的函数 len()。它工作正常)

代码:

char* copy(char c1[],char c2[])
{
    int i=0;
    int lc1=len(c1);
    int lc2=len(c2);
    if(lc1<lc2)
    {
                //are the following two lines allowed?
        c1=(char*) malloc(lc1*sizeof(char));
        c1=(char*) realloc(c1,lc2*sizeof(char));
        for(i=0;i<lc2;i++)
        {
            *(c1+i)=c2[i];
        }
        *(c1+lc2)='\0';
    }
    return c1;
}

*如果此代码有多个问题,我不会感到惊讶! * 我试过如下测试:

#include <stdio.h>
#include <string.h>
#include "mystring.h"
main()
{
    int i;
    char s1[12],s2[12];
    gets(s1);
    gets(s2);
    printf("copy: %s",copy(s1,s2));
    printf("\ns1: %s",s1);
}

我得到: output

我希望两个输出相同,即副本和 s1。碰巧只有当我将它与调用一起打印时,它才会起作用。当我打印 s1 时,我期待它打印副本。

我哪里做错了?我认为这与我正在处理的变量的范围有关,或者与整个指针和内存分配有关!

编辑: 我做了一个替代函数 xcopy:

char* xcopy(char c1[])
{
    int i=0;
    int lc1=len(c1);
    char* c2=(char*) malloc((lc1+1)*sizeof(char));
    for(i=0;i<lc1;i++)
    {
        *(c2+i)=c1[i];
    }
    *(c2+lc1)='\0';
    return c2;
}

我意识到这个功能并没有解决实际问题。


谢谢你的帮助!

c pointers c-strings strcpy function-definition
3个回答
1
投票

函数

copy
没有意义。

对于初学者来说,参数

c1
指向的数组不一定包含字符串。所以这条线

int lc1=len(c1);

调用未定义的行为。

即使指针

c1
指向的数组包含一个字符串,存储的字符串也可能比数组的大小小得多。所以又是这条线

int lc1=len(c1);

使用以下 if 语句

if(lc1<lc2)

没有意义。

同样分配内存两次

c1=(char*) malloc(lc1*sizeof(char));
c1=(char*) realloc(c1,lc2*sizeof(char));

不安全、多余且效率低下。

实际上函数并没有复制目标数组中指针

c2
所指向的字符串。因此再次使用参数
c1
没有意义。你的函数看起来像 POSIX 函数
strdup
如果要删除第一个无意义的参数。

您没有显示函数

len
如何计算字符串的长度,但它似乎不计算字符串的终止零字符。在这种情况下,您至少需要使用表达式
( lc2 + 1 ) * sizeof( char )
分配内存,为终止零字符
'\0'
保留内存。否则这个声明

*(c1+lc2)='\0';

调用未定义的行为。

函数的用户有责任提供一个足够大的目标数组来存储源字符串。该函数不应分配任何内存。

类比标准C函数

strcpy
函数可以看成下面的样子

char * copy( char s1[], const char s2[] )
{
    for ( char *p = s1; ( *p++ = *s2++ ) != '\0'; );

    return s1;
}

注意函数

gets
不安全,C标准不支持。而是使用标准 C 函数
fgets
。它可以附加一个带有换行符的字符串
'\n'
.

要删除它,您可以编写例如

c2[ strcspn( c2, "\n" ) ] = '\0';

0
投票
#include <stdio.h>
#include <string.h>

/* headers.h
#define SLEN 100
#define SLENT 200

typedef struct size {
    size_t length_one[SLEN];
    size_t length_two[SLENT];

} siz, *siz_point;

char * copy(char var1[], char var2[])
{
    struct size siz;
    int i = 0;

    siz.length_one = strlen(var1);
    siz.length_two = strlen(var2);

    if (siz.length_one < siz.length_two) {

        void vars_one = (char *) malloc(siz.length_one * sizeof(siz.length_one));
        void vars_two = (char *) memcpy(siz.length_one, siz.length_two, size_t memory);

        for (i=0; i < siz.length_two; i++) {
            *(var1+i) = var2[i];
        }
        *(var1 + siz.length_two) = '\0';
    }
    return var1;
}


*/

#define LEN 20

char * s_gets(char * set_string, size_t isize_n);

char * s_gets(char * set_string, size_t isize_n) {
    char * retnval;
    char * findval;

    retnval = fgets(set_string, isize_n, stdin);
    if (retnval) {
        findval = strchr(set_string, '\n');
        if (findval) *findval = '\0';
        else
            while (getchar() != '\n')
                continue;
    }
    return retnval;
}

int
main() {

    int i;
    char string_one[LEN];
    char string_two[LEN];

    s_gets(string_one, "This string one");
    s_gets(string_two, "This string two");

    printf("Copying string: %s", copy(string_one, string_two));
    printf("\nString: %s", string_one);
}

也许你的代码看起来像这样


-2
投票

您提供的代码存在以下问题:

  1. c2
    c1
    的字符没有被正确复制。您正在迭代循环直到
    lc2
    ,但是由于您是从
    c2
    复制到
    c1
    ,所以您应该只迭代
    lc1
    。您还应该复制每行结尾的空字符。
  2. 你没有返回一个以空结尾的字符串。要在复制字符后结束字符串,您应该在
    \0
    的末尾添加一个空字符
    c1

更正代码

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

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

char* copy(char c1[], char c2[])
{
    int i = 0;
    int lc1 = len(c1);
    int lc2 = len(c2);

    // Allocate memory for c1 if its length is less than c2's length
    if (lc1 < lc2)
    {
        // Allocate memory for c1 using malloc
        char* temp = (char*) malloc(lc2 * sizeof(char));
        if (temp == NULL)
        {
            printf("Memory allocation failed");
            exit(1);
        }

        // Copy the contents of c2 to temp
        for (i = 0; i < lc2; i++)
        {
            *(temp + i) = c2[i];
        }

        // Add null terminator
        *(temp + lc2) = '\0';

        // Free memory allocated to c1
        free(c1);

        // Return the pointer to the newly allocated memory block
        return temp;
    }
    else
    {
        // If c1 is already big enough to hold the contents of c2, just copy the contents and return c1
        for (i = 0; i < lc2; i++)
        {
            *(c1 + i) = c2[i];
        }

        // Add null terminator
        *(c1 + lc2) = '\0';

        // Return the original pointer to c1
        return c1;
    }
}

int main()
{
    char s1[12], s2[12];

    printf("Enter string s1: ");
    fgets(s1, sizeof(s1), stdin);
    printf("Enter string s2: ");
    fgets(s2, sizeof(s2), stdin);

    // Remove newline character from input strings
    s1[strcspn(s1, "\n")] = '\0';
    s2[strcspn(s2, "\n")] = '\0';

    // Call the copy function and print the results
    char* result = copy(s1, s2);
    printf("Result: %s\n", result);

    free(result);

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.