0

I was looking online for solution for this problem with no result. I'm trying to do while loop to read only characters using scanf(). If user type more than 3 characters than it will display error.

However, my code works partially if I type 3 characters and press enter it works without executing loop this is what I want. If I type 4 characters and press enter also works it executes loop and says "too long" same for 5 char + enter also what I want.

However, if I type 7 characters and enter it executes loop and exits program right away. Any advice?

Ps. I apologize for any grammar error but English is my second language.

#include<stdio.h>
int main(){
char alo;
char alo1; 
char alo2; 
char alo3;

printf("enter 3 characters: ");
scanf(" %c %c %c%c", &alo, &alo1, &alo2, &alo3); 

while(alo3!='\r' && alo3!='\n'){
    printf("too long \n");
    printf("enter ");       
    scanf(" %c %c %c%c", &alo, &alo1, &alo2, &alo3); 
}   
return 0;
}
5
  • 2
    FYI, when you press enter. You entered another character. Commented Sep 1, 2016 at 3:52
  • 3
    When 7 characters are entered, the first scanf reads 4 characters, and the second scanf reads the other 3 characters and the newline. To avoid the problem, you should read a line with fgets and then parse the line with sscanf. Commented Sep 1, 2016 at 3:53
  • With the 7-character (plus newline) input, you get told 'too long' and 'enter' but it doesn't wait for you to type anything. And maybe you don't notice the output because your terminal window vanishes as the program exits. Commented Sep 1, 2016 at 4:08
  • @JonathanLeffler I am able to see "to long" and "enter" before window vanishes, but how to prompt for an input with 7 characters and not exits the program? Commented Sep 1, 2016 at 4:15
  • 1
    Use a buffer that's long (4096 bytes?) and use fgets() to read a line. Then use sscanf() to analyze the input. One advantage is you can include what they typed in the error message. Commented Sep 1, 2016 at 4:19

1 Answer 1

2

Using scanf() only

Using just scanf() to achieve this requires a certain amount of jiggery-pokery. It isn't the best way to code it, but…

#include <stdio.h>

int main(void)
{
    char alo0;
    char alo1;
    char alo2;
    char alo3;

    printf("enter 3 characters: ");

    while (scanf(" %c %c %c%c", &alo0, &alo1, &alo2, &alo3) == 4 &&
           alo3 != '\r' && alo3 != '\n')
    {
        char buffer[4096];
        if (scanf("%4095[^\n]", buffer) == EOF)
            break;
        printf("too long\n");
        printf("enter 3 characters: ");
    }

    printf("Got [%c][%c][%c]\n", alo0, alo1, alo2);
    return 0;
}

The while() condition uses scanf() to read four characters, skipping white space before the first three. Note that it is OK to put newlines in between characters; scanf() doesn't care. If you want line-based input, scanf() is simply the wrong tool for the job! However, assuming that 4 characters are read and the fourth is neither carriage return nor newline, then the code uses:

        char buffer[4096];
        if (scanf("%4095[^\n]", buffer) == EOF)
            break;

to read any characters up to, but not including, a newline. It doesn't mind if there are no such characters so scanf() returns 0. The code then prompts you to enter the correct data and goes around to the main scanf(). This skips the newline that was left behind and then looks for three characters again.

When the while loop exits, it could be because it got three characters and a newline, or because it got fewer characters and EOF, or because the clean-up scanf() detected EOF. The code doesn't attempt to distinguish between these (but it should) and simply prints out three values. Fixing that is not dreadfully hard; simply assign the return from each scanf() to a variable and then test that after the loop:

int rc;
while ((rc = scanf(…)) == 4 && …)
{
    …
    if ((rc = scanf(…)) == EOF) 
        break;
    …
}

if (rc == 4)
    printf(…);
else
    printf("Didn't get 3 characters as requested\n");

Using fgets() for line input

Personally, I think it is easier/better to use fgets() and sscanf() like this:

#include <stdio.h>

int main(void)
{
    char alo0;
    char alo1;
    char alo2;
    char alo3;
    char buffer[4096];
    int rc = 0;

    printf("enter 3 characters: ");

    while (fgets(buffer, sizeof(buffer), stdin) != 0 &&
           (rc = sscanf(buffer, " %c %c %c%c", &alo0, &alo1, &alo2, &alo3)) == 4 &&
           alo3 != '\r' && alo3 != '\n')
    {
        printf("too long\n");
        printf("enter 3 characters: ");
        // In case you get 4 characters but the 4th was not a newline
        // and then you get EOF
        rc = 0;
    }

    if (rc == 4)
        printf("Got [%c][%c][%c]\n", alo0, alo1, alo2);
    else
        printf("Didn't get 3 characters as requested\n");
    return 0;
}

This could report the string that was too long, or otherwise incorrect.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. That make sens. But, what about if i can't use arrays and strings, Is there any other way to do it?
Well, I suppose you could drop buffer and use if (scanf("%*4095[^\n]") == EOF) where the * suppresses assignment. But if that won't do for you, you'll have to invent a solution for yourself — it isn't worth spending the time thinking about it as the constraint being proposed is not realistic. You can scrutinize the POSIX specification for scanf() to come up with any more ideas — and the best of luck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.