Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help understanding while loops

Tags:

c

Let's say that we have a very simple code that begins like:

#include <stdio.h>
int main() {
    char c;
    int x;

    printf("Num here: ");
    c = getchar();
    x = 0;

    while (c!=EOF) {
        x = c - 48; //to convert x from ASCII

In this program, I'm trying to get the user to type a number (ex. 42) and am trying to add the ones digit to the tens (and to the hundreds, etc.); I'm having a lot of trouble understanding how you can get the while loop to go back to the loop until the end of the number.

So, I need a lot of help understanding how I can get the loop to read until the end of the character, read the char input the user puts in as a number (42), and then, treat the numbers individually using just getchar().

like image 900
Alex Ray Avatar asked Dec 10 '25 21:12

Alex Ray


1 Answers

Normally, you'd use:

int c;  // Because getchar() returns an int, not a char
int x = 0;

while ((c = getchar()) != EOF)
{
    if (isdigit(c))
        x = x * 10 + (c - '0');
    else
        ...
}

This reads a character each time it reaches the top of the loop. You get the loop to go back by running into the brace at the end of the loop (or, occasionally, by using a continue statement). You might exit the loop with a break, for example if you read some character that can't be part of a number.

If the user types 42 (followed by Enter), then you first read c == '4' and then c == '2' and then you read newline '\n'. For every digit from '0' to '9', digit - '0' yields the number corresponding to the digit. The newline can't be part of the number, so you either put it back with ungetc(c, stdin) or break the loop when you've read it.

Beware of overflow if the user types 43219876543 where you expected just 42 (and int is a 32-bit quantity).

You could write the loop condition as:

while ((c = getchar()) != EOF && isdigit(c))

or even:

while (isdigit(c = getchar()))

I'd be extremely reluctant to actually put the latter into production code but it is, in theory, safe.


How could I treat each number individually so that I can use the entirety of the numbers later on? So that if the user types 10 20 30, I can multiply 10 by 20, then (10*20) by 30?

Wheels within wheels — or loops within loops. You'll need to specify your criteria a bit. If the user types 1 you want the answer 1; if they type 1 2, you want 2; if they type 1 2 3, you want 6; and so on (where these are all the numbers on a single line of input). You'll need an outer loop that skips over blanks and tabs, then uses the inner loop to read a number, and then multiplies the current product (initial value 1) by the new number, and after the outer loop, you'll print the product. This will print 1 for an empty line; maybe that doesn't matter (and maybe it does).

Here's some code that approximates what is appropriate:

#include <ctype.h>
#include <stdio.h>

int main(void)
{
    int c;
    while ((c = getchar()) != EOF && c != '\n')
    {
        int product = 1;
        while (c != EOF && c != '\n')
        {
            while (isspace(c))
                c = getchar();
            int number = 0;
            while (isdigit(c))
            {
                number = number * 10 + (c - '0');
                c = getchar();
            }
            printf("Number:  %d\n", number);
            product *= number;
        }
        printf("Product: %d\n", product);
    }
    return 0;
}

I also tried a version with a slightly different 'skip' loop:

            while (c != EOF && c != '\n' && !isdigit(c))
                c = getchar();

Both work OK on sane inputs. Empty lines are treated as end of input; lines containing blanks are not. If you input 1a2b3c with the second condition, you will get the output 0; with the first, you get an infinite loop. There is no overflow protection; don't try doing factorial 20 and expect the correct answer (with 32-bit int). Tweak to your heart's content.

like image 132
Jonathan Leffler Avatar answered Dec 13 '25 17:12

Jonathan Leffler