I am new to C programming as you can already guess by my question. I am trying to enter a valid pin of 4 digits e.g. 9999. However, if the first digit is a zero i.e. 0111 the logic in my program doesn't increment counter. In a nutshell I am stuck on how I can account for a pin that begins with a zero. I could add a piece of error checking stating to the user that the pin must not begin with a zero but I don't want to resort to that if its possible.
Here is what I have so far:
/*
Program name: Count num of digits
*/
#include <stdio.h>
#define PIN_LENGTH 4
int main()
{
int pin = 0;
int counter = 0;
printf("Enter your PIN: ");
scanf("%d", &pin);
while(pin != 0)
{
pin = pin / 10;
counter++;
}
if(counter == PIN_LENGTH)
{
printf("Valid pin of %d digits\n", counter);
}
else
{
printf("Invalid pin of %d digits\n", counter);
}
return(0);
}
As you can see I divide the pin number by 10 and assign the new value into pin.
9999 divided by 10 = 999 (int truncates decimal part) and counter = 1
999 divided by 10 = 99 (int truncates decimal part) and counter = 2
99 divided by 10 = 9 (int truncates decimal part) and counter = 3
9 divided by 10 = 0 (int truncates decimal part) and counter = 4
Then I compare it to the symbolic name value which is 4 and if they are the same length I say its valid, and if not, its not valid.
But how do I account for a pin beginning with zero...
As #Olaf said, read the pin as a string. Define your pin as follows: char pin[PIN_LENGTH + 1], with the '+1' for the '\0' character. Then in scanf, you can say scanf("%4s", pin) to read the 4 characters. Finally, when you want to drag the values down, you can simply subtract a '0' from the character read at any position and treat them as integers from there on.
You cannot actually if you read it as an integer. One thing you can do is to read it as a string, count its length and find out if its right input or not. Afterwards you can use the ASCII table to convert the chars into integers in order to get each pin number.
You can change the type of pin to char * and do this
#include <stdio.h>
int size(char *, int);
int main() {
char pin[5];
printf("Enter your pin: ");
fgets(pin, sizeof(pin), stdin);
if(size(pin, sizeof(pin)/sizeof(char)) == 5) {
printf("Valid pin of 4 digits\n");
} else {
printf("Invalid pin of %d digits\n", size(pin) - 1);
}
return 0;
}
int size(char * a, int size) {
int i;
for (i = 0; a[i] != '\0' && i < size; i++);
return i;
}
fgets() is a better approach, but to do this task with scanf()...
Use "%n" to record the number of characters scanned.
printf("Enter your PIN: ");
int n1, n2;
if (scanf(" %n%d%n", &n1, &pin, &n2) == 1 && (n2 - n1) == 4)) {
// Success, 4 character `int` has been read.
}
Note: This will accept "+123".
Related
Below is the code for reversing a number (in the standard way)
#include <stdio.h>
int main()
{
int result=0;
int q,n,rem;
printf("enter number: ");
scanf("%d",&n);
q=n;
while(q!=0){
rem=q%10;
result=result*10+rem;
q=q/10;
}
printf("reversed number is: %d",result);
return 0;
}
But I was thinking whether there is a way to find the reversed program using the expanded form of numbers?
For example: If the input to the program is 123, then the required output would be 321 which can be written as 3 * 100+2 * 10+1 * 1
I'm not quite sure what you mean by a "different algorithm for reversing a number using expanded form of numbers."
Perhaps this is a solution to what you are asking:
Take each digit, one at a time, moving from right to left across the number and multiply that digit by the multiple of 10 associated with the current left-most digit. Accumulate these values in the variable reverse.
e.g. number = 123, digitCount = 3, power = 100, reverse = 0
for loop executed digitCount times (3 times)
get current right-most digit (3)
multiply current right-most digit (3) times current left-most multiple of 10 (100) = 300
reverse = 300
drop right-most digit from number (number changes from 123 to 12)
adjust multiple of 10 (power changes from 100 to 10)
continue with second pass through loop, etc.
Also your version of the program will not properly handle trailing zeroes. The printf statement at the end of this program will fill in any formerly trailing zeroes which now should be leading zeroes.
/* reverse.c
reverse the digits of a non-negative integer and display it on the terminal
uses an advanced formatting option of printf() to handle any trailing zeroes
e.g. 500 produces 005
*/
#include <stdio.h>
int main (void)
{
printf("\n"
"program to reverse a number\n"
"\n"
"enter a number: ");
int number;
scanf ("%d", &number);
printf("\n");
int digitCount = 1;
int power = 1;
while (number / power > 9) {
++digitCount;
power *= 10;
}
// power = multiple of 10 matching left-most digit in number
// e.g. if number = 123 then power = 100
int reverse = 0;
for (int i = 1; i <= digitCount; ++i) {
reverse += number % 10 * power; // number % 10 = right-most digit
number /= 10; // drop right-most digit
power /= 10; // adjust multiple of 10
}
// .* represents a variable that specifies the field width (the minimum number of
// digits to display for an integer and with unused digits filled by leading zeroes)
printf("reversed number: %.*d\n", digitCount, reverse);
return 0;
}
There is no particular logic like that,if you are interested to acheive that kind of output, you can just come up with something like this
#include <stdio.h>
#include <math.h>
int main()
{
int result=0;
int q,n,rem;
printf("enter number: ");
scanf("%d",&n);
q=n;
int number[100];
for (int i = 0; i < 100 ; i++){
number[i] = -1;
}
int i=0;
while(q!=0){
rem=q%10;
number[i++]= rem;
q=q/10;
}
int size=0;
for (i = 0; i < 100 ; i++){
if(number[i]== -1) break;
else{
size++;
}
}
int tenPowers= size;
for(int i=0; i<=size-1 && tenPowers>=0 ;i++){
printf("%dx%d", number[i],(int)pow(10,tenPowers-1));
tenPowers=tenPowers-1;
if(tenPowers>=0) printf("+");
}
return 0;
}
You can have this. It's not reversing, but it's formatting the output for you. Reversing a binary number or a string is not difficult.
int main() {
int n = 123456;
char in[16], obuf[] = " + x*10000000";
sprintf( in, "%d", n );
int rev = strlen( in ) + 2;
for( int o=3, i=0; (obuf[3] = in[i]) != '\0'; o=0, i++ )
printf( "%.*s", rev+3-o-i-(in[i+1]?0:2), obuf+o );
return 0;
}
Output
1*100000 + 2*10000 + 3*1000 + 4*100 + 5*10 + 6
You can expand the sizes to suit your needs.
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.
I have a number, 321197186 which the user inputs. How can I store this number into an array one element at a time. Basically, I am trying to store the 1st digit into 0th element and so on. And then I have to do some computation on that number.
Represent your number as a string, where every character of that string will be the corresponding digit of your number.
There are a plethora of method to read a string, but I suggest you use fgets() like this:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 10
int main (int argc, char *argv[])
{
char number[MAX_LEN];
printf("Enter a number: \n");
fgets(number, MAX_LEN , stdin);
printf("%s\n", number);
return 0;
}
With a for loop, you access the characters (digits) of the string (number) one by one, if you like.
I suggest you also eat the trailing newline that fgets() leaves in the input array, as already explained in Removing trailing newline character from fgets() input.
Alternative solution proposed by bruno#:
scanf("%9s", number);
Read more in C - scanf() vs gets() vs fgets().
Assume you have
int num;
if (scanf("%d", &num) != 1)
{
// Input error
exit(1);
}
// Now the user input is available in num
then you do
#define MAX_DIGITS 32
int digits[MAX_DIGITS] = { 0 };
int index = 0;
while(num != 0 && index < MAX_DIGITS)
{
digits[index] = num % 10;
++index;
num = num / 10;
}
// Now the array digits holds the individual digits
// and index holds the number of valid digits
You can consider this logic in C -
number = 321197186
while(number> 0) - leave if number becomes 0
{
int last_digit = number % 10; - Last digit from the number
printf("%d",last_digit);
number = number / 10; - to get the remaining number.
}
This can be also done in Python as -
number = 321197186
list1 = []
for i in str(number):
list1.append(i)
print(list1)
store this number into an array one element at a time.
Let us take advantage of the input process to have a convenient way to determine the length of input including leading zeros (but not input with a sign, leading spaces) by using "%n" to record the offset of the scan.
Use % 10 to exact the least significant decimal digit of the number.
int number;
int offset;
if (scanf("%d%n", &number, &offset) == 1) {
int a[offset]; // VLA
while (offset > 0) {
a[--offset] = number % 10;
number /= 10;
}
for (int i = 0; i < sizeof a/sizeof a[0]; i++) {
printf("a[%d] = %d\n", i, a[i]);
}
}
Output
a[0] = 3
a[1] = 2
a[2] = 1
a[3] = 1
a[4] = 9
a[5] = 7
a[6] = 1
a[7] = 8
a[8] = 6
But as bruno points out, you just have to check it as a string as an user input with fgets is an array of characters (even if we are talking about numbers).
For more detail:
for(i=0;i<sizeof(array_input);i++){
//Store the char into another array
}
I have this c program where I am inputing a number N followed by N more numbers. For example, I'll enter 100 followed by 100 more numbers. For some reason, after so many inputs the scanf function will stop working properly. It's as if it has stopped taking input and will just continue one with whatever value is in size.
The use case I came up with is 100 1 2 3 4 5 6 7 8 9 10... (repeated ten times). then after three or four times of that I'll type in 100 10 9 8 7 6 5 4 3 2 1... (repeated ten times) and then there will be an infinite loop of print statements.
int main(int argc, const char * argv[]) {
int histogram[10000];
int i;
while (1) {
int *rectPtr = histogram;
int size;
scanf("%d", &size);
if (!size) return 0;
for (i = 0; i < size; ++i) {
scanf("%d", rectPtr);
rectPtr++;
}
printf("%d", 1);
printf("\n");
}
return 0;
}
Distrust infinite loops.
In a series of comments, I said:
You're not testing the return value from scanf(), so you don't know whether it is working. The pair of printf() statements is odd; why not write printf("%d\n", 1); or even puts("1");?
Your code does not test or capture the return value from scanf(), so you do not know whether scanf() is reporting a problem. As a general rule, test the return value of input functions to make sure what you thought happened did in fact happen. You could also print out the values read just after you read them:
if (scanf("%d", rectPtr) != 1)
{
fprintf(stderr, "scanf() failed\n");
return 1;
}
printf("--> %d\n", *rectPtr);
rectPtr++;
Similarly when inputting size. Also consider if (size <= 0) return 0;. And using fgets() plus `sscanf() can make reporting errors easier.
j.will commented:
It is great to know if scanf fails, but I want to know why it fails and prevent it from failing. How do I do that?
I responded:
I understand you'd like to know. With scanf(), the best you can do after a failure is usually to read all the characters that follow up to a newline or EOF, and if you want to know what went wrong, then you print those characters too, because scanf() leaves the last character that it read in the input buffer ready for the next input operation.
void gobble(void)
{
printf("Error at: <<");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
puts(">>");
if (c == EOF)
puts("<<EOF>>");
}
The first character in the output is what caused the failure.
See also How to use sscanf() in loops?
Hacking your code to match this:
#include <stdio.h>
static void gobble(void)
{
printf("Error at: <<");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
puts(">>");
if (c == EOF)
puts("<<EOF>>");
}
int main(void)
{
enum { MAX_VALUES = 10000 };
int histogram[MAX_VALUES];
int size;
while (printf("Number of items: ") > 0 && scanf("%d", &size) == 1 &&
size > 0 && size <= MAX_VALUES)
{
int *rectPtr = histogram;
for (int i = 0; i < size; ++i)
{
if (scanf("%d", rectPtr) != 1)
{
gobble();
return 1;
}
rectPtr++;
}
printf("size %d items read\n", size);
}
return 0;
}
IMO, you need to check the return value of scanf() for proper operation. Please check the below code. I have added some modifications.
To exit from the program, you need to press CTRL+ D which will generate the EOF. Alternatively, upon entering some invalid input [like a char instead of int] wiil also cause the program to beak out of while() llop and terminate.
I have put the sequence to check first scanf(). All others need to be checked, too.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
int histogram[10000] = {0};
int i;
int *rectPtr = histogram;
int size = 0;
int retval = 0;
printf("Enter the number of elements \n");
while ( (retval = scanf("%d", &size)) != EOF && (retval == 1)) {
rectPtr = histogram;
if (!size) return 0;
printf("Enter %d elements\n", size);
for (i = 0; i < size; ++i) {
scanf("%d", rectPtr); //check in a simmilar way to above
rectPtr++;
}
printf("%d\n", 1111111);
printf("Enter the number of elements: \n");
}
return 0;
}
The output of a sample run
[sourav#broadsword temp]$ ./a.out
Enter the number of elements: 2
Enter 2 elements
1
2
1111111
Enter the number of elements: 3
Enter 3 elements
1
2
3
1111111
Enter the number of elements: 9
Enter 9 elements
0
9
8
7
6
5
4
3
2
1111111
Enter the number of elements: r
[sourav#broadsword temp]$
histogram is declared to have size 10000. You say you do 100 1 2 3 ... repeated 10 times. If I correctly understand that uses 1000 slots in histogram.
If you repeat the test more than 10 times, you exhaust histogram and begin to write past the end of array causing undefined behaviour.
So you must either :
reset recPtr = histogram at each iteration
control recPtr - histogram + size <= sizeof(histogram) after reading size (IMHO better)
And as other said, you should always control input operations : anything can happen outside of your program ...
So I am trying to make a smaller simple program to solve a problem. For this, I am trying to check to make sure the user inputs a number containing ONLY 1s and 0s and then I will use this number to perform a division. For example the number 11010 or 10111. Now my problem is, if I declare an integer to store this number (as follows) there wouldn't be a way to check all the digits are 1s or 0s right?
int userInput;
Now, I can use an array for this. (I know how to do this BUT this leads to my second problem.). Like so:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main (int argc, char *argv[]){
int myArray[20];
int i, input, length;
printf("Please enter how long your number is: \n");
scanf("%d", &length);
for (i = 0; i < length; i++){
printf("Please enter digit %d of your array\n", i+1);
scanf("%d", &input);
assert ((input == 1) || (input ==0));
}
For example, for the first digit the user enters a '1', the second digit the user enters a '0', then the third digit the user enters '0'. I need to "grab" this number though. How would I grab this number "100" and perform arithmetic operations on it. I hope this makes sense, if not moderators please give me a chance to clear it up.
EDIT: Many have suggested the modulo approach. BUT I still want to know if I can do this with an array. That is creating a integer variable and set that equal to each element the user has entered in the array.
I think this could be more simple:
bool is_zeros_and_ones(int n) {
for (; n != 0; n /= 10) {
int mod = n % 10;
if (0 != mod && 1 != mod) {
return false;
}
return true;
}
So you can input whole number and test it without arrays.
You don't really need to get the number one digit at a time.
It is easy to extract the digits of an int. Notice that a number such as 12345 is actually
5 * 10^0 + 4 * 10^1 + 3 * 10^2 + 2 * 10^3 + 1 * 10^4.
To get the lowest digit you can just take the remainder of the number when divided by 10 (i.e. mod it by 10 using the % operator). So, 12345 % 10 is 5. To get the next digit, you can divide the number by 10 (getting 1234) and then mod by ten again - giving you 4. Keep doing this as long as you have digits left in the number (i.e. the number is > 0).
#include <stdio.h>
int is_valid(int number) {
if (number == 0) return 1; // its a 0.
while (number != 0) {
int digit = number % 10;
if (digit != 1 && digit != 0) return 0;
number = number / 10;
}
return 1; // no other digits were found.
}
int main() {
int n;
scanf("%d", &n);
if (is_valid(n)) printf("valid\n");
else printf("not valid\n");
return 0;
}
Here's another idea:
Just write the number again into a string. Then iterate over the string checking each character. This is somewhat less efficient, but simpler to understand/code.
#include <stdio.h>
int is_valid(int n) {
char buffer[20];
char *c;
sprintf(buffer, "%d", n);
for(c = buffer; *c != '\0'; c++) {
if (*c != '0' && *c != '1') return 0;
}
return 1;
}
int main() {
int n;
scanf("%d", &n);
if (is_valid(n)) printf("valid\n");
else printf("not valid\n");
return 0;
}
EDIT:
Since you mentioned in your edit that you are not interested in alternate approaches and just need a way to "grab" the digits as they are fed in, I'm adding this to my answer.
Keep a variable initially set to 0. Now as each digit comes in, (I am assuming the user enters higher digits before lower ones), we multiply our variable by 10 and add the new digit to it. Thus, if the user enters 1, 0, 0, our variable is initially 0, the its 1 (0 * 10 + 1), then its 10 (1*10 + 0) and finally 100 (10 * 10 + 0), which is what we needed.
Maybe something like this would be enough
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main (int argc, char *argv[]){
int myArray[21];
printf("Please enter your number (max 20 digits)\n");
scanf("%s", myArray);
for (i = 0; i < strlen(myArray); i++){
assert ((myArray[i] == 1) || (myArray[i] == 0));
}
You don't need an array to store all the digits.
Keep dividing by 10 & taking modulo to get each digit & keep a single flag to mark if all digits are 1 or 0.
Of course works only for max word size of the integer...
Something like:
char isBinary = 1;
int copyInput = +input;
while(copyInput && (isBinary=copyInput%10<=1)) copyInput/=10;
You could cheat your way by making sure the program always deals with ints. Your array basically holds the binary representation of a base 10 number. Why not use it convert to an int. Then you can apply all operations to that number just as you would operate on ints.
Here is what i mean
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main (int argc, char *argv[]){
int i, input, length;
int num = 0; /* holds the actual number */
printf("Please enter how long your number is <= %d: \n", 8 * sizeof(num) - 1);
scanf("%d", &length);
for (i = 0; i < length; i++){
printf("Please enter digit %d of your array\n", i+1);
scanf("%d", &input);
assert ((input == 1) || (input ==0));
/* humans enter numbers L TO R */
/* set that bit if it is one */
num |= (input << (length - i - 1)) ;
}
printf("Your number in base 10 is %d\n",num);
/* Now you do normal multiplications, additions, divisions */
/* The only thing remaining now is to convert from base 10 to base 2. */
}
Sample run
Please enter how long your number is <= 31:
5
Please enter digit 1 of your array
1
Please enter digit 2 of your array
1
Please enter digit 3 of your array
1
Please enter digit 4 of your array
1
Please enter digit 5 of your array
0
Your number in base 10 is 30
This solution is only for the second part of the problem. You can take the input as characters and use atoi to convert them to integer.
char arrayOfNumbers[MAX_LENGTH];
char tmpChar;
int number;
for (i = 0; i < length; i++){
printf("Please enter digit %d of your array\n", i+1);
scanf("%c", &tmpChar);
assert ((tmpChar == '1') || (tmpChar == '0'));
arrayOfNumbers[i] = tmpChar;
}
/*make sure it is NULL terminated*/
arrayOfNumbers[length] = '\0';
number = atoi(arrayOfNumbers);