Why We Should Never Use gets()... And Why To Use fgets() Instead | C Programming Tutorial

Поделиться
HTML-код
  • Опубликовано: 7 май 2022
  • Why we should never use the gets() function in C, including an explanation as to how it is unsafe due to buffer overflow, and an explanation as to why we should use fgets instead. Source code: github.com/portfoliocourses/c... Check out www.portfoliocourses.com to build a portfolio that will impress employers!

Комментарии • 40

  • @emirhandemir3872
    @emirhandemir3872 2 года назад +17

    Great explanation

  • @sabitnirob983
    @sabitnirob983 Год назад +1

    Thanks for this class.. ❤️👍

  • @AhmadAlMutawa_abunoor
    @AhmadAlMutawa_abunoor Год назад +2

    This video is very informative. I wish you would include a way to flush the stdin before reading any left over from the previous attempt. That would have been wonderful.

    • @PortfolioCourses
      @PortfolioCourses  Год назад +1

      Hi Ahmad, this video covers how to clear the standard input buffer: ruclips.net/video/N7-MueK2CX8/видео.html. :-)

  • @sai_eshu7159
    @sai_eshu7159 9 месяцев назад +1

    great explanation....

  • @gourabmaityeducation
    @gourabmaityeducation 11 месяцев назад

    Thank you so much 😊😊

  • @elmarc4289
    @elmarc4289 9 месяцев назад

    Muchas gracias amigo, de verdad que me has ayudado mucho. Saludos desde México

  • @Brock-Landers
    @Brock-Landers 2 года назад +6

    My 2 pennies, you can just discard the overflow up to newline so your next call will be clean.
    For input from stdin:
    if(strchr(buffer, '
    ') == NULL)
    while((fgetc(stdin) != '
    ');
    For input from a file also check for end of file or you will go into an infinite loop :
    if(strchr(buffer, '
    ') == NULL)
    {
    char discard;
    while((discard = fgetc(fp) != '
    ' && discard != EOF);
    }
    Then strip the newline character, only if one exists:
    buffer[strcspn(buffer, "
    ")] = '\0';
    Now buffer contains exactly what one would expect.

    • @PortfolioCourses
      @PortfolioCourses  2 года назад +2

      Thanks for sharing this! 🙂

    • @edgarherrera8587
      @edgarherrera8587 Год назад +1

      Hi Brock. Do you have a code (i.e. at GitHub) where I can see your solution implemented? I have been looking for a solution since days ago. But this might bring me some light. Thanks

    • @Brock-Landers
      @Brock-Landers Год назад

      @@edgarherrera8587 Here's a video I made on the subject that uses this exact code:
      ruclips.net/video/ITR-Acel7tg/видео.html
      There is a link in the description to the source code on my github for that channel.

    • @cervelex
      @cervelex Год назад

      @@Brock-Landers nice

  • @mateuscruz3009
    @mateuscruz3009 6 месяцев назад +1

    When you use the second fgets in the end of video, shouldn't have another space for data input in terminal? One for fgets buffer and other for fgets next? You only typed and entered one time, one data, why it happened?

  • @Stekaren
    @Stekaren 5 месяцев назад

    i tried something like this
    int main(){
    char a[] = "hello"; // here im initializing my char array with a string without declaring how many characters i want in the array, i know that the compiler will put 6 characters away so that the char array a may store 5 characters + null characters = 6 characters.
    printf("enter string:
    "); //
    fgets(a, 21, stdin); /* here i use fgets, and i have 21 characters i want to write, which are "you are most welcome" 20 characters + white space character + the null character at the end that indicates end of the string = 21 characters total */
    printf("string: %s", a); // will print "you are most welcome"

    return 0;
    }
    i got no warning writing this. So still the question remains, do i need to dynamically allocate memory like you did sir or is this legal in C?

  • @py4311
    @py4311 3 месяца назад

    Afaik, most of time, we would get more spaces than how much we have applied due to memory alignment for performance. but why 16 bytes[a-p] when you applied for 5, I think it would be 8.

  • @Stekaren
    @Stekaren 5 месяцев назад

    hello sir im trying to learn c on my own. so why i came here from neso academy was because of this: video was about difference between scanf and gets, in order to print out the white space character. what i understood was when the scanf() function sees a white space character it does not print anything else past that, so if i write "you are most welcome" it will only print out "you" and ignore the rest. with gets() the problem was as you are also mentioning, it can overwrite in the memory and use memory that is not allocated for the char array.
    so in order to get the white space character and print out the complete sentence "you are most welcome" i can use fgets() function instead of gets(). my question is sir, do i need to dynamically allocate memory everytime with the malloc function or can i just go ahead and use fgets? im new to this and i appreciate any help you can give me

    • @swati9841
      @swati9841 Месяц назад

      we can use the fgets function only if we know the size of the string so instead of using fgets its better to use selective scanf syntax:-scanf("%[^
      ]", str); in this syntax ^ indicates starting of string and
      indicates the end of the line and str is string name

  • @ritapiu319
    @ritapiu319 7 месяцев назад

    謝謝!

  • @fadyasaad1105
    @fadyasaad1105 Год назад +1

    Is there a way to clear stdin before fgets again??

    • @PortfolioCourses
      @PortfolioCourses  Год назад

      Great question Fady! :-) This video might help you out: ruclips.net/video/0UJX96_ZpVE/видео.html. These answers might help too: stackoverflow.com/q/7898215.

  • @luka_9196
    @luka_9196 7 месяцев назад

    Hi sorry I’m new to programming but if i use a second fgets to prevent overflow and the user doesn’t write a string longer than the max characters I chose the fgets want an input how do I resolve this issue thank you for the help.

    • @henry_tsai
      @henry_tsai 3 месяца назад

      The second fgets isn't needed if you just want to avoid overflow from the first input, fgets already limits how many characters it's going to read.
      However, I assume you want to read user input for the second time and the remaining characters in the stdin stream may wrongly be read in. In which case, a solution I come up with is to: 1.check if the user's first input is longer then first input buffer and has thus remaining data in stdin stream 2. if so, clear stdin stream 3. read user input.
      For step1, since fgets will stop reading if a
      is encountered, you can check if the first input string contains a
      , ex: with buffer size 5 and user inputs "abc
      ", then you knows there isn't any excess characters in stdin, then you can use a "if" to skip step2 and use another fgets() to read second input. if first input doesn't contain
      , then it means user input more character then the buffer size, ex: buffer size 5 but user inputs "abcdef
      ", then in buffer will be "abcd\0", and "ef
      " will remain in stdin, then you can use:
      char c[2];
      while(c[0] != '
      '){
      fgets(c, 2, stdin);
      }
      which should clear out any remain characters in stdin, then you can continue to step3 and use another fgets() to read.

    • @haroldcruz8550
      @haroldcruz8550 Месяц назад

      That's actually considered the best practice specially for newbies

  • @josso8584
    @josso8584 11 месяцев назад

    Soy de Mexico y tuve que ver tu video en subtitulos pero tienes mi like jeje

    • @PortfolioCourses
      @PortfolioCourses  11 месяцев назад

      That's awesome! :-) I hope one day RUclips does AI translation on the fly. Hopefully this translation makes sense.

  • @Architector120
    @Architector120 2 года назад +2

    Can you explain how to make non-blocking delay or events in while loop in C? i came up with this approach... it works but CPU 100% loaded... hope you get the idea...
    #include
    #include
    void my_event(clock_t *cnt, int time_delay)
    {
    if(clock() - *cnt >= time_delay)
    {
    *cnt = clock();
    printf("%ld
    ", clock());
    }
    }
    int main()
    {
    clock_t tim = 0;
    while(1)
    {
    my_event(&tim, 1000);
    if(tim == 10000) break;
    }
    return 0;
    }

    • @PortfolioCourses
      @PortfolioCourses  2 года назад +2

      I'm not too sure, I think it depends on what you mean by non-blocking delay and what you're trying to do. Is the goal to delay executing some code by some amount of time, but to allow other code to execute in the meantime? If that's the case, it sounds like a situation best solved using threads. These folks have an interesting article on the idea: learn.digilentinc.com/Documents/407. And others seem to suggest using threads to solve the problem: stackoverflow.com/questions/7771142/non-blocking-sleep-timer-in-c. Maybe I can make a video about this, though I think I'd likely solve the problem using threads. :-)

    • @Architector120
      @Architector120 2 года назад

      I already thought about using threads... But here's the catch... CPU single threaded...

    • @PortfolioCourses
      @PortfolioCourses  2 года назад +1

      @@Architector120 Interesting, that makes things more challenging. 🙂
      I think if the delay is for some amount of time, the general idea would be something like this:
      time1 = the current time
      do {
      // do work that can be done now
      time2 = the current time
      diff = difference between time2 and time1
      } while (diff < desired);
      // do work that could only be done after diff amount of time has passed
      Just out of curiosity, what is the work that needs to be done in-between waiting some amount of time? Is it something that can be put into a function and called frequently? Is the delay for some fixed amount of time like 10 seconds, or is it until some event has occurred? Maybe I can make a video on this idea some day.

  • @Awwe12675
    @Awwe12675 Год назад

    He bro stdin Is macro
    stdin is 1 stdout is 0
    Like that
    #define stdin 1
    #define stdout 0
    stdin only to tell for programmer hey we need use input with fgets function

    • @PortfolioCourses
      @PortfolioCourses  Год назад +3

      Yes, the actual term "stdin" is a macro in C. If anyone wants to learn more about that you can read up on it here: man7.org/linux/man-pages/man3/stdin.3.html. The standard input stream is a bigger concept than just a macro that sets to 1 though. It's not even necessarily going to be user input, it could be a file if it is re-directed when the programmer is run. Maybe one day I can make a video on the standard input streams and re-directing them. :-)

  • @bolvarsdad3825
    @bolvarsdad3825 Год назад +3

    Here's the function I always use to take input, which I afterwards use other accompanying functions to convert the string value to what I need.
    #include
    size_t get_line(char *buffer, size_t bufsz)
    {
    size_t buflen = 0;
    int ch;
    while ((ch = getchar()) != EOF && ch != '
    ')
    if (buflen < bufsz)
    buffer[buflen++] = ch;
    return buflen;
    }
    int main(int argc, char **argv)
    {
    char buffer[5];
    size_t nread = get_line(buffer, 5);
    // I don't need to null terminate the buffer because of this printf format
    // If you were using puts instead of printf here, you should null terminate it by writing:
    // buffer[nread] = '\0';
    // But since we're using printf in this case that can be ignored.
    printf("%.*s
    ", (int)nread, buffer);
    return 0;
    }
    Input: 12345678
    Output: 12345

    • @PortfolioCourses
      @PortfolioCourses  Год назад

      Thank you for sharing this! :-)

    • @IonizedComa
      @IonizedComa Год назад

      I always just use scanf("%[^
      ]s", stringName);

    • @PortfolioCourses
      @PortfolioCourses  Год назад

      @@IonizedComa that works! 🙂

    • @Queue_27
      @Queue_27 Год назад

      to me, getchar is the only one that make sense out of everything. i always feel safe considering every char even \0 and
      .