0

I'm pretty new to C. Writing in Visual Studio 2015, I'm trying to safely prompt a user for a string by using fgets. I want to use fgets to get the string, check if the string is too long, and reprompt the user if it is until they enter a good string. Here is my code

/*
* Nick Gilbert
* COS317 Lab 2 Task 2
*/
#include "stdafx.h"
int main()
{
    char str[10];
    int isValid = 0;
    while (isValid == 0) {
        printf("Please enter a password: ");
        fgets(str, 10, stdin);
        if (strlen(str) == 9 && str[8] != '\n') { //http://stackoverflow.com/questions/21691843/how-to-correctly-input-a-string-in-c
            printf("Error! String is too long\n\n");
            memset(&str[0], 0, sizeof(str));
        }
        else {
            printf(str);
            isValid = 1;
        }
    }
    printf("Press 'Enter' to continue...");
    getchar();
}

However, when I run this and enter a bad string, the excess characters get fed into the next fgets automatically!

enter image description here

How can I fix this to do what I want it to do?

Nick Gilbert
  • 4,159
  • 8
  • 43
  • 90
  • 2
    `printf(str);` --> `printf("%s\n", str);` – MByD Feb 01 '16 at 16:59
  • Best Advice - Quit Visual Studio to learn C! Start with something like CodeBlocks on Windows. – Am_I_Helpful Feb 01 '16 at 16:59
  • [this answer](http://stackoverflow.com/a/35095526/2410359) may be useful. – chux - Reinstate Monica Feb 01 '16 at 17:16
  • Checking for overly-long input is a good idea. The problem here is that, in effect, `fgets` is already doing that for you, and what it does with the overly-long input is, it leaves it on the input stream for somebody else to read. When you call `fgets(str, 10, stdin)` you are saying "read characters from `stdin` into `str` until you see a newline or you have read 10 characters, whichever comes first". – Steve Summit Feb 01 '16 at 20:58
  • the reason it fails is because of your str[8] != \n. you are insisting that the 7th character is a newline. – pm100 Feb 01 '16 at 21:00

2 Answers2

1

If the string read in by fgets doesn't end with a newline, call fgets in a loop until it does, then prompt the user again.

    if (strlen(str) > 0 && str[strlen(str)-1] != '\n') {
        printf("Error! String is too long\n\n");
        do {
            fgets(str, 10, stdin);
        } while (strlen(str) > 0 && str[strlen(str)-1] != '\n') {
    }

Also, never pass a variable at the first argument to printf, particularly if the contents of that variable comes from user entered data. Doing so can lead to a format string vulnerability.

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273
0

Try this:

#include "stdafx.h"
int main()
{
    char str[10];
    int isValid = 0;
    while (isValid == 0) {
        printf("Please enter a password: ");
        fgets(str, str, stdin);
        if (strlen(str) == 9 && str[8] != '\n') { //http://stackoverflow.com/questions/21691843/how-to-correctly-input-a-string-in-c
            printf("Error! String is too long\n\n");
            memset(str, 0, sizeof(str));
        }
        else {
            printf("%s",str);
            isValid = 1;
        }
    }
    printf("Press 'Enter' to continue...");
    getchar();
}

In addition:

While using memset() you can directly use the array_name rather &array_name[0].

Shafi
  • 1,850
  • 3
  • 22
  • 44
  • Rather than `10,9,8` in `fgets(str, 10, stdin); if (strlen(str) == 9 && str[8] ...`, consider `fgets(str, sizeof str, stdin); if (strlen(str) + 1 == sizeof str && str[sizeof str - 2]`. Just like code used well in `memset(str, 0, sizeof(str));`. – chux - Reinstate Monica Feb 01 '16 at 17:20