4-bit BCD to 7-segment

Viewed 361

I'm making a 4-bit BCD decoder to 7-segment display in C.

After the output is displayed I ask if the user wants to input again. I can display the desired output and I can exit the program when I don't want to input again.

The problem is when I want to input again it doesn't stop to ask for my input and prints the previous input.

This is the output:

This program displays the decimal equivalent of a
4-bit binary-coded decimal input on a 7-segment LED Display.

Please enter a 4-bit binary-coded decimal: 1000
You've entered 1000.

The decimal equivalent is 8.

              _
             |_|
LED Display: |_|


Would you like to input another 4-bit BCD?
Enter [1] if yes or [0] if no. 1
Please enter a 4-bit binary-coded decimal: You've entered 1000.

The decimal equivalent is 8.

              _
             |_|
LED Display: |_|


Would you like to input another 4-bit BCD?
Enter [1] if yes or [0] if no.

This is my code:

int main() {
    int i, dec, retry = 1; //declare integers i ,dec, and retry
    int bit[4]; //declare integer array with 4 elements
    unsigned char input[5]; //declare string with 5 elements

    printf("This program displays the decimal equivalent of a\n 4-bit binary-coded decimal input on a 7-segment LED Display.\n\n");

    do {         
        printf("Please enter a 4-bit binary-coded decimal: "); //instructs user to enter 4-bit bcd
        scanf("%[^\n]%*c", input); //read string
        printf("You've entered %s.\n\n", input); //shows the 4-bit bcd input 

        for (i=0; i<5; i++) {
            bit[i] = input[i] - '0';
        }

        dec = bit[0]*8 + bit[1]*4 +bit[2]*2 + bit[3];
        printf("The decimal equivalent is %d.\n\n", dec); //shows decimal equivalent

        switch (dec) { //displays 7-segment display depending on the value of dec
            case 0:
                printf("              _ \n             | |\nLED Display: |_|\n");     
                break;
           ...
        }
        printf("\n\nWould you like to input another 4-bit BCD?\nEnter [1] if yes or [0] if no. ");
        scanf("%d", &retry); 
    }
    while (retry == 1);   
}

I also encounter the same problem when using fgets(input, sizeof(input), stdin); instead of scanf("%[^\n]%*c", input);

2 Answers

After the input 1\n is given in order to go on withe next 7 segment number, only 1 is captured by scanf() and \n is left tho the followong one.

But the format %[^\n] tells scanf() to NOT match any input starting with a \n, so the leftover makes the following it return without any value scanf'd. Checking its return value you would find that the second time is 0, so the variable is not updated and that's why the previous value is used.

In order to fix it, since you need %[^\n] in to trim the input (you expect only digits), just add a space before current input format:

scanf(" %[^\n]%*c", input);

in this way any whitespace character (all characters for which isspace() returns true, including '\n', ' ', and'\t') is consumed.

Note that adding

fflush(stdin);

before your first scanf() is Undefined Behavior for the standard C. In some environments it works, but this solution should be avoided as, to say the least, it makes the code non-portable!

Note: you have the same behavior with fgets() because it reads until a \n is found, and like it happened before with scanf, that's exactly the character remaining from the previous user input insertion.


Suggestions on how to check your input

Instead of using %[^\n] format, I suggest a different approach in order to check your input:

while( 1 )
{
    printf("Please enter a 4-bit binary-coded decimal: "); //instructs user to enter 4-bit bcd
    scanf(" %4s", input); //read string

    if( validateBinaryInput( input, 4 ) == 0 )
    {
        break;
    }
    else
    {
        printf( "Wrong input!\n" );
    }
}

With scanf(" %4s", input); you make sure to capture exactly four characters, and to store them within input array. The loop makes sure that whenever the input is not valid the input sequence is repeate. The input validity can be checked with validateBinaryInput() function. Please find below an implementation example:

/* Returns 0 on success, -1 on failure */
int validateBinaryInput( unsigned char *input, size_t len )
{
    int ret = 0;

    if( !input )
    {
        ret = -1;
    }
    else
    {
        int i;
        for( i=0; i<len; i++ )
        {
            if( input[i] != '0' && input[i] != '1' )
                ret = -1;
        }
    }

    return ret;
}

Not only it makes sure that every inserted character is a digit, but it verifies that it is a binary digit. In this way you avoid strange behaviors that would occur inserting an input such as 5: your assignment of

dec = bit[0]*8 + bit[1]*4 +bit[2]*2 + bit[3];

would result in the value 5, and the corresponding 7-segments digit would be printed even if the input wasn't a valid binary word.

This line right here is an issue:

      scanf("%[^\n]%*c", input); //read string

The previous %d only consumes whitespace before the format specifier, not after. This means that this scanf will read an empty string.

To fix this, add a space before so the whitespace will be consumed:

      scanf(" %[^\n]%*c", input); //read string
Related