3

I've written this code in C. I need to solve a problem and there I'll have to input 5 line string including whitespace. This program will just give me output of all 5 line string including whitespace. By white space I mean on input I can put space before and char or after any char. That's why I've written this code but I can't understand why it's not working.

#include<stdio.h>
int main() {
    char str[5][100];
    for(int i=0;i<5;i++) {
        scanf("%[^n\]",str[i]);
    }
    for(int j=0;j<5;j++) {
        printf("%s\n",str[j]);
    }
    return 0;
}

I tried to use only

scanf("%s",str[i]);

but then it's ignoring all whitespace inside the input and trimming the output. Also I tried to use

scanf(" %[^\n]",str[i]);

this time little better but it's ignoring the all white space before any character a example input is like.

    Robin Islam
// output showing
Robin Islam
// should show
    Robin Islam

I just want to make this program to allow whitespace on every I mean output should show the same as input without ignoring space. Someone please help me. Tried lot's of way but don't know how to make it works or how......Help please

Thanks, Robin

Robin
  • 446
  • 2
  • 4
  • 24
  • scanf %s read till the end of the string. You'll have to split on spaces in some other way. – BitWhistler Mar 01 '16 at 19:15
  • Try using `scanf("%99[^\n]\n", str[i]);`. – ddz Mar 01 '16 at 19:27
  • `scanf()` just does not read lines well, use `fgets()`. – chux - Reinstate Monica Mar 01 '16 at 19:35
  • actually this is allowing space after any alphabetic character like Robin "space here is allowing" Islam but here "ignoring space here i mean before the word" Robin Islam – Robin Mar 01 '16 at 19:36
  • fgets(); :) thank you very much to all :) – Robin Mar 01 '16 at 19:51
  • @LuizEduardoF. do not try that, `\n` outside the string means *match arbitrary amount of whitespace*. – M.M Mar 01 '16 at 21:47
  • In your code, `%[^n\]` should be `%[^\n]` (your actual version will use the letter `n` as delimiter, and include newlines in the input) – M.M Mar 01 '16 at 21:49
  • @M.M which is what he wants. `\n` outside the string will consume it from input buffer, leaving the next line for scanf to process. – ddz Mar 08 '16 at 14:53
  • @LuizEduardoF. no, `\n` outside the string in scanf does NOT "consume it from input buffer, leaving the line for scanf to process". Please read the documentation for scanf. – M.M Mar 08 '16 at 19:13

2 Answers2

2

scanf is riddled with problems, just search for it here and you'll see. It should be avoided whenever possible.

You're reading whole lines, and there are functions for doing that. fgets and getline. I prefer getline because it handles memory allocation for you, there's no risk of your input overrunning a buffer.

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

int main() {
    char *line = NULL;
    char *lines[5];
    size_t linecap = 0;

    for( int i = 0; i < 5; i++ ) {
        /* Getline will allocate sufficient memory to line.
           It will also reuse line, so... */
        getline(&line, &linecap, stdin);

        /* ...we have to copy the line */
        lines[i] = strdup(line);
    }

    /* line must be freed after calls to getline() are finished */
    free(line);

    for( int i = 0; i < 5; i++ ) {
        printf("%s\n", lines[i]);
    }

    /* Cleaning up all memory is a good habit to get into.
       And it removes clutter from you Valgrind report. */
    for( int i = 0; i < 5; i++ ) {
        free(lines[i]);
    }

    return 0;
}
Schwern
  • 153,029
  • 25
  • 195
  • 336
  • 1
    For completeness, needs `free(lines[i])`. – chux - Reinstate Monica Mar 01 '16 at 19:37
  • @Michi [There's a lot of ways to use `scanf` wrong](https://stackoverflow.com/search?q=scanf). It is best avoided unless you know what you're doing. Even then, probably best to do the IO separately and use `sscanf` instead. – Schwern Mar 01 '16 at 19:46
  • Thanks for the great explanation really help me a lot to understand many thing's. However this is little longer process to solve my current problem but I believe it's definitely going to help me in my future problems. Thanks a lot. – Robin Mar 01 '16 at 19:49
  • @Schwern Agree, but it is nothing wrong with SCANF, only like you pointed too, if is wrong used. To many people treat SCANF like a dangerous function. – Michi Mar 01 '16 at 19:54
  • @Michi [`scanf` is dangerous because it encourages you to pass unbound input into a fixed size buffer](https://stackoverflow.com/questions/1621394/how-to-prevent-scanf-causing-a-buffer-overflow-in-c), and that's just one problem. Dangerous functions are those where the simplest uses are the most dangerous. For example, `strcpy` can be used safely but it requires a bunch of extra code to make it safe *every time you use it*. Or you can use `strlcpy` and not even take the risk. [`scanf` is so bad it has its own tag with 2000+ questions](https://stackoverflow.com/questions/tagged/scanf). – Schwern Mar 01 '16 at 20:08
  • @Schwern I'm sorry, if I made you believe that I don't know about SCANF "problems". SCANF is safe if is used safe. Like I said is wrong used and if happens to be 2000+ question is just because they don't really know much about SCANF. – Michi Mar 01 '16 at 20:17
1
#include<stdio.h>
#include<stdlib.h>

int main() {

    char str[5][100];
    for(int i=0;i<5;i++) {
        fgets(str[i],100,stdin);
    }
    for(int j=0;j<5;j++) {
        printf("%s\n",str[j]);
    }

    return 0;
}
JCollerton
  • 3,227
  • 2
  • 20
  • 25
  • Thanks a lot this is pretty much everything that I need to solve my current problem but one question. when it's printing the result there I can see it's adding extra more newline "\n" can you please tell me why like this. – Robin Mar 01 '16 at 19:47
  • The reason that it works is because in `scanf` you are searching for a predefined pattern in the argument (for example a string, `%s`), then it just finds the first string, ignoring the whitespace. `fgets` just pulls the first set of characters from that source. – JCollerton Mar 01 '16 at 19:53
  • Thank you very much but another problem please #include #include #include int main() { int n; scanf("%d",&n); char str[n][100]; for(int i=0;i – Robin Mar 01 '16 at 20:04
  • Go on chat and I will try and answer this for you. – JCollerton Mar 01 '16 at 20:08
  • This solution leaves the `\n` in the string arrays. You can remove those with `str[i][strcspn(str[i], "\n")] = '\0';` just after the `fgets()`. – chqrlie Mar 01 '16 at 20:10
  • Thank you #JCollerton but actually don't have enough reputation to go in chat. But already thankful to you really appriciate your answer. – Robin Mar 01 '16 at 20:13
  • Thank you can you please give me a example what should I use instead of scanf() to get a number input? at the moment? Thanks – Robin Mar 01 '16 at 20:21