2

I'm programming this code (personal software) for a spa which is still in a beta version but I encounter a issue well is more like an idea than an issues let me explain you:

Source code:

    fflush(stdin);
    gets(NC1.Customer_Nameandlastname);
    fflush(stdin);
    printf("provide the customer's age\n\t");

    fflush(stdin);
    scanf("%d",&NC1.Customer_Age);
    fflush(stdin);

this is just part of the source code but what I want to do when the program is running is this:

If the the person that is typing the information makes a mistake or wants to retype the same information but the next command line is already waiting for the input data the question is how would I do to go back to the previous line and then after I finish continue to the next line? So it is like how would I return to the previous scanf() if I already type that information and then the system is waiting for the next line. Please help me because I dont really know what yo do I am seeking how to do it but I still not able to find it.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Arthurdc
  • 21
  • 1
  • 4
    Note that `fflush(stdin)` is not standard. And it's actually strictly *Undefined Behavior*. And `gets()` is dangerous and no longer a part of the standard. – Iharob Al Asimi Jul 30 '16 at 22:05
  • 3
    `fflush(stdin)` is undefined behavior. Please see [this SO post](http://stackoverflow.com/questions/22901901/what-does-fflushstdin-do-in-c-programing). `gets` is [unsafe](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) and is not C anymore. – user3078414 Jul 30 '16 at 22:07
  • Using it just to clean the buffer I to prevent any information before I input data. if you have a better way to clean the buffer in C please let me know. – Arthurdc Jul 30 '16 at 22:08
  • 1
    @Arthurdc There is no such functionality as per the [tag:c] standard, and it's not needed. Input is normally flushed when the `'\n'` occurs. – Iharob Al Asimi Jul 30 '16 at 22:08
  • 1
    Using `scanf` for user input means you've already lost. You can't detect bad input with `scanf`, and you can't reliably recover. – melpomene Jul 30 '16 at 22:12
  • Understand, so If I dont need to use the fflush(stdin) to clean the buffer before getting the data line in the source code. – Arthurdc Jul 30 '16 at 22:12
  • @melpomene You can detect bad input with `scanf()`, who told you you can't? – Iharob Al Asimi Jul 30 '16 at 22:13
  • 1
    @iharob Let's say the user inputs nothing for "age" and just hits enter. How do you detect that? (Answer: You don't, and the user just thinks the program is frozen.) – melpomene Jul 30 '16 at 22:18
  • @melpomene Yes you are 100% right! – Iharob Al Asimi Jul 30 '16 at 22:24
  • Ok so regarding to fflush(stdin) since is not defined in the standard library i should not use it. but what I I have a code like this: #include main() { int a,b; printf("Insert the first number:"); scanf("%d",&a); printf("Insert the second number:"); scanf("%d",&b); printf("A is:%d", a); printf("b is:%d", b); } simple code not bit deal, but while Iam running the program and I got the first printf requesting the first int which is a if I enter the first one then I press Backspace and enter another number any number then hit enter the program skip--- – Arthurdc Jul 30 '16 at 22:47
  • the next scanf(""); then it prints the information in the buffer. – Arthurdc Jul 30 '16 at 22:53
  • How would I avoid having using fflush(stdin) to clean the buffer before the program goes to the next scanf(""); becuase with \n is not working. – Arthurdc Jul 30 '16 at 22:56
  • 1
    @Arthurdc Please [edit] your question to include your code – code in a comment is difficult to read, and people won't do it. Please also include other important information in the **question**, rather than in comments. Also, please specify which problem you are trying to solve, as clearly as possible (ideally, describe how your program behaves, and how you want it to behave, in terms of input and output). – anatolyg Jul 31 '16 at 07:25
  • @Arthurdc: can you accept one of the answers by clicking on the grey checkmark below its score? – chqrlie Aug 18 '16 at 18:00

3 Answers3

1

You cannot portably flush input from stdin with fflush(stdin);. It invokes undefined behavior.

You can read the rest of an offending line from stdin with this function:

void flush_line(FILE *fp) {
    int c;
    while ((c = getc(fp)) != EOF && c != '\n')
        continue;
}

Furthermore, do not use gets(). This unsafe function (you cannot provide the size of the destination array, so any properly crafted input may cause undefined behavior, a flaw that can be used by an attacker to compromise your program). The function was finally removed from the C Standard in 2011. Use fgets() and remove the trailing linefeed if any this way:

if (fgets(line, sizeof line, stdin)) {
    line[strcspn(line, "\n")] = '\0';
    ...
}

You cannot restart a failed scanf(). The return value gives you some information as to where it failed, but not enough to restart the parse reliably. A better way to parse standard input is to read line by line and use sscanf() to parse the lines. Example:

/* read the customer's age.  Keep prompting in case of invalid input */
for (;;) {
    char line[80];

    printf("provide the customer's age\n\t");

    /* force flush of stdout for systems that do not do it
       automatically upon reading from stdin */
    fflush(stdout);

    if (!fgets(line, sizeof line, stdin)) {
        /* end of file reached */
        return -1;
    }
    if (sscanf(line, "%d", &NC1.Customer_Age) == 1) {
        /* input parsed correctly, break out to the next question */
        break;
    }
    /* parse failed, output an appropriate message and restart */
    printf("bad input, please type a number\n");
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Understood never again using gets(). – Arthurdc Jul 30 '16 at 22:58
  • fgets(NC1.Customer_Cellhponenumber, 20,stdin); this would be then a better much better. – Arthurdc Jul 30 '16 at 23:05
  • @Arthurdc: It would be better indeed, but 2 issues: check the return value to ensure something was input, and strip the trailing linefeed `'\n'` that `fgets()` leaves at the end of the destination array. Using a temporary array is still recommended to handle and reject the case of user input exceeding the length of the array. – chqrlie Jul 30 '16 at 23:09
  • 1
    Interesting use of `continue;` instead of `;` – chux - Reinstate Monica Jul 31 '16 at 04:52
  • Suggest `printf("provide the customer's age\n\t"); fflush(stdout);` to insure `'\t'` is printed promptly. – chux - Reinstate Monica Jul 31 '16 at 04:54
  • @deamentiaemundi: oops! fixed the `sscanf` and added more explanatory comments. – chqrlie Jul 31 '16 at 11:32
  • @chux: this is part of my coding conventions. I think it is a good combination of regularity and obviousness. The lone `;` looks awkward, with or without a comment, and the empty block lacks elegance. – chqrlie Aug 03 '16 at 10:45
0

This is really a basic problem, what you want is a loop like this

while (fgets(buffer, SIZE_OF_BUFFER, stdin) != NULL) {
    if (is_input_valid(buffer) == 1)
        break;
    /* Or else, go again */
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
0

After asking the user for all the details, ask something like

Do you want to store this record in the database?

Instruct the user that if he makes a mistake, he should enter garbage for the following fields, and answer "no, I want to discard this record".

Maybe the user will understand by himself that this is what he should do, because asking for such confirmation is a pretty standard practice.

anatolyg
  • 26,506
  • 9
  • 60
  • 134