2

(EDIT)

Probable misunderstanding in updating and returning a string from a function in C.

I'm a student and have just started trying out dynamic memory allocation techniques. Recently, I was told to work on a string copy() function similar to the strcpy() function in C under <string.h>.

It is supposed to be taking two arguments: char c1[],char c2[]. Momentarily, I am focusing on a constraint wherein the length of string c1 is lesser than the string c2. This is the case, we will be copying a larger string into a smaller one. So, naturally it would have to expand the former string's size. (I have defined a function len() which returns the length of the string. It's working fine)

Code:

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;
}

*I won't be surprised if this code has multiple issues! * I tried testing it as follows:

#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);
}

I got: output

I wanted both of the outputs to be the same, i.e. copy's and s1's. It happens to be that only this functions only when I print it along with the invokation. I was expecting it to print the copy when I printed s1.

Where have I gone wrong? I think it's something related to the scope of the variables I'm dealing with, or the pointers and memory allocation as a whole!

EDIT: I had made an alternative-function 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;
}

I realised this function was not solving the actual problem.


Thankyou for your help!!

IICN-08
  • 23
  • 5

2 Answers2

1

The function copy does not make sense.

For starters it is not necessary that the array pointed to by the parameter c1 contains a string. So this line

int lc1=len(c1);

invokes undefined behavior.

Even if the array pointed to by the pointer c1 contains a string the stored string can be much lesser than the size of the array. So again this line

int lc1=len(c1);

with the following if statement

if(lc1<lc2)

does not make sense.

Also allocating memory two times

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

is unsafe, redundant and inefficient.

Actually the function does not copy the string pointed to by the pointer c2 in the destination array. Thus using the parameter c1 again does not make sense. Your function looks like POSIX function strdup if to remove the first senseless parameter.

You did not show how the function len that calculates length of a string but it seems it does not count the terminating zero character of a string. In this case you need at least to allocate memory using the expression ( lc2 + 1 ) * sizeof( char ) to reserve memory for the terminating zero character '\0'. Otherwise this statement

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

invokes undefined behavior.

It is the responsibility of the user of the function to provide a destination array large enough to store the source string. The function shall not allocate any memory.

By analogy with the standard C function strcpy the function can look the following way

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

    return s1;
}

Pay attention to that the function gets is unsafe and is not supported by the C Standard. Instead use standard C function fgets. It can append a string with the new line character '\n'.

To remove it you can write for example

c2[ strcspn( c2, "\n" ) ] = '\0';
Harith
  • 4,663
  • 1
  • 5
  • 20
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • The if() is unnecessary, I did realise, but it was part of a more expansive function i had made earlier. I just copied the segment including it, i did realise it was meaningless.Function len() did count the terminating character, I just messed up the +1 in the allocation process. Thanks for the insight and your answer !! :) – IICN-08 Apr 07 '23 at 10:47
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);
}

maybe your code looks like this

  • Rather than just posting code, you should consider adding some explanation to your answer, and detail how it addresses the OP's problem(s). – Adrian Mole Apr 11 '23 at 12:14
  • sure, ... at above 'void xcopy function' need to copying string with new placeholder so that's the function automatic copying, with creating new function of 'memcpy()' i think the authors want to creating new function likes memcpy for copying from older memory to new memory and want to exchange them, for 'gets() function' i used new 'gets() function' with size checker, for avoiding buffer overflows, gets(string_one) unknown the size there's just copying the string without knowing exact size @AdrianMole – doomster_legion Apr 11 '23 at 18:11
  • so at the end the copy function can exchange the value like string_one = "This string two" and string_two = "This string one" – doomster_legion Apr 11 '23 at 18:27