-2

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...

4 Answers4

1

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.

SenselessCoder
  • 1,139
  • 12
  • 27
  • I must admit, I know very little at the moment about strings in C. I must look up some information about them. Thanks for the help :) –  Oct 29 '16 at 15:16
  • @Konahrik16 the single most important thing you need to know about a C string, it is only a "string" if the array ends with a `0` terminator, and following on from that, the memory allocated must allow for that terminator. So a PIN length 4 will need a string of at least 5 to accomodate it. – Weather Vane Oct 29 '16 at 15:19
  • This sounds silly to ask but if the pin is a string can't someone enter "BOBY" as a valid pin input? Even if it's supposed to be a number? –  Oct 29 '16 at 15:24
  • Yes, but that won't match the PIN, so it is detected as an invalid input. – Weather Vane Oct 29 '16 at 15:27
0

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.

elikatsis
  • 479
  • 1
  • 3
  • 8
0

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;
}
Eli Sadoff
  • 7,173
  • 6
  • 33
  • 61
  • `(size(pin) == 5)` is true no matter what is entered. – Weather Vane Oct 29 '16 at 15:17
  • I am sorry, but `char pin[5];` is an array of 5 bytes. Its size is `5`. – Weather Vane Oct 29 '16 at 15:22
  • I'm using `size` not `sizeof` and I defined `size` myself. It gives the number of elements until `\0`. It's not the size of the array, but the size of the string including the null terminator. – Eli Sadoff Oct 29 '16 at 15:23
  • Uh, sorry about my oversight, but you made the [classic boob](http://stackoverflow.com/questions/17590226/c-finding-length-of-array-inside-a-function) with `sizeof(a)` in the function. That is the size of the pointer that was passed. if it works, it is a coincidence that the pin is 4 digits and a 32-bit pointer is 4 bytes. – Weather Vane Oct 29 '16 at 15:25
  • @Eli what is the difference between `size()` and `strlen()`. BTW, `fgets(pin, sizeof(pin), stdin);` likely leaves a `'\n'` in `stdin`. – chux - Reinstate Monica Oct 29 '16 at 15:26
  • @chux, there is no difference, but you don't have to include `string.h` which saves loading a library. – Eli Sadoff Oct 29 '16 at 15:28
  • @WeatherVane Oops. I fixed that. – Eli Sadoff Oct 29 '16 at 15:28
  • 1
    @chux good point, but by restricting the length to 5, the `newline` will be input at the next `fgets` (if any) when 4 digits were entered. – Weather Vane Oct 29 '16 at 15:31
  • Eli it's a rare C program that does not need `string.h` – Weather Vane Oct 29 '16 at 15:35
  • It depends upon what you're doing. If you only need `string.h` for `strlen`, IMO it isn't worthwhile to include the entire library. I have a 2 functions or more rule generally for including libraries unless it's `stdio.h` or `stdlib.h`. – Eli Sadoff Oct 29 '16 at 15:37
0

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".

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256