1

this is my example code:

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

void convert(char *a, char *b) {
    int i;
    for(i=0; i<strlen(a); i++) {
        b[i]=tolower(a[i]);
    }
}

int main() {
    char a[20], b[20];

    fgets(a, sizeof(a), stdin);
    convert(a, b);
    printf("%s\n", b);
    return 0;
}

but sometimes the convert() function convert also one more char than strlen(a) (it's a random char), for example this is an output:

ASDSA
asdsa
%

How can i fix it?

giozh
  • 9,868
  • 30
  • 102
  • 183

3 Answers3

5

You have to add a nul character ('\0') at the end of b.

md5
  • 23,373
  • 3
  • 44
  • 93
2

As others mentioned, you need to null-terminate the target string. Aside from that, note that you are recalculating the length of a at each iteration of the loop. This will not matter for small strings, but with large strings you will notice that the time to convert is proportional to the square of the string length. The standard idiom is to calculate the length once and use it repeatedly. With those two changes, the function would look like this:

void convert(const char *a, char *b) {
    size_t i, len = strlen(a);
    for(i = 0; i < len; i++) {
        b[i] = tolower((unsigned char) a[i]);
    }
    b[len] = '\0';
}
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • To prevent *undefined behavior*, you should cast the argument of `tolower` to `unsigned char`. See http://pubs.opengroup.org/onlinepubs/9699919799/functions/tolower.html for details. – Roland Illig Jan 04 '15 at 22:14
  • @RolandIllig Good catch, I've updated the answer. (C99 also requires `tolower` argument to be EOF or a value representable as `unsigned char`, so it's not just a POSIX thing.) But this is not enough, the modified code still contains a lurking undefined behavior: if `a[i]` is negative, `tolower((unsigned char) a[i])` will return a value that will overflow `char`. I haven't checked the standard, but hopefully this can be avoided by casting `b` to `unsigned char *`, e.g. `((unsigned char *)b)[i] = tolower((unsigned char) a[i])` (or a more readable version thereof). – user4815162342 Jan 04 '15 at 22:36
1

strlen returns the length of the string, for instance strlen("hello") is 5. This does not copy the 0 character used to terminate the string (which means the string in the memory is actually 6 characters long: 'h' 'e' 'l' 'l' 'o' '0')

gil_bz
  • 478
  • 1
  • 5
  • 16