Search code examples
cequationatoi

int with atoi() calculated value is always 0


I am creating a program that will calculate first degree equations. My issue is that, because an equation will include characters and operands, I need to store date on a string and then pass them to integers via atoi(). Yet, the answer value never changes from 0 (set value). Why is that?

Here is the code:

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


int main()
{
    char equation[10];

    scanf("%s", equation);

    int length = strlen(equation);


    char operands[7];
    int op_index[7];
    int op_amount = 0;

    for(int i = 0; i < length; i++){
        if(equation[i] == '*' || equation[i] == '/' || equation[i] == '+' || equation[i] == '-'){
            operands[op_amount] = equation[i];
            op_index[op_amount] = i;
            op_amount++;
        }
    }

    char nums1[3];
    char nums2[3];
    int i = op_index[0] - 1;
    int j = 3;

    int ans = 0;

    while(isdigit(equation[i]) != 0){
        nums1[j] = equation[i];

        j--;
        i--;
    }

    i = op_index[0] + 1;
    j = 0;

    while(isdigit(equation[i]) != 0){
        nums2[j] = equation[i];

        j++;
        i++;
    }

    if(operands[0] == '*'){
        ans = atoi(nums1) * atoi(nums2);
    }
    else if(operands[0] == '/'){
        ans = atoi(nums1) / atoi(nums2);
    }
    else if(operands[0] == '+'){
        ans = atoi(nums1) + atoi(nums2);
    }
    else if(operands[0] == '-'){
        ans = atoi(nums1) - atoi(nums2);
    }

    printf("ans = %d", ans);
}

Solution

  • You are working too hard. Or, rather you're making the computer work too hard. You don't need (or want) to "store date on a string". You do not need to copy that data around. atoi is a broken tool (undefined behavior if the input cannot be represented by an integer), but it is able to mostly do what you want. Instead of copying the data around, just pass it the first character of the string you are interested in. The following code does not handle invalid data very well (ie, the string "5 + + + 10" will be treated the same as "5 + 0" and "1foo +3x" is the same as "1+3"), but adding the logic to validate the input is left as an exercise for the reader. (hint: validating the input is a lot easier if you use strtol instead of atoi.)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    int
    main(int argc, char **argv)
    {
        char equation[1024];
        int ans;
    
        if( 1 != scanf("%1023[^\n]", equation) ){
            fprintf(stderr, "No data avaialable\n");
            return 1;
        }
    
        char *operator = equation + strcspn(equation, "*/+-");;
        char *operand = operator + 1;
        switch( *operator ){
        case '*': ans = atoi(equation) * atoi(operand); break;
        case '/': ans = atoi(equation) / atoi(operand); break;
        case '+': ans = atoi(equation) + atoi(operand); break;
        case '-': ans = atoi(equation) - atoi(operand); break;
        default:
            fprintf(stderr, "No operator found\n");
            return 1;
        }
    
        printf("ans = %d\n", ans);
        if( fflush(stdout) ){
            perror("stdout");
            return 1;
        }
        return 0;
    }
    

    Note that scanf is absolutely the wrong way to get input here, and it would make more sense to take the argument as a command line parameter. If you do read from the input stream, it would make more sense to use fgets. But I keep scanf here to demonstrate two thing: you must use a width modifier on %s and %[ conversions to prevent buffer overflow, and you should always check the return value.