nofe
nofe

Reputation: 408

Extracting individual digits from a long in C

I'm doing a homework assignment for my course in C (first programming course). Part of the assignment is to write code so that a user inputs a number up to 9 digits long, and the program needs to determine whether this number is "increasing"/"truly increasing"/"decreasing"/"truly decreasing"/"increasing and decreasing"/"truly decreasing and truly increasing"/"not decreasing and not increasing". (7 options in total)

Since this is our first assignment we're not allowed to use anything besides what was taught in class:

do-while, for, while loops, else-if, if, break,continue scanf, printf ,modulo, and the basic operators

(We can't use any library besides for stdio.h)

That's it. I can't use arrays or getchar or any of that stuff. The only function I can use to receive input from the user is scanf.

So far I've already written the algorithm with a flowchart and everything, but I need to separate the user's input into it's distinct digits.

For example, if the user inputs "1234..." i want to save 1 in a, 2 in b, and so on, and then make comparisons between all the digits to determine for example whether they are all equal (increasing and decreasing) or whether a > b >c ... (decreasing) and so on.

I know how to separate each digit by using the % and / operator, but I can't figure out how to "save" these values in a variable that I can later use for the comparisons.

This is what I have so far:

printf("Enter a positive number : ");

do {
    scanf ("%ld", &number);
    if (number < 0) {
        printf ("invalid input...enter a positive integer: ");
        continue;
    }
    else break;
} while (1);

while (number < 0) {
    a = number % 10;
    number = number - a;
    number = number / 10;
    b = a;
}

Upvotes: 8

Views: 19822

Answers (7)

Andrew.K.S
Andrew.K.S

Reputation: 56

// u_i is the user input, My homework asked me to extract a long long, however, this should also be effective for a long.

int digits = 0;
long long d_base = 1;
int d_arr[20];
while (u_i / d_base > 0)
{
    d_arr[digits] = (u_i - u_i / (d_base * 10) * (d_base * 10)) / d_base;
    u_i -= d_arr[digits] * d_base;
    d_base *= 10;
    digits++;
}

EDIT: the extracted individual digit now lives in the int array d_arr. I'm not good at C, so I think the array declaration can be optimized.

Upvotes: 1

P.P
P.P

Reputation: 121397

I would suggest loop-unrolling.

int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits
int count = 0; //for number of digits in the given number


if(number>0) {
i=number%10;
number/=10;
count++;
}

if(number>0) {
h=number%10;
number/=10;
count++;
}

if(number>0) {
g=number%10;
number/=10;
count++;
}
....
....
/* All the way down to the storing variable a */

Now, you know the number of digits (variable count) and they are stored in which of the variables. Now you have all digits and you can check their "decreasing", "increasing" etc with lots of if's !

I can't really think of a better soltion given all your conditions.

Upvotes: 0

Aaron Dufour
Aaron Dufour

Reputation: 17505

Since you only need to compare consecutive digits, there is an elegant way to do this without arrays:

int decreasing = 2;
int increasing = 2;

while(number > 9)
{
  int a = number % 10;
  int b = (number / 10) % 10;

  if(a == b)
  {
    decreasing = min(1, decreasing);
    increasing = min(1, increasing);
  }
  else if(a > b)
    decreasing = 0;
  else if(a < b)
    increasing = 0;

  number /= 10;
}

Here, we walk through the number (by dividing by 10) until only one digit remains. We store info about the number up to this point in decreasing and increasing - a 2 means truly increasing/decreasing, a 1 means increasing/decreasing, and a 0 means not increasing/decreasing.

At each step, a is the ones digit and b is the tens. Then, we change increasing and decreasing based on a comparison between a and b.

At the end, it should be easy to turn the values of increasing and decreasing into the final answer you want.

Note: The function min returns the smaller of its 2 arguments. You should be able to write your own, or replace those lines with if statements or conditionals.

Upvotes: 2

Evan Mulawski
Evan Mulawski

Reputation: 55334

Why not scan them as characters (string)? Then you can access them via an array offset, by subtracting the offset of 48 from the ASCII character code. You can verify that the character is a digit using isdigit from ctype.h.


EDIT

Because of the incredibly absent-minded limitations that your professor put in place:

#include <stdio.h>

int main()
{
  int number;
  printf("Enter a positive number: ");

  do
  {
    scanf ("%ld", &number);
    if (number < 0)
    {
      printf ("invalid input...enter a positive integer: ");
      continue;
    }
    else break;
  } while (1);

  int a = -1;
  int b = -1;
  int c = -1;
  int d = -1;
  int e = -1;
  int f = -1;
  int g = -1;
  int h = -1;
  int i = -1;

  while (number > 0)
  {
    if (a < 0) a = number % 10;
    else if (b < 0) b = number % 10;
    else if (c < 0) c = number % 10;
    else if (d < 0) d = number % 10;
    else if (e < 0) e = number % 10;
    else if (f < 0) f = number % 10;
    else if (g < 0) g = number % 10;
    else if (h < 0) h = number % 10;
    else if (i < 0) i = number % 10;

    number /= 10;
  }

  /* Printing for verification. */

  printf("%i", a);
  printf("%i", b);
  printf("%i", c);
  printf("%i", d);
  printf("%i", e);
  printf("%i", f);
  printf("%i", g);
  printf("%i", h);
  printf("%i", i);

  return 0;
}

The valid numbers at the end will be positive, so those are the ones you validate to meet your different conditions.

Upvotes: 5

ali
ali

Reputation: 11045

Let us suppose you have this number 23654

23654 % 10000 = 2 and 3654
3654 % 1000 = 3 and 654
654 % 100 = 6 and 54
54 % 10 = 5 and 4
4

This way you can get all the digits. Of course, you have to know if the number is greater than 10000, 1000, 100 or 10, in order to know the first divisor.

Play with sizeof to get the size of the integer, in order to avoid a huge if...else statement

EDIT:

Let us see

if (number>0) {
    // Well, whe have the first and only digit
} else if (number>10) {
    int first_digit = number/10;
    int second_digit = number % 10;
} else if (number>100) {
    int first_digit = number/100;
    int second_digit = (number % 100)/10;
    int third_digit = (number % 100) % 10;
} ...

and so on, I suppose

Upvotes: 1

aleroot
aleroot

Reputation: 72636

Here's a working example in plain C :

#include <stdio.h>

unsigned long alePow (unsigned long int x, unsigned long int y);

int main( int argc, const char* argv[] )
{
   int enter_num, temp_num, sum = 0;
   int divisor, digit, count = 0;

    printf("Please enter number\n");
    scanf("%d", &enter_num);

   temp_num = enter_num;

   // Counting the number of digits in the entered integer
   while (temp_num != 0)
   {
       temp_num = temp_num/10;
       count++;
   }

   temp_num = enter_num;

   // Extracting the digits
   printf("Individual digits in the entered number are ");
   do
   {
       divisor = (int)(alePow(10.0, --count));
       digit = temp_num / divisor;
       temp_num = temp_num % divisor;

       printf(" %d",digit);
       sum = sum + digit;
   }
   while(count != 0);

   printf("\nSum of the digits is = %d\n",sum);

   return 0;
}


unsigned long alePow(unsigned long int x, unsigned long int y) {

    if (x==0) { return 0; } 
    if (y==0||x==1) { return 1; } 
    if (y==1) { return x; }
    return alePow(x*x, y/2) * ((y%2==0) ? 1 : x);
}

Upvotes: 0

Robert Martin
Robert Martin

Reputation: 17157

It's stupid to ask you to do loops without arrays --- but that's your teacher's fault, not yours.

That being said, I would do something like this:

char c;
while (1) {
    scanf("%c", &c);
    if (c == '\n')    /* encountered newline (end of input) */
        break;
    if (c < '0' || c > '9')
        break;        /* do something to handle bad characters? */
    c -= '0';
    /*
     * At this point you've got 0 <= c < 9. This is
     * where you do your homework :)
     */
}

The trick here is that when you type numbers into a program, you send the buffer all at once, not one character at a time. That means the first scanf will block until the entire string (i.e. "123823" or whatever) arrives all at once, along with the newline character ( '\n' ). Then this loop parses that string at its leisure.

Edit For testing the increasing/decreasing-ness of the digits, you may think you need to store the entire string, but that's not true. Just define some additional variables to remember the important information, such as:

int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far;

etc. etc.

Upvotes: 1

Related Questions