user1696230
user1696230

Reputation:

C Program not running as intended, hangs after input

The program I am writing to take a number and display that number as a calculator would display it (shown below) is compiling with no issues, but when I try to run it, I am able to input my number, but nothing happens. It seems like it is "hanging", since no further output is shown as I would have expected. Might anyone know what the problem is?

#include <stdio.h>
#define MAX_DIGITS 20

char segments[10][7] =              /* seven segment array */
    {{'1','1','1','1','1','1','0'}, /* zero */
     {'0','1','1','0','0','0','0'}, /* one */
     {'1','1','0','1','1','0','1'}, /* two */
     {'1','1','1','1','0','0','1'}, /* three */
     {'0','1','1','0','0','1','1'}, /* four */
     {'1','0','1','1','0','1','1'}, /* five */
     {'1','0','1','1','1','1','1'}, /* six */
     {'1','1','1','0','0','0','0'}, /* seven */
     {'1','1','1','1','1','1','1'}, /* eight */
     {'1','1','1','0','0','1','1'}};/* nine */
char digits[3][MAX_DIGITS * 4];     /* digits array */
int i, j;                           /* count variables */
int adjust;                         /* output formatting */

int main(void) {
    clear_digits_array();

    int digit[20];
    for (i = 0; i < 20; i++) {
        digit[i] = 0;
    }

    int count = 20;
    int position = 0;

    printf("Enter a number: ");

    int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
            &digit[0],
            &digit[1],
            &digit[2],
            &digit[3],
            &digit[4],
            &digit[5],
            &digit[6],
            &digit[7],
            &digit[8],
            &digit[9],
            &digit[10],
            &digit[11],
            &digit[12],
            &digit[13],
            &digit[14],
            &digit[15],
            &digit[16],
            &digit[17],
            &digit[18],
            &digit[19]);                        //NOTHING HAPPENS AFTER HERE

    printf("Got input, number is %d", number); 

    while (count > 0) {
        printf("Reading digits, count is %d", count);
        process_digit(digit[20 - count], position);
        position++;
        count--;
    }

    print_digits_array();
    printf("\n");
    return 0;
}

void clear_digits_array(void) {
    /* fill all positions in digits array with blank spaces */
    for (i = 0; i < 3; i++) {
        for (j = 0; j < (MAX_DIGITS * 4); j++) {
            digits[i][j] = ' ';
        }
    }
}

void process_digit(int digit, int position) {
    /* check each segment to see if segment should be filled in for given digit */
    for (i = 0; i < 7; i++) {
        printf("Processing digit %d at position %d, i is %d", digit, position, i);
        if (segments[digit][i] == 1) {
            switch (i) {
                case 0: digits[0][(position * 4) + 1] = '_';
                        break;
                case 1: digits[1][(position * 4) + 2] = '|';
                        break;
                case 2: digits[2][(position * 4) + 2] = '|';
                        break;
                case 3: digits[2][(position * 4) + 1] = '_';
                        break;
                case 4: digits[2][(position * 4) + 0] = '|';
                        break;
                case 5: digits[1][(position * 4) + 0] = '|';
                        break;
                case 6: digits[1][(position * 4) + 1] = '_';
                        break;
            }
        }
    }
}

void print_digits_array(void) {
    /* print each character in digits array */
    for (i = 0; i < 3; i++) {
        for (j = 0; j < (MAX_DIGITS * 4); j++) {
            printf("%c", digits[i][j]);
        }
        printf("/n");
    }
}

Upvotes: 0

Views: 576

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 754400

Your code includes:

printf("Enter a number: ");

int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
        &digit[0],
        &digit[1],
        &digit[2],
        &digit[3],
        &digit[4],
        &digit[5],
        &digit[6],
        &digit[7],
        &digit[8],
        &digit[9],
        &digit[10],
        &digit[11],
        &digit[12],
        &digit[13],
        &digit[14],
        &digit[15],
        &digit[16],
        &digit[17],
        &digit[18],
        &digit[19]);                        //NOTHING HAPPENS AFTER HERE

Have you entered twenty separate digits? If not, scanf() is waiting for you to type some more numbers.

Note that the return value from scanf() is the number of successfully converted numbers (0..20 in the example), not the value you entered.


Is that the issue? I tried to make it such that the maximum amount of numbers the user could enter was 20, and if any more were entered they would be ignored, or if fewer were entered, it would only consider those (say, 5 were entered, then only the 5 would be used). Is there an easier way to do this sort of thing then?

Yes, I think that's the issue.

There are probably several easier ways to do it. I'd be tempted to use:

char buffer[22];  // 20 digits, newline, null
if (fgets(buffer, sizeof(buffer), stdin) != EOF)
{
    size_t len = strlen(buffer);
    if (len >= sizeof(buffer) - 1)
    {
        fprintf(stderr, "You entered too long a string (maximum 20 digits)\n");
        exit(EXIT_FAILURE);
    }
    if (len > 0)
        buffer[--len] = '\0';  // Zap newline — carefully
    for (int i = 0; i < len; i++)
    {
        if (!isdigit(buffer[i]))
        {
            fprintf(stderr, "Non-digit %c found\n", buffer[i]);
            exit(EXIT_FAILURE);
        }
    }
    ...and from here, process the digits in buffer, one at a time...
    ...Use buffer[i] - '0' to get a number 0..9 from the character in buffer...
}

Another option is to use a long long number, but that only gives you up to 18 digits (signed) or 19 digits (unsigned), with some values of 19 or 20 also within range. You'd then strip the digits out of the number using division and modulus operations.

long long value;
if (scanf("%lld", &value) == 1)
{
    if (value < 0)
        ...error processing...
    do
    {
        int digit = value % 10;
        value /= 10;
        ...process digit...
    } while (value > 0);
}

This has some merits, but in practice, I'd be tempted to use fgets() to read a line of input, and either sscanf() or strtoll() to convert and validate the number. That isn't as simple as it looks; the error returns from strtoll(), in particular, are many and subtle, and none of the scanf() family handle overflowing numbers gracefully. You could constrain the scanf() though with %18lld so that no more than 18 digits are read, but that would mean that if the user typed 19 or more digits, you'd get the leftovers on the next attempt to read with scanf(). So, handling scanf() is not simple either, especially if you need to convert multiple numbers in a single run of the program.

With those caveats out of the way, you can usually do a 'good enough' job with a sensible person providing the input. It is the process of making a program bomb-proof (foolproof — as in, proof against fools) that is hard. I find meaningful error reporting easier when I can report the whole string that was read in (as with fgets()); with scanf(), you can't see the characters that were entered and consumed before something went wrong.

Upvotes: 2

Omkant
Omkant

Reputation: 9204

int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
            &digit[0],
            &digit[1],
            &digit[2],
            &digit[3],
            &digit[4],
            &digit[5],
            &digit[6],
            &digit[7],
            &digit[8],
            &digit[9],
            &digit[10],
            &digit[11],
            &digit[12],
            &digit[13],
            &digit[14],
            &digit[15],
            &digit[16],
            &digit[17],
            &digit[18],
            &digit[19]);         

I don't think this is a good idea use loop here

for (i = 0; i < 20; i++) 
        scanf("%d",&digit[i]);

And if you need the number then do like this

int number = i; when loop finishes.

You can also try this

char buf[12]; 
while((c=getchar())!=EOF && i < 20)
{
 buf[j++] =c;
 if((c == '\n' || c == ' ' || c == '\t') && (sscanf(buf,"%d",&digit[i])) == 1)
   {
    i++;
    j = 0;
   }
 }

For EOF you will have to press CTRL+D In this way you can take 20 or less integers

Upvotes: 0

Charan Pai
Charan Pai

Reputation: 2318

use GDB, here is introduction for it http://www.gnu.org/software/gdb/ look into this tutorial too http://www.cs.cmu.edu/~gilpin/tutorial/

Upvotes: 0

Related Questions