4-bit BCD to 7-segment - c

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);

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

C Program -- While loop with scanf function condition runs even if condition is not met. How to fix this?

I am attempting to create a program where you input 2 numbers and then print out the first number to the power of the second number.
I tried using a while loop to say that if the numbers you input are two, then you keep repeating the program, otherwise if you input more than 2, you end the loop and print out that you input too many numbers.
However, the code still works if I input more than two, and I assume this is because the scanf function ignores anything other than the first two numbers I input.
How do I fix this program so that it works as I had intended?
#include <stdio.h>
#include <math.h>
int main(void)
{
float x, exp;
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
while(scanf("%f%f", &x, &exp) == 2)
{
printf("%f\n", pow(x, exp));
printf("Enter the next pair of numbers:\n");
}
printf("You entered too many numbers!\n");
return 0;
}
User input is tricky. Get input as a string, and loop on that. Just keep in mind that the user may enter each input one at a time. Either require it to be correct (user types two numbers followed by Enter) or take effort to handle multiple correct inputs (user types one number followed by Enter and then another number followed by Enter). Here we will require both inputs on the same line:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
float x, exp;
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
char s[1000];
while (fgets(s, sizeof(s), stdin))
{
if (sscanf(s, "%f %f", &x, &exp) != 2)
{
puts("Invalid input, my dude.");
break; // Stop running if user supplies fewer than two valid inputs
}
else
{
printf("%f\n", pow(x, exp));
}
printf("Enter the next pair of numbers:\n");
}
return 0;
}
This requires the user to terminate the stream to quit, BTW, by pressing ^Z,Enter on Windows or ^D on Linux. You could easily add additional methods to terminate in the loop (for example, terminate if s is empty or sscanf returns 0), but this is not necessary.
EDIT: There are other issues too. For example, what if the user enters more than two inputs on a line. Should I detect that? Again, for programs like this, it is ok to assume that inputs will be valid unless your assignment specifically requires you to detect error conditions.
EDIT 2: If you wish to catch a more than two items entered error, you must make sure that sscanf() consumed the entire line. Fortunately there is an easy way to do that. Change line 15 to:
int n;
if ((sscanf(s, "%f %f %n", &x, &exp, &n) != 2) || (s[n] != '\0'))
What that does is skip all whitespace after the second float to either end of string or the next available item in the string and returns the index of that position in n.
After that we only need to verify that the end of string condition is what was found.
If the user types more than two numbers this will not be an error. They will be stored in the input buffer and read in the next call of scanf.
Pay attention to that the user can type two numbers on the same line or in different lines.
In fact you can not prevent the user to enter on one line numerous numbers. But you can check that at most two lines there are entered two numbers.
So you need to split the input.
The first number will be read using scanf and the second number will be read using fgtes.
Here is a demonstration program.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
while ( 1 )
{
float x, exp;
if ( scanf( "%f ", &x ) != 1 ) break;
char s[20];
if ( !fgets( s, sizeof( s ), stdin ) ) break;
int n;
if ( sscanf( s, "%f %n", &exp, &n ) != 1 || s[n] != '\0' ) break;
printf("%f\n", pow(x, exp));
printf("Enter the next pair of numbers: ");
}
puts( "You entered too many or too few numbers!" );
return 0;
}
Its output might look like
Please enter a number followed by the power you want to raise it to: 1 2
1.000000
Enter the next pair of numbers: 2
3
8.000000
Enter the next pair of numbers: 4
5 6
You entered too many or too few numbers!
Simply put, your code will always continue. This is just because of how scanf works:
Scanf scans input from stdin. When scanf reaches the end of stdin and still hasn't scanned everything it expected to scan, it waits until the user sends a newline (presses enter). In other words, so long as you enter valid floats, your scanf will never return a value lower than the expected float count.
On the other end, once scanf is finished with scanning stdin, it immediately evaluates the variables and returns. This means that there is still some input left in stdin that has not yet been read. In fact, when scanf next runs, it will resume scanning exactly where it left off. Take this sample code:
int main()
{
int x,y;
int ct = scanf("%d%d",&x,&y);
printf("%d (%d,%d)\n",ct,x,y);
scanf("%d",&x);
printf("%d\n",x);
}
If you compile and run this, try inputting three ints at once. The second scanf will immediately terminate because it is reading the third integer that was inputted.
If you are trying to get a specific number of inputs, I would suggest scanning the user's input as a string and then using sscanf (scanf for strings). You could also check for the number of spaces in the string, then, to determine if there are too many inputs. If you want to get a little tricky, you could continue to use scanf but then check whether bytes are remaining in stdin before you continue. Here is a good answer that will help if you want to keep using scanf as is, but checking whether stdin is empty.
There is another issue with your code though; what happens when a user inputs something other than a float? But that is a different question entirely (and one where my personal suggestion would be to analyze the entire scanned string).
The problem with using scanf is that it treats all whitespace characters (e.g. spaces and newline characters) as equal. For example, scanf won't care whether the numbers you entered are on the same line or not.
If scanf is asked to read two numbers, but the user instead enters three numbers on the same line, then your first call to scanf will only read the first two numbers and leave the third number on the input stream, so that the next scanf call in the next loop iteration will read it as the next first number. This is not what you want.
Therefore, for line-based user input, it is probably better not to use scanf. Instead, it makes more sense to always read exactly one line per loop iteration. You can do this with the function fgets.
After using fgets to read a line of input, two of the other answers use sscanf to convert both numbers at once. However, you can also convert one number at a time using strtof:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
int main(void)
{
//we want to provide the user with a different prompt the first time,
//so we must remember whether it is the first time
bool first = true;
//infinite loop
while ( true )
{
float x, exp;
char line[100];
char *p, *q;
//prompt user for input
if ( first )
{
printf(
"Please enter a number followed by the power "
"you want to raise it to: "
);
//remember to use a different prompt next time
first = false;
}
else
{
printf("Enter the next pair of numbers: ");
}
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
//break out of infinite loop
break;
}
//attempt to find newline character
p = strchr( line, '\n' );
//make sure entire line was read in
if ( p == NULL && !feof(stdin) )
{
//only accept missing newline character on end-of-file
if ( !feof(stdin) )
{
int c;
printf( "Line too long for input buffer!\n" );
//discard remainder of line
do
{
c = getchar();
} while ( c != EOF && c != '\n' );
continue;
}
}
else
{
//remove newline character by overwriting it with null character
*p = '\0';
}
//start parsing at start of line
p = line;
//attempt to convert first number
x = strtof( p, &q );
//determine whether conversion of first number succeeded
if ( p == q )
{
printf( "Conversion of first number failed!\n" );
continue;
}
//continue parsing at end of first number
p = q;
//attempt to convert second number
exp = strtof( p, &q );
//determine whether conversion of second number succeeded
if ( p == q )
{
printf( "Conversion of second number failed!\n" );
continue;
}
//verify that remainder of line is either empty or only
//consists of whitespace characters
for ( p = q; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected character found after second number!\n" );
//we cannot use the "continue" keyword here, because
//we want to continue to the next iteration of the
//outer loop, not the inner loop
goto continue_outer_loop;
}
}
//print result
printf( "Input accepted, the result is: %f\n", pow(x, exp) );
continue_outer_loop:
continue;
}
return 0;
}
This program has the following behavior:
Please enter a number followed by the power you want to raise it to: abc
Conversion of first number failed!
Enter the next pair of numbers: 10
Conversion of second number failed!
Enter the next pair of numbers: 10 abc
Conversion of second number failed!
Enter the next pair of numbers: 10 20
Input accepted, the result is: 100000000000000000000.000000
Enter the next pair of numbers: 10 20 30
Unexpected character found after second number!
As you can see, the program correctly rejects the input if it contains a third number.

Analyze a variable in C and then decide what to do

Hi I'm still a C beginner and a beginner coder,
I've been trying to develop some sort of a rudimental interface via command line and would like to implement that when the user inserts something that isn't a number the loop breaks and moves on
(my dream would be that it checks when the input is equal to the word new) Anyhow here's my code snippet:
do {
printf("\nInsert the score you obtained: ");
scanf("%d", &avg);
} while ( isdigit(avg) == 0 );
Basically until the input is a number it will keep going and when something that isn't an integer is inserted it should exit the loop.
To receive something that isn't an integer, you have to scanf something that isn't an integer.
char* input;
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", input);
...
Now that you have a variable that can hold both "quit" and some number (represented as characters), you need to make a decision based on what kind of input you received.
char input[80];
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
while ( strncmp(input, "exit", 4) == 0 );
this means also that you'll have to possibly convert the "string" of the number into a number value.
char input[80];
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
int number = convert_to_number(input);
while ( strncmp(input, "exit", 4) == 0 );
but the conversion should only happen if it looks like a number
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
if ( looks_like_number(input) ) {
int number = convert_to_number(input);
}
} while ( strncmp(input, "exit", 4) == 0 );
and finally you might need to collect multiple inputs, as the loop will accept them now
do {
printf("\nInsert the score you obtained, or exit to quit: ");
scanf("%[^/n]", &input);
if ( looks_like_number(input) ) {
sum = add(sum, convert_to_number(input));
}
} while ( strncmp(input, "exit", 4) == 0 );
This is only one solution of a very large number of possible ways to do this.
This solution also could be improved (like trimming white space around the "exit" flag, so a user could type " exit" or "exit " to leave. One could also make the loop not a loop, as the question seems to imply entering one number or "exit" once, while a loop will permit many numbers until exit was typed. And one could remove the silly add function which was only used to demonstrate with a word a very clear idea, when + might do.
Even if the above loop / approach isn't a perfect fit for your need, please look at it carefully because the ideas within it can be used to make your program a success.
Also, don't use isdigit for checking for an entire number. Look into sscanf which is like printf but for reading stuff out of strings. sscanf your number off the string, and check the return value to see if you found a number within the string.
isdigit (prototyped as int isdigit (int Test_Character);) is not the right function to use with testing whether an int is a digit or a number. isdigit() is used rather to test if a single character is a decimal digit (0-9). The input to this function must be a character with integer value between 0 and 255. ( refer to ASCII table to view what these value are.)
The right thing to do here is to determine if scanf converted an input value correctly.
The function scanf() is prototyped with a return value, indicating success or failure, but your code does not currently check it.
So, in summary, your while loop can be written using the return of scanf():
int main(void)
{
int count = 0;
int avg= 0;
do
{
printf("\nInsert the score you obtained: ");
count = scanf("%d", &avg);
}while(count > 0); //stays in loop for any numeric value
// } while ( isdigit(avg) == 0 );//Note; input containing decimal points will be truncated
//to contain only integer portion
return 0;
}
As long as the input is an integer numeric value, scanf will return count as a positive value (the number of values scanned correctly.)
For example:
123, -123, 8, 0 will all allow the loop to continue.
a, dfg will all result in a failed attempt to convert the input to a numeric, and return EOF (-1)
Process as string representation of numeric: (similar behavior with alternative coding approach.)
I promised to show how to use strtol():
By changing the input format specifier from "%d" to "%s", scanf() will read the input value of 123 as a string: "123". When input is brought into your program as a string representation of a numeric, it must be converted to a number a numeric type before it can be used. strtol() can be used to do this conversion.
Here is a modification of your original program illustrating how it can be done:
int main(void)
{
int count = 0;
char avg[20] = {0};//changed to string variable
long val = 0;
bool success = FALSE;
do
{
printf("\nInsert the score you obtained: ");
count = scanf("%s", avg);//changed format specifier to read strings
if(count)
{
success = parseLong(avg, &val);//see correct usage of strtol in function
}
}while(success); //Stays in loop for any numeric input.
//Note: input containing decimal values
//will be truncated to contain integer portion only.
return 0;
}
bool parseLong(const char *str, long *val)
{
char *temp;
BOOL rc = TRUE;
errno = 0;
*val = strtol(str, &temp, 0);
if (temp == str || ((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE))
rc = FALSE;
return rc;
}

Using malloc in C to make sure that user enter certain digits

So I want to write a program to check if user enter. Say requirement is 4 digits number, if user enters 5 then program keeps asking user to renter exactly 4 digit number.
I got the working code like this: basically use scanf to read in a string value, then use strlen to count number of digits. If user enters the correct digit, then I use atoi to convert that string into an int, which I will use for later.
Say requirement is 4 digit number:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int digit, mynumber;
int digit = 5;
char str[5];
/* Checking if enter the correct digit */
do {
printf("Enter a %d digit number\n", digit);
scanf("%s", &str);
if (strlen(str) != digit) {
printf("You entered %d digits. Try again \n", strlen(str));
} else {
printf("You entered %d digits. \n", strlen(str));
printf("Converting string to num.....\n");
mynumber = atoi(str);
printf("The number is %d\n", mynumber);
}
} while (strlen(str) != digit);
return 0;
}
I want to modify this a bit. Instead of doing char str[5] for 5 digit string. I want to try a dynamic array.
So in place of char str[5], I do this:
char *str;
str = malloc(sizeof(char) * digit);
Running this through the code gives seg fault. Can anyone help me with this?
This is the complete code with the issue
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int mynumber;
int digit = 5;
char *str;
str = malloc(sizeof(char) * digit);
/* Checking if enter the correct digit */
do {
printf("Enter a %d digit number\n", digit);
scanf("%s", &str);
if (strlen(str) != digit) {
printf("You entered %d digits. Try again \n", strlen(str));
} else {
printf("You entered %d digits. \n", strlen(str));
printf("Converting string to num.....\n");
mynumber = atoi(str);
printf("The number is %d\n", mynumber);
}
} while (strlen(str) != digit);
return 0;
}
While you can use the formatted input function scanf to take your input as a string, scanf is full of a number of pitfalls that can leave stray characters in your input stream (stdin) depending on whether a matching-failure occurs. It also has the limitation using the "%s" conversion specifier of only reading up to the first whitespace. If your user slips and enters "123 45", you read "123", your tests fail, and "45" are left in stdin unread, just waiting to bite you on your next attempted read unless you manually empty stdin.
Further, if you are using "%s" without the field-width modifier -- you might as well be using gets() as scanf will happily read an unlimited number of characters into your 5 or 6 character array, writing beyond your array bounds invoking Undefined Behavior.
A more sound approach is the provide a character buffer large enough to handle whatever the user may enter. (don't Skimp on buffer size). The read an entire line at a time with fgets(), which with a sufficient sized buffer ensure the entire line is consumed eliminating the chance for characters to remain unread in stdin. The only caveat with fgets (and every line-oriented input function like POSIX getline) is the '\n' is also read and included in the buffer filled. You simply trim the '\n' from the end using strcspn() as a convenient method obtaining the number of characters entered at the same time.
(note: you can forego trimming the '\n' if you adjust your tests to include the '\n' in the length you validate against since the conversion to int will ignore the trailing '\n')
Your logic is lacking one other needed check. What if the user enters "123a5"? All 5 characters were entered, but they were not all digits. atoi() has no error reporting capability and will happily convert the string to 123 silently without providing any indication that additional characters remain. You have two-options, either use strtol for the conversion and validate no characters remain, or simply loop over the characters in your string checking each with isdigit() to ensure all digits were entered.
Putting that altogether, you could do something like the following:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define NDIGITS 5 /* if you need a constant, #define one (or more) */
#define MAXC 1024
int main (void) {
int mynumber;
size_t digit = NDIGITS;
char buf[MAXC]; /* buffer to hold MAXC chars */
/* infinite loop until valid string entered, or manual EOF generated */
for (;;) {
size_t len;
printf("\nEnter a %zu digit number: ", digit); /* prompt */
if (!fgets (buf, sizeof buf, stdin)) { /* read entire line */
fputs ("(user canceled input)\n", stdout);
break;
}
buf[(len = strcspn(buf, "\n"))] = 0; /* trim \n, get len */
if (len != digit) { /* validate length */
fprintf(stderr, " error: %zu characters.\n", len);
continue;
}
for (size_t i = 0; i < len; i++) { /* validate all digits */
if (!isdigit(buf[i])) {
fprintf (stderr, " error: buf[%zu] is non-digit '%c'.\n",
i, buf[i]);
goto getnext;
}
}
if (sscanf (buf, "%d", &mynumber) == 1) { /* validate converstion */
printf ("you entered %zu digits, mynumber = %d\n", len, mynumber);
break; /* all criteria met, break loop */
}
getnext:;
}
return 0;
}
Example Use/Output
Whenever you write an input routine, go try and break it. Validate it does what you need it to do and catches the cases you want to protect against (and there will still be more validations you can add). Here, it covers most anticipated abuses:
$ ./bin/only5digits
Enter a 5 digit number: no
error: 2 characters.
Enter a 5 digit number: 123a5
error: buf[3] is non-digit 'a'.
Enter a 5 digit number: 123 45
error: 6 characters.
Enter a 5 digit number: ;alsdhif aij;ioj34 ;alfj a!%#$%$ ("cat steps on keyboard...")
error: 61 characters.
Enter a 5 digit number: 1234
error: 4 characters.
Enter a 5 digit number: 123456
error: 6 characters.
Enter a 5 digit number: 12345
you entered 5 digits, mynumber = 12345
User cancels input with ctrl+d on Linux (or ctrl+z on windows) generating a manual EOF:
$ ./bin/only5digits
Enter a 5 digit number: (user canceled input)
(note: you can add additional checks to see if 1024 or more characters were input -- that is left to you)
This is a slightly different approach to reading input, but from a general rule standpoint, when taking user input, if you ensure you consume an entire line of input, you avoid many of the pitfalls associated with using scanf for that purpose.
Look things over and let me know if you have further questions.
In your code you have an array of 5 bytes. If the user enters more than 4 digits, scanf will happily overflow the array and corrupt the memory. It will corrupt the memory in both cases, as an array and as a malloc. However, not every memory corruption causes a crash.
So, you need to limit the number of bytes the scanf can read. The way to do it is to use %4s in the format string.
However, in this case you will not be able to detect when the user enters more than 4 digits. You would need at least 1 more byte: str[6] and %5s;
I suggest, instead of using scanf, use getchar. It would allow you to read character by character and count them on the way.

Storing int variable from user into array in C

I am fairly new to c programming, and also this forum but I thought I would give it a try. What I want to do is have a user enter a 4 digit number. From there i want to take the number and store it in an array, so as i could call arr[2] when I need it and so on and so on. Thanks in advance for any help!
I would really like to know what is going on here. Thanks again
Many possibilities exist to implementing the behavior you want. Here's one way of doing it:
int arr[4];
int i;
char var1[4];
printf("Please enter a 4 digit number: ");
scanf("%s", var1);
for (i = 0; i < 4; i++ ) {
arr [i] = var1[i] - '0'; // convert char to int
printf("%d", arr[i]);
}
printf("\n");
Your code does not do what you think it does. scanf reads a line from the console. %d matches a number (i.e. 123), not a digit (i.e. 1, 2, 3). You call printf in a loop, not scanf (i.e. you capture one number and you print it multiple times).
Actually, I see it is more than that - you are assuming integer in C++ means digit. Your array of 4 integers does not hold a 4 digit number - it holds four separate integers, each of which can be (usually) from -2147483648 to +2147483648.
The thing is, it's not easy to break a number into digits - because "digits" are base 10 (decimal) while a computer thinks in base 2 (binary). What we can do instead is read and write the number and digits as text, instead. Read the integer as a string, and write each digit as a character:
#include <stdio.h>
int main()
{
char input[4];
//get input as text, instead of as a number
printf ("Please enter a 4 digit number: ");
scanf ("%s", input);
for ( int i = 0; i < 4; i++ )
{
//print as char instead of as number
printf ("%c\n", input[i]);
}
}
This code is not perfect. If the user entered "blah" it will print "b" "l" "a" "h" instead of complain about non-numeric input. If the user enters more than 4 characters, our array of characters to hold the number will overflow causing serious security risks and a crash.
var1 is an integer and you are storing it in each element of the integer array arr, hence the output
If you want to store each number as a character, use fgets, or if you want to store it a number, do
i=0;
while(var1){
arr[len-i-1] = var1%10; //len is 4 in your case
var1 /= 10;
i--;
}
You have asked scanf to read an integer value. You might want to read a string instead.
In a pinch, you can use fgets:
char number[5];
if( fgets(number, sizeof(number), stdin) != NULL )
{
for( i = 0; i < 4; i++ ) {
printf( "%c\n", number[i] );
}
}

Inputting float into a program that only deals with ints

I have a program, but when I input float numbers whenever the program asks for inputs, the program abruptly skips a step and moves onto the end output. The program is below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b,c;
int i;
printf("Please enter a number: ");
scanf("%d", &a);
printf("Please enter a number: ");
scanf("%d", &b);
c = 0;
for(i=0; i < b; i++)
{
c = c + a;
}
printf("%d x %d = %d\n", a, b, c);
return 0;
}
When I input an int for a, and a float for b, the program will output the product as expected if the numbers after the decimal point for b is truncated. However when I input a float for a, the program doesn't take the value for the second number b and instead skips that step and outputs the integer version of a x -858993460 = 0.
For example:
a = int, b = float
Please enter a number: 3
Please enter a number: 5.6
3 x 5 = 15
a = float, b = skipped
Please enter a number 3.9
Please enter a number: 3 x -858993460 = 0
All the flaws in the code are deliberate, but I just wanted to know why it behaves the way I explained above. I know it's because of something to do with trying to input a float into a signed integer but I'm not sure what exactly is causing it to skip the second scanf("%d", &b). Can anyone explain why this happens?
Thanks.
It looks like scanf() is reading your "3" in the second case, and ignoring the "9".
Then when the second scanf() is called, there is already text in the input buffer (the ".9").
I can't tell exactly what it's doing with the ".9". It may have found the dot and just aborted there with b uninitialized. It should be a simple matter to determine what is happening by stepping through with the debugger.
But, basically, not all the input is being processed by the first call to scanf() and so that's what the second call is trying to read. And that's why it's not waiting for you to input any data for the second call.
Console input is line buffered; when you enter 3.9 into a %d format specifier, only the 3 is consumed, the remaining data remains buffered, so the second scanf() call attempts to convert it according to its specifier, it finds a '.' and aborts the conversion leaving b undefined.
scanf() will continue to "fall-through" until the '\n' at the end of the input data is consumed. You can do this thus:
printf("Please enter a number: ");
scanf("%d", &a);
while( getchar() != '\n' ) { /* do nothing */ }
printf("Please enter a number: ");
scanf("%d", &b);
while( getchar() != '\n' ) { /* do nothing */ }
Note that if the format specifier is %c, a modification of the "flush" code is required, because the converted character may already be '\n' :
scanf("%c", &c);
while( c != '\n' && getchar() != '\n' ) { /* do nothing */ }
If the next character that is to be read cannot be converted under the current format as specified by the Format Specifier, scanf stops scanning and storing the current field and it moves to the next input field (if any).
And that particular character is treated as unread and used as the first character of next input field or any subsequent read operation.
In the example given above, it is scanning 3 and then cannot resolve . to the format specifier "%d". Hence it stores 3 in variable a leaving .9 as unread. The control when passes to the next scanf statement, it scans ., but again as it cannot resolve . to format specifier "%d", it skips the input scanning for that field.
Now as variable b was not assigned, it contains some garbage value. And any arithmetic operation with garbage values result into garbage values.

Resources