-1

I'm writing a simple calculation program, however the only string handling functions I can use are getchar and putchar. Right now I'm just trying to assign the numbers from input to variables, but when I print the variable it's some random number. For example, I entered 3 into the console and the output was 505110. Any help would be appreciated. Thank you.

#include <stdio.h>
#include "math.h"

int addFunction( int, int);
int subtractFunction(int, int);
int multiplyFunction(int, int);
int modulusFunction(int, int);
float divideFunction(float, float);

int main(int argc, const char * argv[])
{

int iochar = 0;
char num1 = 0, num2 = 0, continuePrompt, operator = 0;

do {
    iochar = getchar();
    getchar();


    if ((iochar >= 0) && (iochar <= 20000)) {
        num1 = iochar; 
    }

    if ((iochar == '+') || (iochar == '-') || (iochar == '*') || (iochar == '/') || (    iochar == '%')) {
        operator = iochar; 
    }

    if ((num1 >= 0) || ((iochar >= 0) && (iochar <= 20000))){
        num2 = iochar;
    }

    switch (operator) {

        case '+':
            iochar = addFunction(num1, num2);
            break;

        case '-':
            iochar = subtractFunction(num1, num2);
            break;

        case '*':
            iochar = multiplyFunction(num1, num2);
            break;

        case '%':
            iochar = modulusFunction(num1, num2);
            break;

        case '/':
            iochar = divideFunction(num1, num2);
            break;

    }

    putchar(iochar);

    printf("Would you like to make another calulation? (y or n)");
    scanf("%c", &continuePrompt);

} while (continuePrompt != 'n');
return 0;
}

int addFunction(int x, int y){
    return x + y;
}

int subtractFunction(int x, int y){
     return x - y;
}

int multiplyFunction(int x, int y){
    return x * y;
}

int modulusFunction(int x, int y){
    return x % y;
}

float divideFunction(float x, float y){
    return x / y;
}
user1681673
  • 368
  • 1
  • 6
  • 28
  • 1
    Without source code we can only randomly guess. – Eric J. Oct 05 '12 at 02:52
  • I forgot that, didn't I? lol. – user1681673 Oct 05 '12 at 02:53
  • Also, the continuePrompt is to ask the user if they would like to enter another calculation. – user1681673 Oct 05 '12 at 02:54
  • Remember: `getchar()` returns an `int`, not a `char`. It returns every possible character value plus a distinct value, EOF. If you store its result in a `char`, you lose information about whether you got an EOF indication. Whether that's the direct cause of your trouble is a separate issue (it probably isn't); but get into the habit of using the correct type for storing the value from `getchar()` and its relatives. – Jonathan Leffler Oct 05 '12 at 03:05
  • You read one character; you are pretty much guaranteed to assign it to `num1` because the value will be between 0 and 255 (or 0 and 127 if you're using a compiler with signed `char` type). Without reading anything else, you see whether the character is one of the operator characters. And again without reading anything else, you almost certainly assign it to `num2` too. The use of `'no'` is non-portable and you're virtually guaranteed that zero does equal it. You need to think a lot harder about what you're doing. You'll need to accumulate digits, ignore spaces, handle operators, etc. – Jonathan Leffler Oct 05 '12 at 03:12

5 Answers5

1

The code is working exactly correct. When you enter a "3" in ASCII that's really the hex value 0x33, you're printing the value in dec (%d) thus you'll see a 51 on the output.

Now you're failing to consume the newline character that was entered, so getchar() is skipping the input on the second pass and is assuming you passed in a '\n' ASCII, which is hex 0xa and thus 10 is printed next.

You don't print any newlines or spaces so on the output you'll see:

3 (I entered that)
5110 (the output from '3''\n')

To fix the main problem, consume the new line character:

int main(int argc, const char * argv[])  {
    int iochar, num1, num2;  
    char continuePrompt = 0, operator;
    do {
      iochar = getchar();  // Get input from user
      getchar(); //Consume new line character

When you're printing the values, you're going to get ASCII values back, so if you want the dec, you're good, if you want it in character:

printf("%c", num1);

if you wanted it in hex (0x??)

printf("%#x", num1);

Also I'd print a new line or spaces or something more helpful then just a string of output to help find problems like this.

Finally this condtion:

while (continuePrompt != 'no');  

Is wrong. That can't happen, check against 'n', you can't have 'no' in a single character.

Mike
  • 47,263
  • 29
  • 113
  • 177
  • Thank you for the help. I entered your suggestions and I'm still having some problems. Also, I can't use printf to display any of the results. I can only use getchar and putchar. Do you know what I'm doing wrong? Thank you for the help. – user1681673 Oct 06 '12 at 00:07
0

Use %c instead of %d

i.e.

printf("%c", num1);

Also,you should initialize the variables.

i.e

int iochar=0, num1=0, num2=0;
char continuePrompt = 0, operator=0;
Anirudha
  • 32,393
  • 7
  • 68
  • 89
0

Since you're only allowed to use putchar and getchar, I assume that you're not allowed to use printf in order to present the result. In order to use an actual number with putchar you'll have to take each digit and transform it to the correct ASCII value.

Fortunately this is very simple, since

digitRepresentationASCIIValue == singleDigitValue + '0';

However, this will only work on a single digit. So you'll have to get the length of a number and use putchar for each digit. This is very simple:

void putNumber(int num){
    int order = 1; // even zero has at least one digit
    int tmp = num; // even zero has at least one digit

    while(tmp /= 10)
        order *= 10; // count digits

   if(num < 0)
       putchar('-'); // sign

    while(order > 0){
        // put a single digit, see above how to calculate the ASCII value
        putchar('0' + ( ( num / order ) % 10));
        order /= 10;
    }
}

In order to actually read values you would have to do the exact opposite: check whether the character provided by getchar is a digit, and modify your current number:

int num[2] = {0,0};
int currentNum = 0;
int iochar = getchar();

while(!isNewline(iochar) && iochar != EOF){
    if(isDigit(iochar)){
        num[currentNum] = num[currentNum] * 10 + iochar - '0';
    }
    else if(isOperator(iochar)){
        if(currentNum == 1)
            num[0] = operate(num[0],num[1],operator);
        else
            currentNum = 1;
        operator = iochar;
        num[1] = 0;
    }
    iochar = getchar();
}

isDigit, isNewline and isOperand are left for exercise, all three are very simple but they will give you a better idea of ASCII values. operate contains your switch statement.

Note that I used int num[2] = {0,0};. This enables (in addition to currentNum) to write something like

3 + 3 + 3 / 9

Note that all operators are evaluated from left to right, as such the result of the example above will be 1 and not 6.3333333.

Exercises:

Don't publish your solution here, but do them for yourself as they should help you to improve your ASCII/char skills. For some exercises an ASCII table might be helpful.

  1. Explain why the digit representation is so simple. Hint: Where and in which order are numbers defined in ASCII? What happens if you increase the value of a char?
  2. Implement the missing isDigit, isNewline and isOperand.
  3. The code for the input isn't commented, especially this line is missing a comment:

        num[currentNum] = num[currentNum] * 10 + iochar - '0';
    

    What exactly happens there? If num[currentNum] is too complicated for you at the moment just use num1 and print the value before you read the second one. Hint: Have a look at exercise #1.

  4. Even if the operators would be evaluated in the right order (multiplication before addition), the result wouldn't be 6.333333 but 6. Why is that? What would you have to change in your current program?

Zeta
  • 103,620
  • 13
  • 194
  • 236
-3

First, you need to cast the input from "getchar", since it is an ascii input.

    iochar = atoi(getchar());

then you can compare it against an integer value.

Enoban
  • 26
  • 1
  • You need some extra code. Try not to mix logic, I mean, you try to validate an integer value greater than 1 and smaller than 20000, and on the same variable you are comparing against characters. Probably you need a bit more complexity on you logic, depending on what values are you comparing, wether integers or characters. – Enoban Oct 05 '12 at 02:58
  • 1
    The return value of `getchar()` is an `int`, and is not suitable for passing to `atoi()`. – Greg Hewgill Oct 05 '12 at 02:59
  • @GregHewgill the return value of `getchar()` is an `unsigned char` which can be converted to an `int` – Anirudha Oct 05 '12 at 03:12
  • @Anirudha: No, it's [really an `int`](http://en.cppreference.com/w/c/io/getchar). That's so it can return the `EOF` value, which is not a `char`. – Greg Hewgill Oct 05 '12 at 03:19
  • C2011 §7.21.7.1 *fgetc()* _If the end-of-file indicator for the input stream pointed to by stream is not set and a next character is present, the `fgetc` function obtains that character as an `unsigned char` converted to an `int` and advances the associated file position indicator for the stream (if defined). **Returns** If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the `fgetc` function returns EOF. Otherwise, the `fgetc` function returns the next character from the input stream pointed to by stream._ – Jonathan Leffler Oct 05 '12 at 03:24
-3

To start with, return value of getchar is char, promoted to int. So, please use an char variable to store it.

Secondly, to convert the input char to int, use something like:

int num1 = iochar - '0';
Deepanjan Mazumdar
  • 1,447
  • 3
  • 13
  • 20
  • No: the return value from `getchar()` is either the value of a `char` converted to `unsigned char` and then `int` or the value EOF, which is negative and distinct from any other value. You *must* assign to an `int` in order not to get confused by the return value. – Jonathan Leffler Oct 05 '12 at 03:14