2

I was practicing and found some exercise on the internet and it says that I should copy str2 to str1, perhaps the main problem is that I should copy only a certain index of that string (so from str2[a] to str2[b]). Therefore A and B should be entered so they reduce the range of copied indexes to str1. So here I used the function method to tackle this problem but something went wrong. So I don't get why function does not work, there must be a big mistake in my understanding or I did it all wrong.

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

#define N 50

void myfunction(char str1[], char str2[], int a, int b);

int main() {
    char str1[N], str2[N];
    int a, b;
    printf("please input str1:");
    gets(str1);
    printf("please input str2:");
    gets(str2);
    printf("please input a and b:");
    scanf("%d%d", &a, &b);
    printf("str2=%s, str1=%s", str2, str1);
    myfunction(str1, str2, a, b);
    return 0;
}

void myfunction(char str1[], char str2[], int a, int b) {
    int i, j;
    for (i = a; i <= b; i++) {
        str1 += str2[i];
    }
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

5 Answers5

1

There are multiple problems in your program:

  • you should not use gets()
  • myfunction just increments str1 instead of copying characters.
  • you should output the resulting string.

Here is modified version:

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

#define N  50

void myfunction(char str1[], char str2[], int a, int b);

// safe replacement for gets()
char *mygets(char *buf, size_t n) {
    int c;
    size_t i;
    while ((c = getchar()) != '\n') {
        if (c == EOF) {
            if (i == 0)
                return NULL;
            break;
        }
        if (i + 1 < n)
            buf[i++] = c;
    }
    if (i < n) {
        buf[i] = '\0';
    }
    return buf;
}

int main() {
    char str1[N], str2[N];
    int a, b;

    printf("please input str1: ");
    if (!mygets(str1, sizeof str1))
        return 1;
    printf("please input str2: ");
    if (!mygets(str2, sizeof str2))
        return 1;
    printf("please input a and b: ");
    if (scanf("%d%d", &a, &b) != 2)
        return 1;
    printf("str2=%s, str1=%s\n", str2, str1);
    myfunction(str1, str2, a, b);
    printf("str1=%s\n", str1);
    return 0;
}

void myfunction(char str1[], char str2[], int a, int b) {
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    int i, j;
    if (a < 0)
        a = 0;
    if (b > len2)
        b = len2;
    for (i = 0, j = a; j <= b; i++, j++) {
        str1[i] = str2[j];
    }
    if (i > len1) {
        /* do not truncate str1 but set the null terminator if needed */
        str1[i] = '\0';
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
1

I should copy str2 to str1, perhaps the main problem is that I should copy only a certain index of that string (so from str2[a] to str2[b]).

It looks like you need to copy a part of one string in another character array starting from its initial position and as a result the character array shall also keep a string built from characters of the first string.

If so then the function should be declared like

char * myfunction( char str1[], const char str2[], size_t n );

that is one of parameters of your original function is redundand because using the pointer arithmetic you can always call the function like

myfunction( str1, str2 + a, b - a + 1 );

In your function implementation it seems there are typos.

void myfunction(char str1[], char str2[], int a, int b) {
    int i, j;
    for (i = a; i <= b; i++) {
        str1 += str2[i];
    }
}

For example the variable j is not used, And in this assignment statement

str1 += str2[i];

the left operand is a pointer. So you are just increasing the pointer itself without copying anything. For example if str2[i] contains the character 'A' then the above statement looks like

str1 += 'A';

If there is used the ASCII character table then the statement is equivalent to

str1 += 65;

That is the address stored in the pointer str1 is increased by 65 and will point beyond the destination array.

Also in main there is no great sense to input a string in the character array str1 because as it is supposed it will be overwritten in the function.

Pay attention to the function gets is unsafe and is not supported by the C Standard any more. Instead you should use the function fgets.

Here is a demonstrative program that shows how the function can be written without using standard string functions.

#include <stdio.h>

#define N 50

char * myfunction( char str1[], const char str2[], size_t n )
{
    char *p = str1;
    
    while ( *str2 && n-- )
    {
        *p++ = *str2++;
    }
    
    *p = '\0';
    
    return str1;
}

int main(void) 
{
    char str1[N];
    char str2[N] = "Hello World!";
    
    puts( str2 );
    
    puts( myfunction( str1, str2 + 6, 6 ) );
    
    return 0;
}

The program output is

Hello World!
World!

If you will change the function the following way

char * myfunction( char str1[], const char str2[], size_t n )
{
    char *p = str1;
    
    while ( *str2 && n )
    {
        *p++ = *str2++;
        --n;
    }
    
    while ( n-- ) *p++ = '\0';
    
    return str1;
}

then it will behave the same way as the standard string function strncpy declared in the header <string.h> which you should familiarize yourself with.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • The last function indeed behaves like `strncpy`, with the same error prone and confusing semantics. The one thing the OP should learn about it is this: https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ – chqrlie Apr 19 '21 at 22:39
  • @chqrlie Actually any C string function is error prone. You need correctly use standard string functions. And strncpy does not much differ from other string functions. – Vlad from Moscow Apr 20 '21 at 05:53
0

str1+= is not how you assign to elements of str1. It simply increments the pointer variable str1, which is not useful here.

You can use two variables, one for the index in str1 to assign to, and another for the index in str2 to read from.

You also need to check for reaching the end of str2, and add a null terminator to str1.

void myfunction(char str1[], char str2[], int a, int b) {
    int i = 0, j = a;
    if (a >= 0 && a <= strlen(str2)) {
        for (; str2[j] && j <= b; i++, j++) {
            str1[i] = str2[j];
        }
    }
    str1[i] = '\0';
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks, added validation of a and fixed i – Barmar Apr 19 '21 at 19:28
  • Rather than repeatedly call `strlen()` and incur `O(len)` time, code could save the length and call `strlen()` only once. – chux - Reinstate Monica Apr 19 '21 at 20:30
  • It only calls `strlen()` once. It's in the `if`, not `for`. – Barmar Apr 19 '21 at 20:35
  • And even if it were in `for`, a decent compiler would optimize it into a single call. – Barmar Apr 19 '21 at 20:36
  • I am not sure if `myfunction("abc", "123", 1, 1)` should produce `"2"` or `"2bc"`. You chose the first and I chose the second, which seems more consistent with the OP's `main()` function that reads `str1` from the user... – chqrlie Apr 19 '21 at 21:04
  • @chqrlie Good point, I hadn't noticed that. – Barmar Apr 19 '21 at 21:06
  • Regarding *a decent compiler would optimize it into a single call*: I'm not sure you can count of that because `str1` and `str2` could point to the same string so the compiler would need to ensure that the code cannot set a null terminator inside `str2` via `str1`, which is not as obvious as assuming `str2` remains constant if no `char` object is modified in the code. – chqrlie Apr 19 '21 at 21:09
0

Instead of copying characters between the strings, the line:

str1 += str2[i];

just increments the pointer.

You probably want:

void myfunction(char str1[], char str2[], int a, int b) {
    int i, j = 0;
    for (i = a; i <= b; ++i) {
        str1[j] = str2[i];  // Copy the character in position i in str2 to position i in str1
        ++j;
    }
    str1[j] = '\0';
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
-1

If you want to copy Characters one by one from array of characters you can use for loop like:-

Considering a to be index of str1 where to paste and b be index of str2 from where to Paste.

This is not exact Solution but you can take help from this...

void myfunction(char str1[], char str2[],int a, int b)
{

    str1[a] = str2[b];

}
Dharman
  • 30,962
  • 25
  • 85
  • 135
Karan
  • 119
  • 3
  • 11