1

I was working on a class project and I wanted to do a little bit extra and make validation on my data. The problem seems to happen at num1 = num1Input (and num2 = num2Input) where it is getting the location (I assume) instead of the actual input value

int main(void) {
    //variables
    char num1input[10];
    char num2input[10];

    int length, i;
    int num1 = 0;
    int num2 = 0;
    int countErrors1 = 0;
    int countErrors2 = 0;

    bool correct1 = false;
    bool correct2 = false;

    //--end of variable declarations--//

    do {
        printf("Please enter a number: ");
        scanf("%s", num1input);
        length = strlen(num1input);
        for (i = 0; i < length; i++) {
            if (!isdigit(num1input[i])) {
                countErrors1++;
            }
        }
        if (countErrors1 > 0) {
            printf("Input is not a number \n");
        } else {
            correct1 = true;
        }
    } while (correct1 == false);
    num1 = num1input;

    do {
        printf("Please enter second number: ");
        scanf("%s", num2input);
        length = strlen(num2input);
        for (i = 0; i < length; i++) {
            if (!isdigit(num2input[i])) {
                countErrors2++;
            }
        }
        if (countErrors2 > 0) {
            printf("Input is not a number \n");
        } else {
            correct2 = true;
        }
    } while (correct2 == false);
    num2 = (int)num2input;

    printf("%d %d \n", num1, num2);

    int addition = num1 + num2;
    int substraction = num1 - num2;
    int multiplication = num1 * num2;
    float division = num1 / num2;

    printf("Addition: %d Subtraction: %d Multiplication: %d Division: %.1e", addition, substraction, multiplication, division);

    getch();
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 2
    C doesn't do decimal-to-binary conversion on cast. You are looking for [`strtol`](http://linux.die.net/man/3/strtol). – zwol Mar 08 '16 at 17:39
  • I only wish that the value in num1Input is stored in num1. What can I do? – Nathaniel Cutajar Mar 08 '16 at 17:43
  • 2
    You use `strtol`, like I said. (Also, forget you ever heard of `scanf`, which is broken-as-specified; the correct function to use for user input in C is `getline` if available, `fgets` otherwise.) – zwol Mar 08 '16 at 17:51
  • "do a little bit extra and make validation on my data" --> Great! Note that `isdigit(num1input[i])` will fail `'-'`. Research `strtol()`. – chux - Reinstate Monica Mar 08 '16 at 18:00

1 Answers1

1

You cannot convert a string to a number with a cast such as num1 = num1input;. You need to call a library function from <stdlib.h>:

#include <stdlib.h>

...

num1 = atoi(num1input);

But atoi ignores parsing errors. To ensure that overflows are detected, you can use strtol() as follows:

#include <errno.h>
#include <limits.h>
#include <stdlib.h>

...

errno = 0;
char *endp;
long lval = strtol(num1input, &endp, 10);
if (endp == num1input || errno != 0 || lval < INT_MIN || lval > INT_MAX) {
    /* parse error detected:
     * you could print an error message.
     */
    if (lval < INT_MIN) lval = INT_MIN;  /* clamp lval as an int value. */
    if (lval > INT_MAX) lval = INT_MAX;
}
num1 = lval;

Or if you want to recognize hexadecimal syntax such as 0x10:

num1 = strtol(num1input, NULL, 0);

The same is applicable for num2input.

Note that isdigit(num1input[i]) is potentially incorrect if char is signed and num1input[i] has a negative value. You should write:

isdigit((unsigned char)num1input[i])

Also note that float division = num1 / num2; will compute the integer division and convert the result to a float. If you want the floating point division, you should write:

float division = (float)num1 / num2;

Note finally that it is recommended to use double instead of float for better accuracy.

Here is a corrected and simplified version:

#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

/* simple implementation of strtoi(), inspired by elegant code from chux */
int strtoi(const char *s, char **endptr, int base) {
    long y = strtol(s, endptr, base);
#if INT_MAX != LONG_MAX
    if (y > INT_MAX) {
        errno = ERANGE;
        return INT_MAX;
    }
#endif
#if INT_MIN != LONG_MIN
    if (y < INT_MIN) {
        errno = ERANGE;
        return INT_MIN;
     }
#endif
    return (int)y;
}

int main(void) {
    char num1input[20];
    char num2input[20];
    char *endp;
    int num1, num2;

    for (;;) {
        printf("Please enter a number: ");
        if (scanf("%19s", num1input) != 1)
            return 1;
        errno = 0;
        num1 = strtoi(num1input, &endp, 10);
        if (errno == 0 && *endp == '\0')
            break;
        printf("Input is not a number\n");
    }

    for (;;) {
        printf("Please enter a second number: ");
        if (scanf("%19s", num2input) != 1)
            return 1;
        errno = 0;
        num2 = strtoi(num2input, &endp, 10);
        if (errno == 0 && *endp == '\0')
            break;
        printf("Input is not a number\n");
    }

    printf("%d %d\n", num1, num2);

    int addition = num1 + num2;
    int subtraction = num1 - num2;
    int multiplication = num1 * num2;
    double division = (double)num1 / num2;

    printf("Addition: %d Subtraction: %d Multiplication: %d Division: %g\n",
           addition, subtraction, multiplication, division);
    getch();
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189