Converting 3 digit decimal number to binary (C) - c

I need to convert 3 digit decimal number to binary using C.
My code:
#include <stdio.h>
#define TWO 2
int main() {
int dec_num; // demical number
int i = 0; // loop cunter
printf("type in 3 digits number to convert to binary\n");
scanf("%d", &dec_num);
while (++i <= 12) {
if (dec_num % TWO != 0) {
printf("1") ;
} else if (dec_num % TWO == 0) {
printf("0");
} else if (dec_num <= 0) {
break;
}
dec_num / TWO;
}
return 0;
}
The problem is that the number doesn't get divided by 2 at the end of the while loop how can I fix it?

You did not store the value of dec_num after the division.
dec_num / TWO; //<--------------------
Your while loop condition was also wrong.
while(++i <= 12) //<-------------------
You should perform the division operation until the number is greater than 0
According to the rules of binary to decimal, you should print 1s and 0s in reverse order. But in your code, you have changed the order. In order to fix that We could store the result in an array and then we could print the result in reverse order.
Here is your modified code,
#include <stdio.h>
#define TWO 2
int main()
{
int dec_num; // demical number
int i=0; // loop cunter
printf("type in 3 digits number to convert to binary\n");
int flag = scanf("%d",&dec_num); //<-----check the user input
if(flag!=1)
{
printf("Input is not recognized as an integer");
return 0;
}
int size=0;
int array[120] = {0}; //<-------to store the result
while(dec_num > 0){ //<------- while the number is greater than 0
if(dec_num % TWO !=0){
array[i] = 1;
}
else if(dec_num % TWO ==0){
array[i] = 0;
}
size = ++i; //<------- store the size of result
dec_num = dec_num / TWO; //<------- divide and modify the original number
}
for(i=size-1;i>=0;i--) //<------- print in reverse order
printf("%d",array[i]);
return 0;
}

My solution will assume that the input is a positive number and that maximal decimal 3 digit number can be presented by 10 bits (decimal 999 is binary 1111100111). I will also use the fact that the bit-wise operators are defined by the C standard and should take place. These operations on most of the architectures are very efficient and much faster than / or %.
#include <stdio.h>
#define MAX_BIN_DIGITS 10
#define ERR_INVALID_INPUT_VALUE 1
int main(void)
{
int dec_num; // demical input number
int i = MAX_BIN_DIGITS;
int bin_bit;
// storing the result at zero terminated string
char bin_res[MAX_BIN_DIGITS+1] = {0};
printf("Type in 3 digits number to convert to binary:\n");
if (1 != scanf("%d",&dec_num))
{
printf("Error: Invalid input value!");
return ERR_INVALID_INPUT_VALUE;
}
// Checking for 'i' here just to be safe in case of larger input than expected - 4 digits or more
while(i-- && dec_num)
{
bin_bit = dec_num & 1; // get the LSB
dec_num >>= 1; // remove the LSB from 'dec_num'
bin_res[i] = '0' + bin_bit; // store the LSB at the end as a char
}
// Print the array starting from the most significant bit which is '1'
// NOTE: Need to take care of special case when the input is '0', then 'i'
// will be equal to 'MAX_BIN_DIGITS-1'.
printf("%s\n", (i != MAX_BIN_DIGITS-1) ? &(bin_res[i+1]) ? "0");
return 0;
}

There are multiple problems in your code:
You do not test the return value of scanf(): you get undefined behavior if the user fails to input characters that can be converted to an integer.
You do not test if the number indeed has at most 3 digits.
You iterate up to 12 times, but 10 should suffice since 210 = 1024 which is greater than any 3 digit number
As a matter of fact, it should not even be necessary to limit the number of iterations, since you stop when the number drops to 0.
The tests are inconsistent: num % TWO is either 0 or 1, the second test is redundant and the third test is never executed, so the loop fails to detect proper termination condition.
dec_num / TWO; does not update dev_num, so your loop just keeps printing the least significant bit (and the test while (++i <= 12) is indeed necessary for the loop to stop).
if corrected, this loop would print the bits from the least significant to the most significant, which is probably not the expected behavior.
#define TWO 2 is not strictly speaking a mistake, but does not improve code readability or safety. Local coding rules might bar you from using non trivial numeric constants in the code: such a rule seems counter productive in this particular case.
It is considered good style to always end output lines with a newline.
beware of typos: demical number is cute and loop cunter is intriguing.
Here is a corrected version of your code, using your algorithm, to illustrate the unexpected output (last significant bit to most significant bit):
#include <stdio.h>
int main() {
int dec_num; // decimal number
printf("type in a 3 digit number to convert to binary\n");
if (scanf("%d", &dec_num) != 1) {
printf("invalid input\n");
return 1;
}
if (dec_num < 0 || dec_num > 999) {
printf("invalid value: must have at most 3 digits\n");
return 1;
}
for (;;) {
if (dec_num % 2 != 0) {
printf("1");
} else {
printf("0");
}
dec_num = dec_num / 2;
if (dec_num == 0)
break;
}
printf("\n");
return 0;
}
Here is a recursive version that outputs the bits in the proper order:
#include <stdio.h>
void output_binary(int num) {
if (num > 1)
output_binary(num / 2);
printf("%d", num % 2);
}
int main() {
int dec_num; // decimal number
printf("type in a 3 digit number to convert to binary\n");
if (scanf("%d", &dec_num) != 1) {
printf("invalid input\n");
return 1;
}
if (dec_num < 0 || dec_num > 999) {
printf("invalid value: must have at most 3 digits\n");
return 1;
}
output_binary(dec_num);
printf("\n");
return 0;
}

While you already have a valid answer correcting the failure to update dec_num following division and valid recursive methods provided by others, it is unclear whether you intend to allow entry of negative 3-digit values as well as positive values. An implementation that determines the size of the type and then shifts by one over each of the bits can provide a simple solution that will handle both positive and negative values.
For example the conversion part of the code shifting by 1 for each bit (indexed 31 -> 0) could be as simple as:
int main (void) {
int decnum = 0; /* user input number */
unsigned remain = 0; /* remainder after shift */
size_t nbits = sizeof decnum * CHAR_BIT; /* number of bits for type */
/* read decnum here */
printf ("decimal: %d\nbinary : ", decnum); /* output value */
while (nbits--) { /* write bits 31->0 while 1 bits remain */
if ((remain = decnum >> nbits)) /* shift saving shifted value */
putchar ((remain & 1) ? '1' : '0'); /* bit 0/1 output '0'/'1' */
}
putchar ('\n'); /* tidy up with newline */
}
(note: a simple ternary operator is used to determine whether to output '1' or '0')
The bigger part of your problem is the your failure to check the return of scanf. This is an open invitation for Undefined Behavior. Regardless of what function you use for user-input, you must validate that input succeeded before proceeding further. Otherwise you will invoke undefined behavior when you attempt to access an indeterminate value.
When using scanf in order to require valid input, you must handle three cases each time (1) did the user cancel input by pressing Ctrl+d generating a manual EOF? (Ctrl+z on windows), (2) did a matching or input failure occur? and (3) the good input case. Then, as is your case, you must further validate the input was in the proper range of values (a 3 digit number in your case). Additionally, to require valid input, you must handle any character that remains unread in the input buffer (as is the case for a matching failure, or if the user slipped and typed additional characters after the integer value.
Now it is completely fine to simply validate the input and return on an invalid input regardless of what caused the failure, but to require valid input it is up to you to handle all three cases, check that the input was within the valid range (and even then remove the trailing '\n' left by scanf preparing the input-buffer for whatever additional input may be taken later in your code.
Many times that will require more code than your actual calculation does, but it is critical. For instance in your case, if you wanted to require the user to enter valid input, you could replace the /* read decnum here */ with something similar to:
for (;;) { /* loop continually until valid input or canceled */
int rtn; /* variable to hold scanf return */
fputs ("enter 3 digit integer: ", stdout); /* prompt */
rtn = scanf ("%d", &decnum); /* read value, saving return */
if (rtn == EOF) { /* handle manual EOF cancelation */
fputs ("(user canceled input)\n", stderr);
return 1;
}
if (rtn == 0) { /* handle input failure */
empty_stdin(); /* always empty input buffer */
fputs (" error: invalid integer input.\n", stderr);
} /* validate 3 digit poisitive (or negative) number */
else if (decnum < -999 || (decnum > -100 && decnum < 100)
|| decnum > 999) {
empty_stdin();
fputs (" error: not a 3 digit number.\n", stderr);
}
else { /* handle good input case (break loop) */
empty_stdin();
break;
}
}
note: the helper function empty_stdin(). That can be implemented with getchar() to read and discard any characters causing problems, e.g.
void empty_stdin (void) /* helper function to empty stdin after bad input */
{ /* (as well as the trailing '\n' after good input) */
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
Putting it altogether, you could do something like the following:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
void empty_stdin (void) /* helper function to empty stdin after bad input */
{ /* (as well as the trailing '\n' after good input) */
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int decnum = 0; /* user input number */
unsigned remain = 0; /* remainder after shift */
size_t nbits = sizeof decnum * CHAR_BIT; /* number of bits for type */
for (;;) { /* loop continually until valid input or canceled */
int rtn; /* variable to hold scanf return */
fputs ("enter 3 digit integer: ", stdout); /* prompt */
rtn = scanf ("%d", &decnum); /* read value, saving return */
if (rtn == EOF) { /* handle manual EOF cancelation */
fputs ("(user canceled input)\n", stderr);
return 1;
}
if (rtn == 0) { /* handle input failure */
empty_stdin(); /* always empty input buffer */
fputs (" error: invalid integer input.\n", stderr);
} /* validate 3 digit poisitive (or negative) number */
else if (decnum < -999 || (decnum > -100 && decnum < 100)
|| decnum > 999) {
empty_stdin();
fputs (" error: not a 3 digit number.\n", stderr);
}
else { /* handle good input case (break loop) */
empty_stdin();
break;
}
}
printf ("decimal: %d\nbinary : ", decnum); /* output value */
while (nbits--) { /* write bits 31->0 while 1 bits remain */
if ((remain = decnum >> nbits)) /* shift saving shifted value */
putchar ((remain & 1) ? '1' : '0'); /* bit 0/1 output '0'/'1' */
}
putchar ('\n'); /* tidy up with newline */
}
Example Use/Output
$ ./bin/prnbin3digit
enter 3 digit integer: why?
error: invalid integer input.
enter 3 digit integer: -75
error: not a 3 digit number.
enter 3 digit integer: 1024
error: not a 3 digit number.
enter 3 digit integer: 127 and more junk
decimal: 127
binary : 1111111
Or the case with a negative value:
$ ./bin/prnbin3digit
enter 3 digit integer: -127
decimal: -127
binary : 11111111111111111111111110000001
Or the case where the user cancels input:
$ ./bin/prnbin3digit
enter 3 digit integer: (user canceled input)
While this ended up being longer than what a simple right-shift implementation of the conversion would have been, it is worth building good user-input habits now to avoid untold problems later. Look things over and let me know if you have further questions.

Related

find the number of prime numbers, from the digits of a number

I am stuck in this problem, 2 integers A and B must be entered, and A must be separated into digits with respect to B, example: A:1234 B:2 You must separate 12, 23, 34, and then verify how many prime numbers are between these digits
This is what I was able to do so far, I would appreciate it if you could guide me to know which way to go
#include <stdio.h>
int main() {
int A, B, i, contador;
//Introducimos el Numero A y verificamos que sea mayor a 0
for (i = 0; i != -1; i++) {
printf("\nIngrese el numero A :");
scanf("%d", &A);
if (A > 0) {
break;
}
}
//Introducimos el Numero B y verificamos que sea mayor a 0
for (i = 0; i != -1; i++) {
printf("\nIngrese el numero B :");
scanf("%d", &B);
if (B > 0) {
break;
}
}
printf("A\t\tB\t\tCifras\t\tCantidad Primos\n");
printf("%d\t\t%d", A, B);
return 0;
}
First we can greatly simplify validating input with a while loop for each variable that will loop until it scans in a number successfully and it's greater than zero.
Second, we can convert that input number to a string with sprintf which makes looping over individual chunks easier.
Having isolated substrings representing chunks of digits, strtol can convert them back to ints. Below I have simply printed them, but you could readily store them in an array for further manipulation.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
int A = 0, B = 0;
while (scanf("%d", &A) != 1 || A <= 0);
while (scanf("%d", &B) != 1 || B <= 0);
char s[1024];
sprintf(s, "%d", A);
for (int i = 0; i < strlen(s) - B + 1; i++) {
char ss[B+1];
for (int j = 0; j < B; j++) {
ss[j] = s[i + j];
}
ss[B] = '\0';
int n = strtol(ss, NULL, 10);
printf("%d\n", n);
}
return 0;
}
There's no need for conversion to/from a string of digits.
You've got the "user input", so far.
The following skips that step, using 2 compile-time int's instead.
int main() {
int v1 = 1357924680, v2 = 3; // simulate two reasonable values from the user.
printf( "Using %d and %d as input\n", v1, v2 );
// calculate the power of 10 that has 'v2' zeros.
int divisor = 1;
while( v2-- ) divisor *= 10;
// from right-to-left, push 2-3-4-... digit values onto a stack
int stack[32] = { 0 }, spCnt = -1;
while( v1 > divisor/10 )
stack[ ++spCnt ] = v1 % divisor, v1 /= 10;
// retrieve (in order) pairs of values from the stack.
for( ; spCnt > 0; spCnt-- ) {
printf( "%d and %d\n", stack[ spCnt ], stack[ spCnt - 1 ] );
/* call your function that prints all the primes between these values. */
}
return 0;
}
Using 1234567890 and 2 as input
12 and 23
23 and 34
34 and 45
45 and 56
56 and 67
67 and 78
78 and 89
89 and 90
Using 1357924680 and 3 as input
135 and 357
357 and 579
579 and 792
792 and 924
924 and 246
246 and 468
468 and 680
There are a number of ways you can approach parsing the input of digits into groups of digits to be checked as prime. A very straight-forward approach is to read the digits into a C-string and then convert the groups of digits desired into integer values. That process can also be done a number of different ways. One instructive way is simply to manually handle grouping the number of desired digits to check and manually converting each group of digits to an integer value to check if prime.
Whenever you are reading input from the user, you are encourage to read a line of input at-a-time to avoid the pitfalls inherent in a formatted-read using scanf() (matching-failures and characters left unread in stdin just waiting to bite you on your next input --> which is the reason for the infinite-loop discussed below your other answer) Reading input with fgets() into a sufficiently sized buffer (character array) ensures are characters are read and nothing remains unread in stdin.
So long as you are not on an embedded system or microcontroller, C provides the constant BUFSIZ which you can use to size your character array, that is sufficient for most inputs you will encounter. In your case two arrays are needed, a separate buffer to hold the digits you will group and convert, and a second general buffer to take the other (B) input with. You can declare your buffers and read the digits with something similar to the following:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXDIGITS BUFSIZ
...
int main (void) {
char buf[MAXDIGITS], /* general input buffer */
digits[MAXDIGITS]; /* buffer to hold digits */
int ndigits = 0; /* digits to separate and test */
/* read/validate input A */
fputs ("enter number : ", stdout);
if (!fgets (digits, sizeof digits, stdin)) {
puts ("(user canceled input)");
return 0;
}
digits[strcspn (digits, "\n")] = 0; /* trim trailing '\n' */
...
(note: fgets() reads and includes the '\n' generated by the user pressing Enter. A simple way to remove it is to overwrite the '\n' character with 0 -- the nul-terminating character. strcspn() provides an efficient manner for doing so as shown above)
Since you are reading digits, you will want to check that the input is comprised of all digits. You can write a simple function to check if each character entered isdigit() with the function (or macro) provided in ctype.h, e.g.
/* simple function checks if s is composed of all digits,
* returns 1 if so, 0 otherwise.
*/
int all_digits (const char *s)
{
int i = 0;
if (!*s || *s == '\n') { /* check empty-string or empty-line */
return 0;
}
for (; s[i]; i++) { /* loop over each digit */
if (!isdigit((unsigned char)s[i])) {
break;
}
}
return !s[i]; /* end-of-string */
}
If the user input into digits is all-digits, you can proceed to take the second input of the number of digits to group together to check for prime. The approach is the same, read with fgets() into buf and then convert the number to int and validate the number represents a group-size that is possible given the number of digits in digits, e.g.
if (!all_digits (digits)) { /* validate input all digits */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* read / validate input B */
fputs ("combine ndigits : ", stdout);
if (!fgets (buf, sizeof buf, stdin)) {
puts ("(user canceled input)");
return 0;
}
/* convert string to int / validate */
if (sscanf (buf, "%d", &ndigits) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* validate the number of digits to combine is possible */
if (ndigits <= 0 || (size_t)ndigits > strlen (digits)) {
fputs ("error: requested combination of digits not possible.\n",
stderr);
return 1;
}
With both inputs taken and the number of digits ndigits to group validated, you can convert your groups to int and check for prime. A simple manual way to do so is to loop over digits beginning with the index ndigits - 1 and looping ndigits times for each group manually converting the digits to int. Only positive values of the groupings are considered, which reduces the task to:
/* loop starting at ndigits digit, combine every ndigits digits into int
* (only positive combinations are considered)
*/
for (int i = ndigits - 1; digits[i]; i++) {
int j = i, /* index for scanning over digits to separate */
n = ndigits, /* copy of number of digits to separate */
num = 0, /* separated number */
mult = 1; /* digit multiplier */
while (n--) { /* loop ndigits times */
num += mult * (digits[j--] - '0'); /* add mult * value to num */
mult *= 10; /* increment mult by 10 */
}
printf (" %*d\n", ndigits, num); /* (optional) output of num */
/** check if num is prime here **/
}
That's it. Checking for prime is left to you. The input, grouping and conversion of the group to int can be checked by printing each grouping that would be checked for prime.
Example Use/Output
Putting the code together (a complete source is provided at the end), compiling and running your would get:
$ ./bin/group-digits
enter number : 1234
combine ndigits : 1
1
2
3
4
Groupings of two:
$ ./bin/group-digits
enter number : 1234
combine ndigits : 2
12
23
34
Groupings of three:
$ ./bin/group-digits
enter number : 1234
combine ndigits : 3
123
234
Groupings of four:
$ ./bin/group-digits
enter number : 1234
combine ndigits : 4
1234
What about a grouping of five with four-digits?
$ ./bin/group-digits
enter number : 1234
combine ndigits : 5
error: requested combination of digits not possible.
What about a larger string of digits, that itself exceeds the size of int, but so long as the group-size is within the size of int, there is no reason that wouldn't work:
$ ./bin/group-digits
enter number : 12345678901234567890
combine ndigits : 4
1234
2345
3456
4567
5678
6789
7890
8901
9012
123
1234
2345
3456
4567
5678
6789
7890
(note: 0123 is properly converted to 123 instead of an octal value representing 83)
Complete Source for Example
The complete combined source code for the example for easy reference is:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXDIGITS BUFSIZ
/* simple function checks if s is composed of all digits,
* returns 1 if so, 0 otherwise.
*/
int all_digits (const char *s)
{
int i = 0;
if (!*s || *s == '\n') { /* check empty-string or empty-line */
return 0;
}
for (; s[i]; i++) { /* loop over each digit */
if (!isdigit((unsigned char)s[i])) {
break;
}
}
return !s[i]; /* end-of-string */
}
int main (void) {
char buf[MAXDIGITS], /* general input buffer */
digits[MAXDIGITS]; /* buffer to hold digits */
int ndigits = 0; /* digits to separate and test */
/* read/validate input A */
fputs ("enter number : ", stdout);
if (!fgets (digits, sizeof digits, stdin)) {
puts ("(user canceled input)");
return 0;
}
digits[strcspn (digits, "\n")] = 0; /* trim trailing '\n' */
if (!all_digits (digits)) { /* validate input all digits */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* read / validate input B */
fputs ("combine ndigits : ", stdout);
if (!fgets (buf, sizeof buf, stdin)) {
puts ("(user canceled input)");
return 0;
}
/* convert string to int / validate */
if (sscanf (buf, "%d", &ndigits) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* validate the number of digits to combine is possible */
if (ndigits <= 0 || (size_t)ndigits > strlen (digits)) {
fputs ("error: requested combination of digits not possible.\n",
stderr);
return 1;
}
/* loop starting at ndigits digit, combine every ndigits digits into int
* (only positive combinations are considered)
*/
for (int i = ndigits - 1; digits[i]; i++) {
int j = i, /* index for scanning over digits to separate */
n = ndigits, /* copy of number of digits to separate */
num = 0, /* separated number */
mult = 1; /* digit multiplier */
while (n--) { /* loop ndigits times */
num += mult * (digits[j--] - '0'); /* add mult * value to num */
mult *= 10; /* increment mult by 10 */
}
printf (" %*d\n", ndigits, num); /* (optional) output of num */
/** check if num is prime here **/
}
}
If The Groups Are Exclusive
If you intended your groupings to be exclusive, meaning if you had ten-digits, "0123456789" and wanted groups of five digits, that would provide two exclusive integers 1234 and 56789, then there are a few easy changes to make.
As a convenience, you can save the length of digits at the same time you trim the '\n' from the end, e.g.
...
int main (void) {
char buf[MAXDIGITS], /* general input buffer */
digits[MAXDIGITS]; /* buffer to hold digits */
int ndigits = 0; /* digits to separate and test */
size_t len = 0; /* length of digits */
...
digits[(len = strcspn (digits, "\n"))] = 0; /* trim '\n' save len */
...
You need to ensure len is divisible by ndigits, so just add your check to the existing checks for combinations
/* validate the number of digits to combine is possible */
if (ndigits <= 0 || (size_t)ndigits > len || len % ndigits ) {
fputs ("error: requested combination of digits not possible.\n",
stderr);
return 1;
}
Finally adjust your for loop increment:
/* loop starting at ndigits digit, combine every ndigits digits into int
* (only positive combinations are considered)
*/
for (int i = ndigits - 1; digits[i]; i += ndigits) {
...
Modified Example Use / Output
Now only exclusive ranges of digits are considered for the check against prime:
./bin/group-digits2
enter number : 12345678901234567890
combine ndigits : 4
1234
5678
9012
3456
7890
Or by groups of 5:
$ ./bin/group-digits2
enter number : 12345678901234567890
combine ndigits : 5
12345
67890
12345
67890
If len isn't divisible by ndigits:
$ ./bin/group-digits2
enter number : 12345678901234567890
combine ndigits : 6
error: requested combination of digits not possible.
Let me know if you have questions.

Input number resets to 0 after scanf

I have a weird issue. I ask a user to enter a number between 1 and 15. Then I would ask the user would the like to get the factorial value of the number using either recursive or a for loop.
When they answer that question the inputted value goes to 0. If I remove the question for testing purpose the value stays the value the user inputted.
#include <stdio.h>
int recursive(int);
int nonRecursive(int);
int main()
{
/* Variables */
int numberSelected, returnedValue;
char answer;
do
{
/* Request a number between 1 and 15 */
printf("Please enter a number between 1 and 15: ");
scanf("%d", &numberSelected);
printf("%d\n", numberSelected); /* This prints out the user's number */
}while(numberSelected < 1 || numberSelected > 15); /* Loops if the value is not between 1 and 15 */
/* Ask user if they want to return a recursive value or a value calculated manually */
printf("Would you like a recusive value of the number you entered? Y or N: ");
scanf("%s", &answer);
if(answer == 'y' || answer == 'Y')
{
printf("%d\n", numberSelected); /* Here it resets to 0 */
returnedValue = recursive(numberSelected); /* Returns the recursive value */
printf("The recursive value of %d is %d\n", numberSelected, returnedValue);
}
else
{
printf("%d\n", numberSelected); /* Here it resets to 0 also*/
returnedValue = nonRecursive(numberSelected); /* Returns the value from for loop */
printf("The non recursive value of %d is %d\n", numberSelected, returnedValue);
}
return 0;
}
/* Get value using recursive */
int recursive(int n)
{
if (n == 0)
return 1; // Base case
else
return n * recursive(n - 1);
}
/* Get value using for loop */
int nonRecursive(int n)
{
int i;
int fact = 1;
for(i = 1; i <= n; i++)
{
fact *= i;
}
return fact;
}
Thank you for the help
scanf("%s", &answer);
is wrong. %s is for reading strings (null-terminated sequence of characters), but answer has only room for 1 character, so out-of-bound write will occur when strings with one or more characters is read. It may break data around that.
The line should be
scanf(" %c", &answer);
Use %c, which reads single character.
Add a space before %c to have scanf() ignore whitespace characters.

Split numbers into place values in C

I want to print a breakdown of an integer, only outputting non-zero numbers. For example: ./printint 23401 will print: 20000 + 3000 + 400 + 1 Note: the tens value of 0 is omitted.
That is my code so far:
#include <stdio.h>
int main(int argc, const char * argv[]) {
int n = 23401;
int g,s,b,q,w;
g=n%10;
s=(n/10)%10*10;
b=(n/100)%10*100;
q= (n/1000)%10*1000;
w= n/10000*10000;
printf("%d" ,"+","%d","+","%d","+","%d","+","%d\n",w,q,b,s,g);
return 0;
}
I am new at coding and new at C. I am also trying to get input but it is hard to think it thoroughly, so I am just using the example in the question. Also, I have a problem with the connect style in the printf().
As with any problem, you simply need to break the complex problem down into smaller problems that you can solve, code a solution for each of the parts and then consolidate all of the individual coded solutions into your final code. In this case that can be thought of as:
prompt user for input,
read and VALIDATE the user input,
handle the corner-case of the user entering 0 which has no additive component,
determine if the number entered was negative, make positive and save flag indicating original was negative,
determine the number of digits in the number entered by the user,
generate a power of 10 for that many digits,
loop over the number dividing by the power of 10, output the resulting power of 10 formed by digit * power of 10 (if non-zero), and reduce the number by that amount and divide your power of 10 by 10 and repeat until your power of 10 is zero.
Now just go write the code for the pieces. Let's decide on a few variable names that we will need before coding up each step (to server as a guide-post as we work through the steps). On a 64-bit computer with a 8-byte long, choosing long as the type to hold your number entered by the user makes sense for handling negative values. We will add a few more to help with the rest of the code. Five variables should do it, e.g.
#include <stdio.h>
int main (void) {
int ndigits, sign = 0; /* number of digits, sign (1 if negative) */
long num /* the number to get from user */
unsigned long limit = 1, n; /* divisor limit, working var for num */
Let's start with Step 1. - prompting for input. There is no conversion required, and if we want the input to be at the end of the line instead of below it, fputs is a good choice for the prompt (use puts if you want to output a newline forcing the user input to the next line), e.g.
fputs ("enter number in range of long int: ", stdout);
Step 2. - read and VALIDATE the user-input (every user input) and handle the error if invalid input is provided (we simply return 1; from main() exiting if an invalid integer is entered):
if (scanf ("%ld", &num) != 1) { /* validate input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
Step 3. - handle the case if the user enters 0 where there will be nothing to add to obtain your final number:
if (!num) { /* handle 0 corner-case */
printf ("%ld : ()\n", num);
return 0;
}
(we will also output the number entered by the user at this point and output the remainder in the loop and following the loop. call this Step 3a.)
printf ("%ld : ", num); /* output orignal number */
Step 4. determine if the number is negative, and if so, make it positive and save a flag indicating the original input was negative. (you could just output the '-' in this case and do away with the flag, but you won't always have that opportunity -- so get used to saving the state with a simple flag if required)
if (num < 0) { /* if negative set sign=1, make positive */
sign = 1;
num = -num;
}
n = num; /* set working variable for num */
(note: we also set our working variable n = num; at this point. If you don't want to preserve the original, you can dispense with using a working variable and just modify the original as needed -- as we could here since we have already output the original)
Step 5. - determine the number of digits in the number entered by the user:
ndigits = snprintf (NULL, 0, "%ld", num); /* get number of digits in num */
(yes: snprintf with a destination of NULL and length of 0 provides a very convenient way to calculate the number of characters that would be required to hold the number converted to a string)
Step 6. - generate a power of 10 for the number of digits entered:
for (int i = 1; i < ndigits; i++) /* set power of 10 limit */
limit *= 10;
(before entering our loop we check if the original number was negative an output the '-' at this point -- a step 6a.):
if (sign) /* if negative, output '-' */
putchar ('-');
Step 7. loop over the number dividing by the limit power of 10 and outputting the resulting component power of 10 (if non-zero) that you would add to arrive at the final number. We then reduce our working variable by that amount and divide the power of 10 (by 10) and repeat until the power of 10 is zero, you can do:
while (limit) { /* loop over each power of 10 */
int digit = n / limit; /* is there a digit at that power of 10? */
if (digit) { /* if so, output digit * power of 10 */
printf (n != (unsigned long)num ? " + %lu" : "(%lu", digit * limit);
}
n -= digit * limit; /* subtract digit * power of 10 */
limit /= 10; /* reduce limit by power of 10 */
}
All that remains is tidying up the output any way you like. We'll add a closing parenthesis just to make it look nice. And this is also were you would figure out where you wanted to put the remainder of your output during the program (what led to all the 3a. and 6a. steps, etc..)
puts (")"); /* output closing paren */
}
If you collect all the pieces and put them together you would have:
#include <stdio.h>
int main (void) {
int ndigits, sign = 0; /* number of digits, sign (1 if negative) */
long num /* the number to get from user */
unsigned long limit = 1, n; /* divisor limit, working var for num */
fputs ("enter number in range of long int: ", stdout);
if (scanf ("%ld", &num) != 1) { /* validate input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
if (!num) { /* handle 0 corner-case */
printf ("%ld : ()\n", num);
return 0;
}
printf ("%ld : ", num); /* output orignal number */
if (num < 0) { /* if negative set sign=1, make positive */
sign = 1;
num = -num;
}
n = num; /* set working variable for num */
ndigits = snprintf (NULL, 0, "%ld", num); /* get number of digits in num */
for (int i = 1; i < ndigits; i++) /* set power of 10 limit */
limit *= 10;
if (sign) /* if negative, output '-' */
putchar ('-');
while (limit) { /* loop over each power of 10 */
int digit = n / limit; /* is there a digit at that power of 10? */
if (digit) { /* if so, output digit * power of 10 */
printf (n != (unsigned long)num ? " + %lu" : "(%lu", digit * limit);
}
n -= digit * limit; /* subtract digit * power of 10 */
limit /= 10; /* reduce limit by power of 10 */
}
puts (")"); /* output closing paren */
}
Example Use/Output
Now run it and make sure it does what you intend, and if not -- go fix it.
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 23401
23401 : (20000 + 3000 + 400 + 1)
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 20431
20431 : (20000 + 400 + 30 + 1)
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 1
1 : (1)
Handle zero:
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 0
0 : ()
Handle negative values:
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: -1
-1 : -(1)
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: -29031
-29031 : -(20000 + 9000 + 30 + 1)
Note. instead of prompting the user for input with scanf, you can simply set a default value for num in your code and then provide any number you want to test as the first argument to your program. That avoids all the prompting and input during the testing phase. If you want to give it a try, just replace your scanf entry with a check to see if an argument was provided on the command line, and if so, convert and assign to num using sscanf instead, e.g.
#include <stdio.h>
int main (int argc, char **argv) {
int ndigits, sign = 0; /* number of digits, sign (1 if negative) */
long num = 23401; /* the number */
unsigned long limit = 1, n; /* divisor limit, working var for num */
/* check if new mumber provided on command line, convert to long */
if (argc > 1 && sscanf (argv[1], "%ld", &num) != 1) {
fputs ("error: invalid non-integer argument.\n", stderr);
return 1;
}
(the only change is the default value for num and then the check of argc and conversion and VALIDATION with sscanf.
Look things over and let me know if you have further questions.

I want to make sure my program is correct this is c programming

i just wanted to make sure my formula was correct and wanted to see if there is a way to make the height go all the way to zero and the time count with it here is my code so far i have ran it with some numbers like height is 10 and velocity is 0 and it will start the time count at 0.0 and increment in .25 and the height will start at 10 but it will not count down to zero for the height and will stop at .75 for the time im sorry if its confusing what im trying to explain bc im confused my self
// Programmer: Your Name
// Date: Date
// Program Name: The name of the program
// Chapter: Chapter # - Chapter name
// Description: 2 complete English sentences describing what the program does,
// algorithm used, etc.
#define _CRT_SECURE_NO_WARNINGS // Disable warnings (and errors) when using non-secure versions of printf, scanf, strcpy, etc.
#include <stdio.h> // Needed for working with printf and scanf
#include <math.h>
int main(void)
{
// Constant and Variable Declarations
double startingHeight = 0.0;
double heightBall = 0.0;
double volicetyBall = 0.0;
double ballTime = 0.0;
double downTime = 0.25;
double maxHeight = 0.0;
double timeLast = 0.0;
// *** Your program goes here ***
do {
printf("\n Enter initial height of the ball (in ft.): ");
scanf("%lf", &startingHeight);
if (startingHeight < 0) {
printf("\t The initial height must be greater than or equal to 0");
}
} while (startingHeight < 0);
do {
printf("\n Enter initial velocity of the ball (in ft. per sec.): ");
scanf("%lf", &volicetyBall);
if (volicetyBall < 0) {
printf("\t The initial velocity must be greater than or equal to 0");
}
} while (volicetyBall < 0);
printf("\n");
printf("Time\tHeight\n");
if (startingHeight < 0 && volicetyBall > 0) {
printf("%0.2f\t%0.1f\n", ballTime, startingHeight);
}
else {
do {
heightBall = startingHeight + volicetyBall * ballTime - 16 * pow(ballTime, 2);
if (maxHeight < heightBall) {
maxHeight = heightBall;
}
if (heightBall >= 0) {
printf("%0.2f\t%0.1f\n", ballTime, heightBall);
timeLast = ballTime;
}
ballTime = ballTime + downTime;
} while (heightBall >= 0);
}
printf("\n The maximum height the ball will reach is %0.1f feet\n", maxHeight);
printf("\n The time for the ball to reach the ground is %0.2f seconds\n", timeLast);
printf("\n");
return 0;
} // end main()
Yes, it's C, but C that invites Undefined Behavior for failing to validate the user input. What happens in your code if the user slips and hits 'r' instead of '5' when entering the height of the ball?
To prevent and recover from an invalid input you need to check the return of your input function and empty stdin of any offending characters before your next attempted read, e.g.
/* validate every input */
if (scanf ("%lf", &startingHeight) != 1) {
int c;
fputs ("error: invalid input.\n", stderr);
do /* read offending chars until '\n' or EOF */
c = getchar();
while (c != '\n' && c != EOF);
continue;
}
All though with a do .... while (...) you simply jump to the end of the loop and your startingHeight < 0 test false and you skip to the velocity question, better to:
for (;;) { /* loop continually until valid input */
printf ("\n Enter initial height of the ball (in ft.): ");
/* validate every input */
if (scanf ("%lf", &startingHeight) != 1) {
int c;
fputs ("error: invalid input.\n", stderr);
do /* read offending chars until '\n' or EOF */
c = getchar();
while (c != '\n' && c != EOF);
continue;
}
if (startingHeight < 0) {
printf ("\t The initial height must be greater than or equal to 0");
/* you should empty stdin here as well -- hint: create a function */
}
else
break;
}
That way you re-ask the height question until you have a valid startingHeight >= 0.
Other nit, don't use printf to output a single-character, that is what putchar or fputc is for, e.g.
// printf ("\n"); /* replace this with... */
putchar ('\n');
Also, no need for two-printf calls (you are not performing any conversions) where a single puts will do, e.g.
// printf("\n");
// printf("Time\tHeight\n");
puts ("\nTime\tHeight");
Otherwise, aside from the normal beginning failure to validates, you are doing fairly well.

How to exit stdin when EOF is reached in C programming

I'm having troubles with my program. The aim of it is to read an input of numbers from the user, and when they stop inputting numbers (ctrl-d) it collects the inputted numbers and prints out 'Odd numbers were: blah blah'
and 'Even numbers were: blah blah'.
I'm having trouble with how to exit the program at EOF and when it feels like I have overcome that problem, another problem occurs which is my program doesn't print the numbers from the array. It only prints 'Odd numbers were:' and 'Even numbers were:'.
Any help is appreciated.
Thanks
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void) {
int n, i, array[1000];
i=0;
while (i = getchar() !=EOF) {
scanf("%d", &array[i]);
i++;
}
printf("Odd numbers were:");
i=0 ;
while(i = getchar() != EOF) {
if(array[i]%2!=0) {
printf(" %d", array[i]);
i++;
}
}
printf("\nEven numbers were:");
i=0 ;
while(i = getchar() !=EOF) {
if (array[i]%2==0) {
printf(" %d", array[i]);
i++;
}
}
printf("\n");
return 0;
}
Performing Single-Digit Conversion to int
You may be making things a bit harder on yourself than it needs to be. While you can use while (scanf ("%d", &array[i]) == 1) to read whitespace separated integers and avoid having to perform a manual conversion, if your intent is to read single-digits, then using getchar() is fine. (for that matter, you can read any multi-digit integer with getchar(), it is simply up to you to provide a conversion from the ASCII characters to final numeric value)
The manual conversion for single-digit characters is straight forward? When you read digits as characters, you are not reading the integer value represented by the digit, you are reading the ASCII value for the character that represents each digit. See ASCII Table and Description. In order to convert a single ASCII character digit to it's integer value, you must subtract the ASCII value of '0'. (note: the single-quotes are significant)
For example if you read a digit with int c = getchar();, then you need to subtract '0' to obtain the single-digit integer value, e.g. int n = c - '0';
When filling an array, you must ALWAYS protect against writing beyond the bounds of your array. If you declare int array[1000] = {0}; (which has available zero-based array indexes of 0-999), then you must validate that you never write beyond index 999 or Undefined Behavior results. To protect your array bounds, simply keep track of the number of indexes filled and test it is always below the number of array elements available, e.g.
while (n < MAX && (c = getchar()) != EOF) /* always protect array bounds */
if ('0' <= c && c <= '9') /* only handle digits */
array[n++] = c - '0'; /* convert ASCII to int */
Next, while you are free to test n % 2 (using the modulo operator), there is no need (little endian). Since any odd number will have its ones-bit set to 1, all you need is a simple bitwise comparison, e.g (7 in binary is 0111).
if (array[i] & 1) /* if ones-bit is 1, odd */
printf (" %d", array[i]);
Of course, for even numbers, the ones-bit will be 0 (e.g. 8 in binary is 1000), so the corresponding test can be:
if ((array[i] & 1) == 0) /* if ones-bit is 0, even */
printf (" %d", array[i]);
Putting all of the pieces together, you can store all single digits read in array and then segregate the even and odd numbers for printing in a very simple manner (note: neither stdlib.h or math.h are required),
#include <stdio.h>
#define MAX 1000 /* define a constant rather than use 'magic' numbers in code */
int main (void)
{
int array[MAX] = {0},
c, i, n = 0;
while (n < MAX && (c = getchar()) != EOF) /* always protect array bounds */
if ('0' <= c && c <= '9') /* only handle digits */
array[n++] = c - '0'; /* convert ASCII to int */
printf ("\narray : "); /* output array contents */
for (i = 0; i < n; i++)
printf (" %d", array[i]);
printf ("\narray - odd : ");
for (i = 0; i < n; i++)
if (array[i] & 1) /* if ones-bit is 1, odd */
printf (" %d", array[i]);
printf ("\narray - even : ");
for (i = 0; i < n; i++)
if ((array[i] & 1) == 0) /* if ones-bit is 0, even */
printf (" %d", array[i]);
putchar ('\n'); /* tidy up w/newline */
return 0;
}
Example Compilation with Warnings Enabled
$ gcc -Wall -Wextra -pedantic-std=gnu11 -Ofast -o bin/arrayevenodd arrayevenodd.c
Example Use/Output
$ echo "01234567890123456789" | ./bin/arrayevenodd
array : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
array - odd : 1 3 5 7 9 1 3 5 7 9
array - even : 0 2 4 6 8 0 2 4 6 8
Look things over and let me know if you have further questions.
Performing Manual Multi-Digit Conversion to int
If you are needing to convert multi-digit integers from characters, the easy way is to use a function that provides the conversion for you (e.g. the scanf family of functions or by using line oriented with fgets or getline and parsing and converting the strings of digits with strtok and then strtol, or parsing with sscanf, etc.)
However, performing a manual conversion of individual characters read by getchar() into a multi-digit integers is straight forward. You simply check for a valid character than can begin an integer (including the prefixes of +/-) and sum each digit providing a proper offset for the place of the digit by increasingly multiplying the sum by 10 before adding (or actually subtracting if building a the sum as a negative sum for coding efficiency purposes) each digit until you reach the next non-digit and then you add the final sum to your array and advance the array index.
While building the sum, it is up to you to check for integer Overflow before adding the final sum to your array. (you can handle the overflow condition however you like, the example below just throws the error and exits)
The manual conversion probably adds about 20 lines of code, e.g.
#include <stdio.h>
#include <stdint.h> /* exact length types */
#include <limits.h> /* INT_X constants */
#define MAX 1000 /* define constant rather than use 'magic' number in code */
int main (void)
{
int array[MAX] = {0},
c, i, start = 0, sign = 1, n = 0;
int64_t sum = 0;
while (n < MAX && (c = getchar()) != EOF) { /* always protect array bounds */
if (!start) { /* flag to start building int */
start = 1; /* flag - working on int */
if (c == '+') /* handle leading '+' sign */
continue;
else if (c == '-') /* handle leading '-' sign */
sign = -1;
else if ('0' <= c && c <= '9') /* handle digits */
sum = sum * 10 - (c - '0'); /* note: sum always computed */
else /* as negative value */
start = 0; /* reset - char not handled */
}
else if ('0' <= c && c <= '9') { /* handle digits */
sum = sum * 10 - (c - '0'); /* convert ASCII to int */
if (sum < INT_MIN || (sign != -1 && -sum > INT_MAX))
goto err; /* check for overflow, handle error */
}
else { /* non-digit ends conversion */
if (sum) /* if sum has value, add to array */
array[n++] = sign != -1 ? -sum : sum;
sign = 1; /* reset values for next conversion */
start = 0;
sum = 0;
}
}
if (sum) /* add last element to array on EOF */
array[n++] = sign != -1 ? -sum : sum;
printf ("\narray : "); /* output array contents */
for (i = 0; i < n; i++)
printf (" %d", array[i]);
printf ("\narray - odd : ");
for (i = 0; i < n; i++)
if (array[i] & 1) /* if ones-bit is 1, odd */
printf (" %d", array[i]);
printf ("\narray - even : ");
for (i = 0; i < n; i++)
if ((array[i] & 1) == 0) /* if ones-bit is 0, even */
printf (" %d", array[i]);
putchar ('\n'); /* tidy up w/newline */
return 0;
err:
fprintf (stderr, "error: overflow detected - array[%d]\n", n);
return 1;
}
Example Use/Output
$ echo "1,2,3,5,76,435" | ./bin/arrayevenodd2
array : 1 2 3 5 76 435
array - odd : 1 3 5 435
array - even : 2 76
Example with '+/-' Prefixes
$ echo "1,2,-3,+5,-76,435" | ./bin/arrayevenodd2
array : 1 2 -3 5 -76 435
array - odd : 1 -3 5 435
array - even : 2 -76
Look over the new example and let me know if you have any more questions.
Change the input loop to:
n = 0;
while ( 1 == scanf("%d", &array[n]) )
++n;
What you actually want to do is keep reading numbers until the read attempt fails; this loop condition expresses that logic. Forget about EOF. (It would also be a good idea to add logic to stop when n reaches 1000, to avoid a buffer overflow).
In the output loops, you do not want to do any input, so it is not a good idea to call getchar(). Instead, use a "normal" loop, for (i = 0; i < n; ++i).

Resources