24

How can I access s[7] in s?

I didn't observe any difference between strncpy and memcpy. If I want to print the output s, along with s[7] (like qwertyA), what are the changes I have to made in the following code:

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

int main() {
    char s[10] = "qwerty", str[10], str1[10];
    s[7] = 'A';
    printf("%s\n", s);
    strncpy(str, s, 8);
    printf("%s\n", str);
    memcpy(str1, s, 8);
    printf("%s\n", str1);
    return 0;
}

Output:

qwerty
qwerty
qwerty
chqrlie
  • 131,814
  • 10
  • 121
  • 189
user559208
  • 1,485
  • 3
  • 13
  • 9

6 Answers6

50

Others have pointed out your null-termination problems. You need to understand null-termination before you understand the difference between memcpy and strncpy.

The main difference is that memcpy will copy all N characters you ask for, while strncpy will copy up to the first null terminator inclusive, or N characters, whichever is fewer.

In the event that it copies less than N characters, it will pad the rest out with null characters.

Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81
Philip Potter
  • 8,975
  • 2
  • 37
  • 47
  • 11
    There's another difference as well, strncpy will fill the rest of the space with 0. e.g. if you do `strncpy(a,b,255);` and a is 10 long, strncpy will copy those 10 characters and fill the remaining 240 characters with 0. – nos Jan 04 '11 at 13:38
  • @nos: I realized that before you did, and edited it in. But thanks anyway :) – Philip Potter Jan 04 '11 at 13:44
  • 1
    Also consider: "No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow)." – JohnyTex Feb 17 '21 at 12:43
8

You are getting the output querty because the index 7 is incorrect (arrays are indexed from 0, not 1). There is a null-terminator at index 6 to signal the end of the string, and whatever comes after it will have no effect.

Two things you need to fix:

  1. Change the 7 in s[7] to 6
  2. Add a null-terminator at s[7]

The result will be:

char s[10] = "qwerty";
s[6] = 'A';
s[7] = 0;

Original not working and fixed working.

As for the question of strncpy versus memcpy, the difference is that strncpy adds a null-terminator for you. BUT, only if the source string has one before n. So strncpy is what you want to use here, but be very careful of the big BUT.

moinudin
  • 134,091
  • 45
  • 190
  • 216
4

Strncpy will copy up to NULL even you specified the number of bytes to copy , but memcpy will copy up to specified number of bytes .

printf statement will print up to NULL , so you will try to print a single charater , it will show ,

printf("\t%c %c %c\t",s[7],str[7],str1[7]);

OUTPUT

  7              7
Himanshu
  • 31,810
  • 31
  • 111
  • 133
GOBI
  • 41
  • 1
2

To make "qwertyA" you need to set s[6] = 'A' and s[7]='\0'

Strings are indexed from 0, so s[0] == 'q', and they need to be null terminated.

Matt Ellen
  • 11,268
  • 4
  • 68
  • 90
  • I should not change s[7] to s[6]. If we set s[6] as 'A' then we will get the desired output.. – user559208 Jan 04 '11 at 13:15
  • 3
    @user so you're saying you *don't* want the desired output? O_o – Philip Potter Jan 04 '11 at 13:17
  • @user559208: when marcog wrote "change `s[6]` to `s[7]`" I think he actually meant instead of writing s[7], write s[6]. Also, don't forget the null termination of the string (setting `s[7]` to `0` or `'\0'`) because that will help prevent overrun bugs from creeping in. – Matt Ellen Jan 04 '11 at 13:53
  • You might be right about the confusion there. I've attempted to make the wording clearer. – moinudin Jan 04 '11 at 14:07
  • @marcog: That's clearer now. Also, sorry for the minor misquote! – Matt Ellen Jan 04 '11 at 14:12
2

When you have:

char s[10] = "qwerty";

this is what that array contains:

s[0]  'q'
s[1]  'w'
s[2]  'e'
s[3]  'r'
s[4]  't'
s[5]  'y'
s[6]   0
s[7]   0
s[8]   0
s[9]   0

If you want to add an 'A' to the end of your string, that's at index 6, since array indexes start at 0

 s[6] = 'A';

Note that when you initialize an array this way, the remaining space is set to 0 (a nul terminator), While not needed in this case, generally be aware that you need to make your strings nul terminated. e.g.

char s[10];
strcpy(s,"qwerty");
s[6] = 'A';
s[7] = 0;

In the above example "qwerty" , including its nul terminator is copied to s. s[6] overwrites that nul terminator. Since the rest of s is not initialized we need to add a nul terminator ourselves with s[7] = 0;

nos
  • 223,662
  • 58
  • 417
  • 506
1

As explained by Philip Potter, the main difference is that memcpy will copy all n characters you ask for, while strncpy will copy up to the first null terminator inclusive, or n characters, whichever is less. In the event that strncpy copies less than N characters, it will pad the rest out with null characters. The below program will answer your question:

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

int main() {
    char s[10] = "qwerty",str1[10];
    int i;
    s[7] = 'A';
    memcpy(str1, s, 8);
    for(i=0;i<8;i++)
    {
        if(str1[i]!='\0')
            printf("%c",str1[i]);
    }
    return 0;
}

o/p:

qwertyA

Execute the below code and check the difference, you might find it useful.

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

int main()
{
    char s[10] = "qwer\0ty", str[10], str1[10];
    s[7] = 'A';
    printf("%s\n",s);
    strncpy(str,s,8);
    printf("%s\n",str);
    memcpy(str1,s,8);
    printf("%s\n",str1);
    for(int i = 0; i<8; i++)
    {
        printf("%d=%c,",i,str[i]);
    }
    printf("\n");
    for(int i = 0; i<8; i++)
    {
        printf("%d=%c,",i,str1[i]);
    }
    return 0;
}

Output:

qwer
qwer
qwer
0=q,1=w,2=e,3=r,4=,5=,6=,7=,
0=q,1=w,2=e,3=r,4=,5=t,6=y,7=A,
Preethi
  • 43
  • 9