Video není dostupné.
Omlouváme se.

[c][explained] Problems with scanf

Sdílet
Vložit
  • čas přidán 13. 10. 2020
  • I do my best to credit the sources and people that helped me with the content. For this one, I did get help from people on Reddit and Discord. :D
    Some of the articles that I read to make this:
    / fun-with-scanf-in-c
    stackoverflow.com/a/22902085
    I do know about the places where some of the lines are not consistent with the opacity, but meh, didn't do a retake, I apologize.

Komentáře • 119

  • @theteachr
    @theteachr  Před 3 lety +183

    %s does not consume the whitespace (
    ). It stops at one, and appends the null terminator. That explains why a space in a string doesn't get read into the buffer supplied to scanf. So, it's actually %d that discards the leading whitespace.
    Thanks to the redditor who pointed this out.

    • @maharun
      @maharun Před 2 lety

      does float and double date types also discards the leading whitespace? please tell me......
      and where is the reddit you are talking about?

    • @csbnikhil
      @csbnikhil Před 11 měsíci

      ⁠@@maharunYes. They also discard the white space.
      The subreddit is C_Programming.

  • @Ramash440
    @Ramash440 Před 2 lety +98

    Wish I knew this years ago. When doing uni assignments which involved command line I/O this stuff was such a headache. Everybody in my class found a different way to reinvent the wheel and deal with this behavior.

  • @mitchellrose6865
    @mitchellrose6865 Před 3 lety +39

    Dude thank you so much. Every other solution I found online was crap. This is well explained and your editing is great. Very well made.

  • @joaogabriels.f.5143
    @joaogabriels.f.5143 Před 2 lety +56

    You can use [^
    ] to consume the '
    ', like this: scanf("%[^
    ]s", my_string);
    it reads: read everything that it's not '
    '.
    the trick is that italso matches '
    ' and consume it. So you can interpret it as "read eveything until new line, excluding the new line"
    this is great to read more than one word in a single sentence

    • @shadamethyst1258
      @shadamethyst1258 Před 2 lety +3

      I usually just `fgets` into a temporary buffer and then parse the value of that buffer. I don't like scanf's spurious behavior

    • @abhishek.rathore
      @abhishek.rathore Před 2 lety

      @@shadamethyst1258 or just use a getline

    • @privileged6453
      @privileged6453 Před 2 lety +1

      @@abhishek.rathore getline is not a C standard library function, it’s a POSIX extension

    • @lembranaodesistaissonaoimp5762
      @lembranaodesistaissonaoimp5762 Před 2 lety +1

      Regex?

    • @joaogabriels.f.5143
      @joaogabriels.f.5143 Před 2 lety +1

      @@lembranaodesistaissonaoimp5762 meio que isso mesmo, o scanf aceita certas funcionalidades de regex.

  • @marshallbcodes
    @marshallbcodes Před 11 měsíci +1

    I was banging my head against the wall trying to figure this out. Thank you for the great explanation!

  • @diegoenriqueoviedollanes453
    @diegoenriqueoviedollanes453 Před 2 lety +110

    A good option also is to select what would be the maximum number of characters that scanf will read.
    char name[10];
    scanf("%9s",name);
    So if the user writes more characters than 10, only the first 10 would be taken. Avoiding any buffer overflow.

    • @ramok1303
      @ramok1303 Před 2 lety

      Thanks

    • @NoNameAtAll2
      @NoNameAtAll2 Před 2 lety +9

      maybe only read 10-1 characters, and keep last one for guaranteed /0

    • @tomaszstanislawski457
      @tomaszstanislawski457 Před 2 lety +14

      Actually it **WILL** overflow the buffer for 10-letter input. It will place byte `0` at `name[10]` that does not exist overflowing a buffer. To fix it use "%9s" specifier

    • @diegoenriqueoviedollanes453
      @diegoenriqueoviedollanes453 Před 2 lety +3

      @@tomaszstanislawski457 I haven't programmed in c for a long time, I appreciate the correction if I wrote something wrong. Happy hacking!

    • @dipanjanghosal1662
      @dipanjanghosal1662 Před 2 lety +3

      @@diegoenriqueoviedollanes453 I'd advice you to edit your original comment to %9s because many people don't delve deeper into the replies.

  • @claverbarreto5588
    @claverbarreto5588 Před 3 lety +22

    thanks for this, keep doing it, i found the video super helpful and it taught great things, the illustrations are amazing thank you.

  • @hiltonchapman4844
    @hiltonchapman4844 Před měsícem +1

    Great explanation!
    It's great because it's CLEAR & CONCISE!
    May you travel a great distance into greatness!
    (I know.... after a 3 year lag!!!)
    HC-JAIPUR (30/06/2024)
    .

  • @alexanderbarhoum5934
    @alexanderbarhoum5934 Před 8 měsíci

    it's been 3 years and your video is still saving lives. thank you very much! ❤

  • @ovutai363
    @ovutai363 Před 3 lety +2

    You're so cool, I love your "C explained" series

  • @dharanishrahuls5705
    @dharanishrahuls5705 Před 3 lety +3

    Thank you so much. You were very clear in the explanation. Keep it up. U will reach the sky for sure.

  • @ramok1303
    @ramok1303 Před 2 lety

    Thank you for making this video you help me so much to understand problems with code you've made a really good job

  • @diegoenriqueoviedollanes453

    I always used the space in the scanf, just because it works, thanks for explain that, now everything makes sense.

  • @desmondle4073
    @desmondle4073 Před 8 měsíci

    This is an amazingly insightful video. Thankyou smmmm

  • @xabe1
    @xabe1 Před 2 lety

    Thanks for tge video! I programming on C a lot of time and I never faced this problem, I sure that this knowledge will help me in the future.

  • @chimbwesa
    @chimbwesa Před 3 lety +3

    how am i just finding this!? thank you commandah

  • @diegoenriqueoviedollanes453

    Really nice quality, keep that good work

  • @reussunased5108
    @reussunased5108 Před 2 lety +2

    Me who only uses getline when reading input from user:
    *What is going on here ?*

  • @DityoManob
    @DityoManob Před 10 měsíci

    Best explanation for the scanf issue.

  • @Reydriel
    @Reydriel Před 2 lety

    I've been looking for info on why this happens in scanf for ages, thanks man

  • @dawaxd
    @dawaxd Před 2 lety +1

    very good explanation! helped me a lot

  • @diegoenriqueoviedollanes453

    Thanks for that useful way of asking for input, my programs were full of fflush, not anymore

  • @halbgefressen9768
    @halbgefressen9768 Před rokem +1

    A good solution is using fgets in combination with another parsing method (strtol etc.)

  • @krzysiu3991
    @krzysiu3991 Před 2 lety

    thank you so much, saved my time

  • @obaodelana
    @obaodelana Před 3 lety +1

    Great explanation!

  • @SloeElvis
    @SloeElvis Před 2 lety +16

    This video is beautiful! May i ask what you used to animate it?

  • @ajtan2607
    @ajtan2607 Před 2 lety +2

    This is from my little "test" library (simplified):
    ```
    void get_str(char *s, int n) {
    if (s != NULL && n > 0) {
    int len = 0, maxlen = n - 1;
    int c = getchar();
    while (c != '
    ' && c != EOF) {
    if (len < maxlen) {
    s[len] = c;
    len++;
    }
    c = getchar();
    }
    s[len] = '\0';
    }
    }
    ```
    `s` is the storage and `n` is the storage capacity. The loop extracts all characters from `stdin` until a delimiter newline or `EOF` is found. The condition inside the loop makes sure that only the first `maxlen` characters (excluding the delimiter) are written to `s`. `maxlen` is `n - 1` because at least one element must be reserved for the null character.
    If you give the right arguments, you can type as much as you want without having to worry about buffer overflow. The function will get rid of the excess characters, including the delimiter. I think this is a nice little "training wheel" for beginners.

    • @shadamethyst1258
      @shadamethyst1258 Před 2 lety

      This is exactly what fgets does :)

    • @ajtan2607
      @ajtan2607 Před 2 lety

      @@shadamethyst1258 Not exactly. My function gets rid of the the other characters not stored in the array, including the delimiter newline. `fgets()` does not do this. Please read the description again carefully.

  • @ishikani
    @ishikani Před 2 lety +5

    One lovely trick that I have against this is literally a single macro which is
    #define CINFLUSH scanf("%*[^
    ]");scanf("%*c");
    Works every time, all the time.

  • @mohansivadhas
    @mohansivadhas Před 2 lety

    Thanks Dude!!! u r great!

  • @vikidprinciples
    @vikidprinciples Před rokem

    Man I wasted so much time because of this problem! Thanks for the explanation

  • @tamjidyetagain
    @tamjidyetagain Před rokem

    Thanks it helps a lot

  • @edwardmacnab354
    @edwardmacnab354 Před 2 lety

    very enlightening

  • @Quzhisnadja128
    @Quzhisnadja128 Před 2 lety

    Thank you sir

  • @code-to-learn
    @code-to-learn Před 2 lety

    Nice presentation

  • @chaitanyasampara1169
    @chaitanyasampara1169 Před 2 lety +1

    Now I like C even more

  • @tadiwrr
    @tadiwrr Před 3 lety

    thank you

  • @gianzindozap
    @gianzindozap Před 2 lety

    You could also use %*c to clean the buffer

  • @rishiktiwari
    @rishiktiwari Před 2 lety +3

    I am pretty sure that this is the same problem as Java's scanner. Just write two scanner .nextLine() inputs one after the other and it skips the 2nd one when executed.

    • @theteachr
      @theteachr  Před 2 lety +2

      Yep, it suffers from the same thing.

  • @sameerkulkarni8176
    @sameerkulkarni8176 Před 3 lety +1

    That's awesome.....👌👌

  • @kiitekogra4012
    @kiitekogra4012 Před rokem

    Thanks😊

  • @hwstar9416
    @hwstar9416 Před 7 měsíci

    2:01 actually the
    is still in stdin, however when you read the %d it consumes the
    looking for an integer

    • @theteachr
      @theteachr  Před 7 měsíci

      Addressed in the pinned comment with a little more detail.

  • @sahil1307
    @sahil1307 Před 2 lety

    Can you please tell me from where you learnt this
    Any book, website, playlist

  • @ivanjermakov
    @ivanjermakov Před 2 lety +4

    C is such a mess from a developer experience perspective (understandable, considering when it was introduced). I work as a software engineer for several years and have some C/C++ background, but I still watch the video open-eyed. Very good content and nice visuals.

    • @CrippleX89
      @CrippleX89 Před 2 lety

      Yeah C is really starting to show its age now. It’s been a good run but more modern languages are probably a better choice for most tasks. And with Rust being just as quick, capable, suitable as a systems programming language and becoming more and more mature, C and C++ probably will have to fight for its right to exist.

    • @bva0
      @bva0 Před 2 lety

      @@CrippleX89 Maybe C, but the new C++ standards have everything you'd want in a good language. Smart pointers, threading, softer typing, modular packages, among others...

    • @VeryAwesomeSheep
      @VeryAwesomeSheep Před 2 lety

      @@bva0 C also supports threading

    • @c0smo709
      @c0smo709 Před 2 lety +2

      get good

    • @erek
      @erek Před 2 lety +2

      @@bva0 maybe but all of the backwards compatibility in C++ makes the language very complicated and a horrible mess to deal with

  • @lakshanchamod1208
    @lakshanchamod1208 Před 11 měsíci

    thnks

  • @glewfw7989
    @glewfw7989 Před 2 lety

    im amazed this dude called noob to everyone that uses scanf lol

  • @matheusaugustodasilvasanto3171

    Excellent video, thank you for the explanation.
    What font is being used here?

  • @Voltra_
    @Voltra_ Před 2 lety

    This random youtuber succeeded where teachers have failed, thx. Although I just use C++ instead

  • @bobmichael8735
    @bobmichael8735 Před rokem

    Great video! What software did you use for editing this video?

  • @dhawan177
    @dhawan177 Před rokem

    Thank you so much i am new to coding and this was soo annoying to see even when i write the code correctly it will just stop. Thak you

  • @nihildicit4217
    @nihildicit4217 Před 2 lety

    char str[101];
    scanf("%100[^
    ]", str);
    while(getchar() != '
    ');
    This solves some of the problems but not all of them.

  • @cyrileo
    @cyrileo Před 2 lety

    +10 social creit score ⬆

  • @maharun
    @maharun Před 2 lety +3

    you made a mistake... %s doesn't consume new line.. it leaves the
    in the stdin buffer..
    try taking a string
    then take a char1 input
    then take char2 input
    when you will run it
    1. you enter the string
    2. it SKIPS char1 input
    3. goes to char2 input
    so %s never consumes new line

    • @theteachr
      @theteachr  Před 2 lety +3

      I address this in my comment.

    • @windowsxseven
      @windowsxseven Před 2 lety

      @@theteachr "I address this in my comment" 🤓 screw off

  • @avastorneretal
    @avastorneretal Před 2 lety

    std::cout

  • @carloscapitinealexandremut8898

    Thanks for the explanation, but i coud't get the problem solved. is there any other way to get out of this?

    • @theteachr
      @theteachr  Před 3 lety +3

      Having `while (getchar() != '
      ');` before scanning a sequence of characters should work just fine. Join the Discord and post the query for a more elaborate explanation specifically tailored to your use case. discord.gg/ANUEGSZPvn

  • @GrandNecro
    @GrandNecro Před 2 lety +1

    what software did you use to edit the video?

    • @chri-k
      @chri-k Před 2 lety +2

      Apparently it was made using keynote

  • @sadhmansarker9133
    @sadhmansarker9133 Před rokem

    can smn explain the while (getchar() != '
    '; part i dont get it

  • @yooyo3d
    @yooyo3d Před 2 lety

    scanf("%[^
    ]
    ", name);
    Read everything til new line into name then consume new line.

    • @techeadache
      @techeadache Před 11 měsíci

      I tried this! The function scanf(_s) never returns. It's an infinity loop for string input.
      Although, it works for anyting that is NOT a string. For example,
      scanf_s("%c
      ", &gender, 1u); // WORKS AND RETURNS

  • @demnyan
    @demnyan Před 2 lety

    cin cout one love 🦊💖

    • @theteachr
      @theteachr  Před 2 lety

      If you do a cin on an int, but the user entered something that could not be parsed as one, the variable would be set to 0. I had no idea how to differentiate between a valid input of 0 and an invalid input, as in both the cases the variable would have the same value.
      It sets some global error flag (I think). IMO, it should have been something that the programmer couldn’t skip.

    • @demnyan
      @demnyan Před 2 lety

      @@theteachr for int you can use atoi( ) and there will be no errors )

  • @oanminhkhoi6584
    @oanminhkhoi6584 Před 7 měsíci

    But why adding that weird space before %c would make it work ?

    • @theteachr
      @theteachr  Před 7 měsíci

      A space in the format string for `scanf` means any amount of whitespace (newlines, spaces, tabs, ...). `scanf("%c %d", &gender, &age)` would read the input `m 45` and assign `m` to `gender` and `45` to `age`.

    • @oanminhkhoi6584
      @oanminhkhoi6584 Před 6 měsíci

      ​@@theteachr Appreciate the reply. Thanks alot

  • @alejandroalzatesanchez

    and we have problems with like python/java/lua/etc this is worse

  • @floskater99
    @floskater99 Před 2 lety

    Pretty sure Scanner.nextLine() and Scanner.nextInt() in Java have exactly the same problem xD

  • @katsumikougen8351
    @katsumikougen8351 Před 3 lety

    Bisqwit brought me here.

  • @23trekkie
    @23trekkie Před 2 lety

    Name: Genie
    Age: six
    Age: Age: Age: Age: Age: Age: Age: Age:....

  • @eldiablo9541
    @eldiablo9541 Před 2 lety

    You would think that after all this time something as simple as this would have been "fixed". I wonder why they haven't changed that

  • @leoleo10xd
    @leoleo10xd Před rokem

    does this problem have a name?

    • @theteachr
      @theteachr  Před rokem

      I wouldn’t think so. It’s expected behavior after all. The programmer is expected to know of the subtlety and that’s what is the problem.

  • @CurrentlyObsessively
    @CurrentlyObsessively Před 3 lety +2

    These fixes are not effective. You should test input at each input. You can even write a small input check function to consolidate your code.
    I recommend Hacking the Art of Exploitation by Jon Erickson. The chapter on programming is strictly C programming and has numerous examples of input and error checks.

    • @theteachr
      @theteachr  Před 3 lety +1

      Thanks for the input and the recommendation!

  • @johnjcb4690
    @johnjcb4690 Před 3 lety

    VERY NICE explaining and work , great. But It is not working in Eclipse. First Scanf processes, the second to last not, And it would only print PRintfs. All correct
    include
    int main()
    {
    char name[20];
    float greutate;
    int ziua;
    int luna;
    int an;
    //scanf("specificatori de format", adresele_din_memorie);//
    printf("Name of sir:
    :");
    fflush(stdout);
    scanf(" s", nume);
    printf("Cat este de greu domnul:[kg]
    ");
    fflush(stdout);
    scanf(" %f", &greutate);
    printf("Dati ziua:
    ");
    fflush(stdout);
    scanf(" %d", &ziua);
    printf("Dati luna:
    ");
    // windows
    fflush(stdout);
    scanf(" %d", &luna);
    // afisare ziua si luna
    an = 2020;
    printf("Astazi este %d/%d/%d!", ziua, luna, an);
    return 0;

    • @theteachr
      @theteachr  Před 3 lety

      scanf("%s", nume);
      I think the missing % is causing you an issue.

  • @samuelwaller4924
    @samuelwaller4924 Před 2 lety +2

    Your first problem was only having two genders lol

    • @theteachr
      @theteachr  Před 2 lety +2

      I want more reactions than just being able to ❤️ the comments.

  • @ivanborsuk1110
    @ivanborsuk1110 Před 2 lety

    so unnecessary

    • @chri-k
      @chri-k Před 2 lety +1

      What exactly?

  • @blushy9215
    @blushy9215 Před 2 lety

    its pronounced char as in charcoal not care........ 👎👎👎 boo

  • @leoleo10xd
    @leoleo10xd Před rokem

    " %[^
    ]s " worked for me.
    printf("
    Name: ");
    scanf(" %[^
    ]s ", vec[i].name);