2

I am new to C programming so please do forgive my naivety. The following program when outputted fails to print the last character of the input string as the first character of the output string.

For example:

Enter no. of elements: 5
Enter string: hello
The reversed string is: lleh

Why is the o not printing?

#include <stdio.h>

int main() {
    printf("Enter no. of elements: ");
    int n;
    scanf("%d", &n);
    char string[10000];
    printf("Enter string: ");
    for (int i = 0; i < n; i++) {
        scanf("%c", &string[i]);
    }
    printf("The reversed string is: ");
    for (int i = (n - 1); i >= 0; i--) {
        printf("%c", string[i]);
    }
    printf("\n");
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189

3 Answers3

2

There is a side effect you take care of:

  • After scanf("%d", &n);, there is a pending newline in the input stream buffer.

  • When you later input n characters, scanf("%c", &string[i]) first reads the pending newline, then the n-1 first characters you type and the remainder of your input stays in the input buffer.

scanf() is a very clunky function. It is difficult to use properly.

Here is a way to fix your problem:

#include <stdio.h>

int main() {
    char string[10000];
    int i, n, c;

    printf("Enter no. of elements: ");
    if (scanf("%d", &n) != 1 || n < 0 || n > 10000)
        return 1;

    // read and discard pending input
    while ((c = getchar()) != '\n' && c != EOF)
        continue;

    printf("Enter string: ");
    for (i = 0; i < n; i++) {
        if (scanf("%c", &string[i]) != 1)
            break;
    }
    // the above loop could be replaced with a single call to fread:
    // i = fread(string, 1, n, stdin);

    printf("The reversed string is: ");
    while (i-- > 0) {
        printf("%c", string[i]);
    }
    printf("\n");
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • you should also take care of a maximum of scanf characters, which would produce a buffer overflow. Use e.g. `scanf("%99999[^\n]", string);` to make an upper bound. – Tom Kuschel Jul 23 '17 at 19:25
  • Or use `fgets` instead. – Some programmer dude Jul 23 '17 at 19:25
  • @TomKuschel: `scanf("%99999[^\n]", string)` would stop at the first newline and would even fail if the user types a newline immediately. The limit should be `9999` instead of `99999`. The OP wants to read `n` characters, either `getchar()` or `scanf("%c", ...` or `fread()` seem better. – chqrlie Jul 23 '17 at 19:30
  • @chqrlie: The above comment applies to your line `if (scanf("%c", &string[i]) != 1)`. What happens when the user enters more than 10,000 characters? Yes, 9999 instead of 99999 (it was a typo), you're right. – Tom Kuschel Jul 23 '17 at 19:41
  • @TomKuschel: if the user types more than 10000 characters, the program will only read the first `n`, which is verified in the initial step to be in the range `0..10000`. The remaining characters will stay in the input buffer or in the terminal buffer. – chqrlie Jul 23 '17 at 21:26
0

Your scanf() should start with a space( more info about that ). Here is the code:

#include <stdio.h>

int main() {
    printf("Enter no. of elements: ");
    int n;
    scanf(" %d", &n);
    char string[10000];
    printf("Enter string: ");
    for (int i = 0; i < n; i++) {
        scanf(" %c", &string[i]);
    }
    /* Just to be safer. */
    string[n] = '\0';
    printf("The reversed string is: ");
    for (int i = (n-1); i >= 0; i--) {
        printf("%c", string[i]);
    }
    printf("\n");
    return 0;
}
simo-r
  • 733
  • 1
  • 9
  • 13
  • This is a simpler solution, but it does not allow for the input to contain spaces – chqrlie Jul 23 '17 at 19:16
  • @chqrlie He's not asking for this, it may be needless in this case. – simo-r Jul 23 '17 at 19:18
  • He is asking why `o` in `hello` does not get printed... the next test is `hello world` ;-) – chqrlie Jul 23 '17 at 19:19
  • @BetaRunner Yes this solves the problem. But can you explain what that space means? – Omkar Mozar Jul 23 '17 at 19:19
  • @user5250644: the initial space in `" %c"` consumes and ignores any white space characters, including the pending newline, but also any spaces in the input string, which may not be OK. – chqrlie Jul 23 '17 at 19:21
  • @chqrlie so if I put anything before "%c" it will just ignore that particular thing in input? right? – Omkar Mozar Jul 23 '17 at 19:23
  • @user5250644 I added an explaination link to the answer. For the spaces problem, he doesn't say anything so I can't suppose anything. – simo-r Jul 23 '17 at 19:24
  • @user5250644: no, if you start the format string with a space, such as `scanf(" %c", ...)` spaces and newlines in the input stream are skipped until a non whitespace character is read and stored into the destination. – chqrlie Jul 23 '17 at 19:26
  • @chqrlie then BetaRunner's solution also valid for "hello word". But for that he just have to make change(adding whitespace after %d) to first scanf i.e. scanf(scanf(" %d ", &n);) And remove white space given in another scanf. – Omkar Mozar Jul 23 '17 at 19:29
  • @chqrlie And It will be more Simpler. – Omkar Mozar Jul 23 '17 at 19:30
  • 1
    @user5250644: no, adding a trailing space to `"%d"` opens another can of worms: `scanf` will keep reading the input until a non white space character is typed after the number. – chqrlie Jul 23 '17 at 19:33
  • @chqrlie Is it ?? That's what we want actually. can you explain the case in which it will fail. (e.g)?? – Omkar Mozar Jul 23 '17 at 19:37
  • @Omkar: not really what the OP wants: The response to the first prompt would need to include both the number and some non whitespace characters, input before the second prompt is output to the user. – chqrlie Jul 23 '17 at 21:16
0

Adding the space to the format string enables scanf to consume the newline character from the input that happens everytime you press return. Without the space, string[i] will receive the char '\n'

So, merely one space is put before format specifier %c at line 11. scanf(" %c", &string[i]);