Related
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);
}
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.
Here's a question from the last year's first "Intro to programming" exam at my uni:
Using the getchar() function read an input sequence consisting of
numbers, + and - signs. The output should be the result of those
arithmetical operations.
For example, if the input is 10+13-12+25-5+100, the output should be 131.
Now, given that I have a little bit of C experience before attending uni, this problem seems easy to solve using pointers, arrays, etc.
But here's the catch: on the exam you can only use things that the students were taught so far. And given that this exam is only like a month after the start of the school year, your options are fairly limited.
You can only use variables, basic input/output stuff, operators (logical and bitwise), conditional statements and loops, functions.
That means no: arrays, strings, pointers, recursion, structures, or basically any other stuff that makes this easy.
How in the hell do I do this? Today is the second time I've spent 3 hours trying to solve this. I have solved it successfully, but only after "cheating" and using arrays, string functions (strtol), and pointers. It's important for me to know how to solve it by the rules, as I'll have similar stuff on the upcoming exam.
Edit: my attempts so far have amounted to using the while loop combined with getchar() for input, after which I just get stuck. I don't have the slightest idea of what I should do without using more "tools".
The solution is quite simple, but it might not be obvious for a beginner. I will not provide a complete program, but rather outline the steps needed to implement this with only a few variables.
First of all, it's important to notice two things:
Your input can only contain one of -, + or any digit (0123456789).
The getchar() function will read one character of input at a time, and will return EOF when the end of the input is reached or an error occurs.
Now, onto the solution:
Start by reading one character at a time, in a loop. You will only stop if you reach end of input or if an error occurs:
int c;
while ((c = getchar()) != EOF) {
// logic here
}
Start with an accumulator set to 0, and "add" digits to it every time you encounter a digit.
// outside the loop
int acc = 0;
// inside the loop
if (/* c is a digit */)
acc = acc * 10 + (c = '0');
Hint: that /* c is a digit */ condition might not be simple, you can put this in the else of the check for - and +.
Every time you encounter either - or +, remember the operation, and each time you encounter an operator, first perform the previous operation and reset the accumulator.
// outside the loop
int op = 0;
int result = 0;
// inside the loop
if (c == '+' || c == '-') {
if (op) {
// there already is a previous operation to complete, do it
if (op == '+')
result += acc;
else
result -= acc;
} else {
// first operation encountered, don't do anything yet
result = acc;
}
acc = 0; // reset
op = c; // remember the current operation for the future
}
When you reach the end of the input (i.e. you exit the loop), perform the last operation (same logic inside the if from point 3).
Output the result:
You would normally write something like:
printf("%d\n", result);
However, if you cannot use string literals ("%d\n") or the printf() function, you will have to do so manually using putchar(). This is basically the opposite of what we did before to scan numbers into an accumulator.
Print the sign first if needed, and make the value positive:
if (result < 0) {
putchar('-');
result = -result;
}
Find the maximum power of 10 that is lower than your number:
int div = 1;
while (result / div / 10)
div *= 10;
Use the power to extract and print each digit by division and modulo by 10:
while (div) {
putchar('0' + ((result / div) % 10));
div /= 10;
}
Note: the '0' + at the beginning is used to convert digits (from 0 to 10) to the relative ASCII character.
End with a newline:
putchar('\n');
When writing a parser, I typically find myself that I "buffer" the next operation that "will be done". When the input changes state - you are reading digits, but then you read an operation - then you execute the "buffered" action and buffer the next operation that will be done in the future.
Example:
10+13-12
^^ - we read 10
^ - result=10 - we buffer that we *will* have to do + in the future
^^ - reading 13
^ - och we stopped reading numbers!
we execute _buffered_ operation `+` , so we do result += 13
and buffer `-` to be done in the future
^^ - we read 12
^ - och, EOF! we execute buffered operation `-` , so we do result -= 12
- etc.
The code:
#include <stdio.h>
int main() {
int result = 0; // represents current result
int temp = 0; // the temporary number that we read into
int op = 0; // represents the _next_ operation that _will_ be done
while (1) {
int c = getchar();
switch (c) {
// we read an operation, so we should calculate _the previous_ operation
// or this is end of our string
case '+': case '-': case EOF:
if (op == 0) {
// we have nothing so far, so start with first number
result = temp;
} else if (op == '+') {
result += temp;
} else if (op == '-') {
result -= temp;
}
// the next operation we will do in future is stored in op
op = c;
// current number starts from 0
temp = 0;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
// read a digit - increment temporary number
temp *= 10;
temp += c - '0';
break;
}
// we quit here, the result for last operation is calculated above
if (c == EOF) {
break;
}
}
printf("%d\n", result);
// As I see it was mentioned that "%d\n" is a string,
// here's the simplest algorithm for printing digits in a number.
// Extract one digit from the greatest position and continue up
// to the last digit in a number.
// Take negative numbers and throw them out the window.
if (result < 0) {
putchar('-');
result = -result;
}
// Our program currently supports printing numbers up to 10000.
int divisor = 10000;
// 000100 should print as 100 - we need to remember we printed non-zero
int was_not_zero = 0;
while (divisor != 0) {
// extract one digit at position from divisor
int digit = result / divisor % 10;
// if the digit is not zero, or
// we already printed anything
if (digit != 0 || was_not_zero) {
// print the digit
putchar(digit + '0');
was_not_zero = 1;
}
// the next digit will be to the right
divisor /= 10;
}
putchar('\n');
}
#include <string.h>
#include <stdio.h>
void operate(int * sum, int * n, char todo) {
if (todo == 1) *sum += *n;
else if (todo == -1) *sum -= *n;
printf("%s %d\n", todo == 1 ? "ADD :" : "SUB :", *n);
*n = 0;
}
int main()
{
char * problem = "10+13-12+25-5+100";
int len = strlen(problem);
int i=0;
char c;
int n = 0;
int sum = 0;
char todo = 1;
while(i < len)
{
c = problem[i++];
if (c < 48 || c >= 58)
{
// Adds or subtracts previous and prepare next
operate(&sum, &n, todo);
if (c == '+') todo = 1;
else if (c == '-') todo = -1;
}
else
{
// Collects an integer
if (n) n *= 10;
n += c - 48;
}
}
operate(&sum, &n, todo); // Last pass
printf("SUM => %d\n", sum); // => 131
return 0;
}
#include <stdio.h>
void do_operation(char next_operation, int * result, int * number){
if (next_operation == '+'){
*result += *number;
*number = 0;
} else if (next_operation == '-'){
*result -= *number;
*number = 0;
} else {
printf("Unknown operation error.");
}
}
int main(int argc, char *argv[]){
char c;
int number = 0;
int result = 0;
char next_operation = '+';
do {
c = getchar();
if( c >= '0' && c <= '9' ){
number = number * 10 + c - 48;
} else if (c == '+'){
do_operation(next_operation, &result, &number);
next_operation = '+';
} else if (c == '-'){
do_operation(next_operation, &result, &number);
next_operation = '-';
} else {
do_operation(next_operation, &result, &number);
}
} while (c != '\n');
printf("%d", result);
}
First time ever C programming class. I have to create a C calculator using putchar/getchar. The code below if what I have to far and loops to ask the user for input. The issue I am having is how to account for space/multiple spaces before input, space/multiple spaces between the digits and operand, no spaces between operand and digits, and spaces after input by the user is complete.
Right now the code will work with one space between the digits and operand.
Meaning, 10 + 5 works. However, for example, 10+5 does not and ____5 + 10 (where __ = space), or 10+5______, or 10_________+ 10 do not work.
Any advice or help on how to account for multiple spaces in between the digits and operand and before after any user input is so very greatly appreciated.
Thank you so very much for any and all help with the current code. Really do appreciate your help and time!!
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
int add(int input1, char operand, int input2);
int subtract(int input1, char operand, int input2);
int mod(int input1, char operand, int input2);
int multiply(int input1, char operand, int input2);
int divide(int input1, char operand, int input2);
char cont(void);
int main()
{
int answer = 0;
int ch = 0;
int input1 = 0;
char operand = 0;
int input2 = 0;
int function = 0;
char flag;
do {
input1 = 0, input2 = 0, operand = 0;
printf("\nPlease enter a calculation to be made.\n");
while (((ch = getchar()) != ' ') && (ch != EOF) && (ch != '\n')){
if (ch == '-') {
printf("\nError: no negatives allowed.\n");
}
else if (!isdigit(ch)){
printf("\nError: number not inputted (first number).\n");
}
else {
input1 = (input1 * 10) + (ch - '0');
}
}
while (((ch = getchar()) != ' ') && (ch != EOF) && (ch != '\n')){
switch (ch){
case '+':
operand = '+';
break;
case '-':
operand = '-';
break;
case '%':
operand = '%';
break;
case '*':
operand = '*';
break;
case '/':
operand = '/';
break;
default:
printf("Error: input is not one of the allowed operands.");
break;
}
}
while (((ch = getchar()) != ' ') && (ch != '\n')){
if (ch == '-') {
printf("\nError: no negatives allowed.\n");
}
else if (!isdigit(ch)){
printf("\nError: number not inputted (second number).\n");
}
else {
input2 = (input2 * 10) + (ch - '0');
}
}
printf("%d", input1);
putchar(' ');
printf("%c", operand);
putchar(' ');
printf("%d", input2);
putchar(' ');
putchar('=');
putchar(' ');
if (operand == '+'){
answer = add(input1, operand, input2);
printf("%d", answer);
}
else if (operand == '-'){
answer = subtract(input1, operand, input2);
printf("%d", answer);
}
else if (operand == '%'){
answer = mod(input1, operand, input2);
printf("%d", answer);
}
else if (operand == '*'){
answer = multiply(input1, operand, input2);
printf("%d", answer);
}
else if (operand == '/'){
answer = divide(input1, operand, input2);
printf("%d", answer);
}
flag = cont();
}
while (flag == 'y' || flag == 'Y');
return 0;
}
int add(int input1, char operand, int input2){
return input1 + input2;
}
int subtract(int input1, char operand, int input2){
return input1 - input2;
}
int mod(int input1, char operand, int input2){
return input1 % input2;
}
int multiply(int input1, char operand, int input2){
return input1 * input2;
}
int divide(int input1, char operand, int input2){
return input1 / input2;
}
char cont()
{
char flag;
printf("\nDo you want to process another calculation (y/n)? ");
scanf("%c%*c", &flag);
return flag;
}
Ok! the solution to this problem involves understanding how getchar() works. It also includes a concept of how input from standard input [stdin] works.
So, whenever input to variables is taken using scanf()/getchar() etc. either operations are required in order to alert the compiler that the input for the variable is confirmed. One is new line \n(Pressing Enter) and the other is white-space. They will alert that the input is finalized.
This is explained by input 10 + 5 [Press Enter]. The first space ensures ch has values 10 and thus input1 has a value 10. Then + come through and after the space the operand gets the value of +. Later, Enter is pressed after writing 5. This will save value 5 in input2. The rest of the operations happen perfectly.
In other cases where we have so many spaces ____5 + 10 / 10+5______ / 10_________+ 10 we must look at how the code will follow on such input.
_____5+10 The first space will miss the first while loop because space is an exit condition. The control then goes to the second while loop, where second space will also be an exit condition for the loop. The same happens to the third while loop and it also exits. Thus, the answer will be input1 operand input2 and all these have default values i.e. 0, 0 (which is blank when scaled down to character) and 0 respectively.
10+5_____ Here the first space appear after 5, thus, the getchar() will feed input1 with values 10+5and other two variables don't even get assigned.
This shows why the variables couldn't get assigned the values we expected. The solution for this problem can be solved by extra processing but performing checks on how spaces appear.
The following code snippet is a part of the program to evaluate a postfix expression. I am not too much experienced with C programming, so forgive me for my lesser knowledge. I do not understand what the highlighted part of the code is doing.
char str[100];
int i, data = -1, operand1, operand2, result;
/* Get the postfix expression from the user */
printf("Enter ur postfix expression:");
fgets(str, 100, stdin);
for (i = 0; i < strlen(str); i++)
{
if (isdigit(str[i]))
{
/*
* if the i/p char is digit, parse
* character by character to get
* complete operand
*/
data = (data == -1) ? 0 : data;
data = (data * 10) + (str[i] - 48); //What is happening here
continue;
}
It is converting the number in the string str to an actual number, digit per digit (or character per character if you will).
The line
data = (data * 10) + (str[i] - 48);
takes the number "so far" and adds the new digit to it, by multiplying the number by 10 and then adding the value of str[i] to it. The character str[i] is in the range '0' .. '9' and by subtracting 48 of it -- the ASCII value of '0' -- you get the value of the digit.
So if data is 95; for instance, and str[i] is '3', then data becomes 950 + ASCII code of '3' - ASCII code of '0', so data becomes 950 + 3 = 953.
data = (data * 10) + (str[i] - 48);
That line converts the value of str[i] to integer value and converts whole number (hence the multiplication by 10).
E.g.
'0' -> 0
'1' -> 1
E.g."100" -> 100
It assumes ASCII representation and hence uses 48. A more portable way would be to use '0' instead:
data = (data * 10) + (str[i] - '0');
According to your code snippet
**data = (data * 10) + (str[i] - 48);
this line will change your string to integer format
for example like you are giving input 235
then ASCII code of 2 is 50 and when you subtract with 48 then it will come 2.
now multiply you previous no (which is 0) by 10 and add 2. then it will become 2
next 3 will come which is having 51 ASCII and after subtract 48 will become 3
now multiply you previous no (which is 2) by 10 and add 3. then it will become 23 and so on.
like this you are converting string to an integer no.
For the better understanding print your values that is been generated at the intermediate instance since your not too much experienced in C Program have a printf statement so that you can understand the logic.
#include <stdio.h>
#include <string.h>
#include<ctype.h>
#include<conio.h>
int top = -1;
int stack[100];
/* push the given data into the stack */
void push (int data) {
stack[++top] = data;
}
/* Pop the top element from the stack */
int pop () {
int data;
if (top == -1)
return -1;
data = stack[top];
stack[top] = 0;
top--;
return (data);
}
int main() {
char str[100];
int i, data = -1, operand1, operand2, result;
/* Get the postfix expression from the user */
printf("Enter ur postfix expression:");
fgets(str, 100, stdin);
for (i = 0; i < strlen(str); i++) {
if (isdigit(str[i])) {
/*
* if the i/p char is digit, parse
* character by character to get
* complete operand
*/
data = (data == -1) ? 0 : data;
printf("%d value of str[i] ",str[i]); // returns the ascii value
data = (data * 10) + (str[i] - 48); //multiplies with ten and substracts with 48 so thst u get ur input number
printf("%d\n",data);
continue;
}
if (data != -1) {
/* if the i/p is operand, push it into the stack */
push(data);
}
if (str[i] == '+' || str[i] == '-'
|| str[i] == '*' || str[i] == '/') {
/*
* if the i/p is an operator, pop 2 elements
* from the stack and apply the operator
*/
operand2 = pop();
operand1 = pop();
if (operand1 == -1 || operand2 == -1)
break;
switch (str[i]) {
case '+':
result = operand1 + operand2;
/* push the result into the stack */
push(result);
break;
case '-':
result = operand1 - operand2;
push(result);
break;
case '*':
result = operand1 * operand2;
push(result);
break;
case '/':
result = operand1 / operand2;
push(result);
break;
}
}
data = -1;
}
if (top == 0)
printf("Output:%d\n", stack[top]);
else
printf("u have given wrong postfix expression\n");
getch();
return 0;
}
output:
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;
}
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.
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;
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.
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?
Implement the missing isDigit, isNewline and isOperand.
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.
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?
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.
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';