Variable length arithmetic calculator WITHOUT using strings? - c

I'm trying to create a calculator that solves arithmetic expressions of different lengths (e.g. 2+3/4 or 7*8/2+12-14), and I was wondering if it was possible to do so without the use of strings.
I've found countless tutorials explaining how to make a simple calculator with only two numbers and an operator, and I've also found examples using sscanf and strings to get the input.
However, my question is: Is there a way (is it even possible) to get variable length inputs without using strings?
At first I thought i could simply add more specifiers:
int num1 , num2, num3;
char op1, op2;
printf("Please enter your equation to evaluate: ");
scanf("%d%c%d%c%d", &num1, &op1, &num2, &op2, &num3);
but obviously, that doesn't work for equations longer than 3 numbers or less than 3 numbers.
I was also thinking of perhaps using some sort of recursive function, but I'm not sure how I would do that if I need to ask for the entire equation up front?

If you intend to read ASCII from user input, or from command line arguments, then you're pretty inescapably in the world of strings. What you can do is convert them into something else as early as possible.
You could abandon ASCII altogether and define a binary file format.
For example, you might say that each pair of two bytes is a token. The first byte is an element type ( signed integer, unsigned integer, float, operator), the second byte is the value.
Pseudocode:
while(!done) {
int type = read(f);
int value = read(f);
switch(type) {
case TYPE_INTEGER:
push_to_stack(value);
break;
case TYPE_FLOAT:
push_to_stack_as_float(value);
break;
case TYPE_OPERATOR:
execute_operator(value);
break;
}
}
Quite why you would force yourself down this route, I don't know. You'd probably find yourself wanting to write a program to convert ASCII input into your binary file format; which would use strings. So why did you run away from strings in the first place?

you can create a list of struct, every struct will have to contains a value OR a sub list, an operator (char?) and a reference to the next (and or before) char.
Then you just ask the user for a number (or "("/")"), and a operator sign. Every number + operator is a new element in list, every ( is a sub list, every ) is a return to superior list (you can even don't create a sublist, but elaborate it on the fly and return just the result, like a recursive function)
Also struct and code can be elaborated to support multiple parameter.

Related

What does items[(int)(type - '1')] mean in this printf statement?

I have an array
char type;
char items[3][15] = {"Fish", "Beef", "Veggie"};
And this as a menu
printf("1. Fish – $5 \n");
printf("2. Beef – $10\n");
printf("3. Veggie – $15 \n");
With a printf statement as follows
printf("\nYou've selected %s \n", items[(int)(type - '1')]);
I found this being done on a completely different type of question but don't really understand what the items[(int)(type - '1')] is doing in my code. It just seems to works.
items[…] is subsetting the array items.
(int)(type - '1') is calculating the index to use for subsetting.
(int)(…) is a cast to int. It’s worth noting that this cast is completely unnecessary here: the result of subtracting two character values (or an integer from a character) already yields the type int in C due to integer promotion. This means that we can rewrite the expression to
items[type - '1']
Lastly, type - '1' subtracts the numeric character code of the character constant '1' from the numeric character code of the value in variable type. The result of this transformation is that if type is '1', the value of type - '1' is 0, if type is '2' the value is 1, and so on.
Alternatively, the code could be implemented as follows:
char type_str[2] = { type };
int choice = atoi(type_str) - 1;
printf("\nYou've selected %s\n", items[choice]);
This makes it perhaps slightly clearer that we’re translating a character value into an integer value. However, it’s actually a much more complex implementation:
we first need to construct a string from the character (by assigning it into an array and zero-terminating the string, which happens implicitly in the initialisation of type_str above)
then we invoke atoi to translate "1" into 1, "2" into 2, …
the we subtract 1, to get a zero-based index.
In the end, this isn’t more readable or less error-prone — neither for beginners nor for expert C programmers.
In a more realistic application, it’s conceivable that the user input was directly a string rather than a character, which makes the application of atoi more useful. We’d also potentially want to handle errors (what happens if the user entered an invalid value? The current code — both mine and the one you posted — happily attempt to subset the array after an invalid input, with potentially bad consequences).

Searching for all integers that occure twice in a vector

I got the task in university to realize an input of a maximum of 10 integers, which shall be stored in a one dimensional vector. Afterwards, every integer of the vector needs to be displayed on the display (via printf).
However, I don't know how to check the vector for each number. I thought something along the lines of letting the pointer of the vector run from 0 to 9 and comparing the value of each element with all elements again, but I am sure there is a much smarter way. I don't in any case know how to code this idea since I am new to C.
Here is what I have tried:
#include <stdio.h>
int main(void)
{
int vector[10];
int a;
int b;
int c;
a = 0;
b = 0;
c = 0;
printf("Please input 10 integers.\n\n");
while (a <= 10);
{
for (scanf_s("%lf", &vektor[a]) == 0)
{
printf("This is not an integer. Please try again.\n");
fflush(stdin);
}
a++;
}
for (b <= 10);
{
if (vector[b] != vector[c]);
{
printf("&d", vector[b]);
c++;
}
b++;
}
return 0;
}
Your code has several problems, some syntactic and some semantic. Your compiler will help with many of the former kind, such as
misspelling of variable name vector in one place (though perhaps this was a missed after-the-fact edit), and
incorrect syntax for a for loop
Some compilers will notice that your scanf format is mismatched with the corresponding argument. Also, you might even get a warning that clues you in to the semicolons that are erroneously placed between your loop headers and their intended bodies. I don't know any compiler that would warn you that bad input will cause your input loop to spin indefinitely, however.
But I guess the most significant issue is that the details of your approach to printing only non-duplicate elements simply will not serve. For this purpose, I recommend figuring out how to describe in words how the computer (or a person) should solve the problem before trying to write C code to implement it. These are really two different exercises, especially for someone whose familiarity with C is limited. You can reason about the prose description without being bogged down and distracted by C syntax.
For example, here are some words that might suit:
Consider each element, E, of the array in turn, from first to last.
Check all the elements preceding E in the array for one that contains the same value.
If none of the elements before E contains the same value as E then E contains the first appearance of its value, so print it. Otherwise, E's value was already printed when some previous element was processed, so do not print it again.
Consider the next E, if any (go back to step 1).

Converting a result of Integer to String or Word in C

so i have a problem here. I am working on my class assignment which is create a calculator but every result must be in a word, example :
int a,b,c;
printf("Input first number:");
scanf("%d", &a);
printf("Input second number:"):
scanf("%d", &b);
c=a+b;
printf("The result are: %d", c);
printf("If in words, it is = ");
switch(c){
case 0:printf("abcdef");break;
case 1:printf("bc");break;
case 2:printf("abged");break;
case 3:printf("abgcd");break;
case 4:printf("fbgc");break;
case 5:printf("afgod");break;
case 6:printf("fgcde");break;
case 7:printf("abc");break;
case 8:printf("abcdefg");break;
case 9:printf("abcdfg");break;
default :printf("error");break;
So the result from this when im running it is :
Input first number : 12
input second number : 12
The result are: 24
If in words, it is = error
so what I'm confused here is how I did print the c result as a word? so what i want from my output is
Input first number : 12
input second number : 12
The result are : 24
If in words, it is = abged fbcg
so far I'm searching for answers but I cannot find it. If anyone here can help me, please do.
Thanks in advance
*edited
what i want from my output is
Input first number : 12
input second number : 12
The result are : 24
If in words, it is = abged fbcg
The question would be much clearer if you had written "two four" instead of "abged fbcg"...
You apparently want to print the "tens" and the "ones" separately. (Probably the "hundreds" as well.)
As this is a homework assignment, I will only give you some hints instead of a complete solution:
If you divide c by 10, you get the "tens". If you divide that result by 10 again, you get the "hundreds".
If something like "two four" would be acceptable, you can use the same lookup for "tens" and "ones". If you actually need "twenty four", you need a lookup for "tens" and a different one for "ones".
You need to print the words for the highest-order (leftmost) digit first, but you get it last from the by-10 divisions I mentioned above. So you need to "store" the lookup result for "ones" somewhere while you do the lookup for "tens" (and, perhaps, "hundreds"). Storage could be...
...an array. Be careful to check the numbers entered against the space in the array (so you don't overflow if someone enters too-large numbers). If you do it right, you do not need to store the strings you looked up, as you could store pointers to those strings.
...a recursive function. (One that calls itself with the value divided by 10, then does the lookup for the "ones" of the value it was called with -- you get that via the modulo operator, c % 10.)
The first problem here, you missed to use the break statement after each case statement.
Hence, yours is a fall-through switch case, which is not what you want. It will jump to the case matching in switch statement and then fall-thorough all other available case statements.
Once you have solved that problem, one of the possible the approach to target the next problem is to explain it properly, with the current description, it's not very clear.
Use a lookup for all the options of this word and then print the relevant according to the index without all the switch case mess
char* lookup = {
{"abcdef\n"},
{"bc\n"},
{"abged\n"},
{"abgcd\n"},
{"fbgc\n"},
{"afgod\n"},
{"fgcde\n"},
{"abc\n"},
{"abcdefg\n"},
{"abcdfg\n"},
};
then==>
c=a+b;
if (c>9)
{
printf("error\n");
}
else
{
printf(lookup[c]);
}
ok, so you mean you want to print a string for each digit of a number, which is the result of whatever math function?
Try [untested]
int d = c;
do {
switch (d % 10) { /* your replacement-text-switch goes here */ }
d /= 10;
} while (d != 0)
This will print out the number in reverse.
If you want to print it out the other way, then you have to know about the maximum number you are going to calculate. (Or, being advanced you can use logarithm to determine the length of a number.)

How to get and evaluate the Expressions from a string in C

How to get and evaluate the Expressions from a string in C
char *str = "2*8-5+6";
This should give the result as 17 after evaluation.
Try by yourself. you can Use stack data structure to evaluate this string here is reference to implement (its in c++)
stack data structre for string calcualtion
You have to do it yourself, C does not provide any way to do this. C is a very low level language. Simplest way to do it would be to find a library that does it, or if that does not exist use lex + yacc to create your own interpreter.
A quick google suggests the following:
http://www.gnu.org/software/libmatheval/
http://expreval.sourceforge.net/
You should try TinyExpr. It's a single C source code file (with no dependencies) that you can add to your project.
Using it to solve your problem is just:
#include <stdio.h>
#include "tinyexpr.h"
int main()
{
double result = te_interp("2*8-5+6", 0);
printf("Result: %f\n", result);
return 0;
}
That will print out: Result: 17
C does not have a standard eval() function.
There are lots of libraries and other tools out there that can do this.
But if you'd like to learn how to write an expression evaluator yourself, it can be surprisingly easy. It is not trivial: it is actually a pretty deeply theoretical problem, because you're basically writing a miniature parser, perhaps built on a miniature lexical analyzer, just like a real compiler.
One straightforward way of writing a parser involves a technique called recursive descent. Writing a recursive descent parser has a lot in common with another great technique for solving big or hard problems, namely by breaking the big, hard problem up into smaller and hopefully easier subproblems.
So let's see what we can come up with. We're going to write a function int eval(const char * expr) that takes a string containing an expression, and returns the int result of evaluating it. But first let's write a tiny main program to test it with. We'll read a line of text typed by the user using fgets, pass it to our expr() function, and print the result.
#include <stdio.h>
int eval(const char *expr);
int main()
{
char line[100];
while(1) {
printf("Expression? ");
if(fgets(line, sizeof line, stdin) == NULL) break;
printf(" -> %d\n", eval(line));
}
}
So now we start writing eval(). The first question is, how will we keep track of how how far we've read through the string as we parse it? A simple (although mildly cryptic) way of doing this will be to pass around a pointer to a pointer to the next character. That way any function can move forwards (or occasionally backwards) through the string. So our eval() function is going to do almost nothing, except take the address of the pointer to the string to be parsed, resulting in the char ** we just decided we need, and calling a function evalexpr() to do the work. (But don't worry, I'm not procrastinating; in just a second we'll start doing something interesting.)
int evalexpr(const char **);
int eval(const char *expr)
{
return evalexpr(&expr);
}
So now it's time to write evalexpr(), which is going to start doing some actual work. Its job is to do the first, top-level parse of the expression. It's going to look for a series of "terms" being added or subtracted. So it wants to get one or more subexpressions, with + or - operators between them. That is, it's going to handle expressions like
1 + 2
or
1 + 2 - 3
or
1 + 2 - 3 + 4
Or it can read a single expression like
1
Or any of the terms being added or subtracted can be a more-complicated subexpression, so it will also be able to (indirectly) handle things like
2*3 + 4*5 - 9/3
But the bottom line is that it wants to take an expression, then maybe a + or - followed by another subexpression, then maybe a + or - followed by another subexpression, and so on, as long as it keeps seeing a + or -. Here is the code. Since it's adding up the additive "terms" of the expression, it gets subexpressions by calling a function evalterm(). It also needs to look for the + and - operators, and it does this by calling a function gettok(). Sometimes it will see an operator other than + or -, but those are not its job to handle, so if it sees one of those it "ungets" it, and returns, because it's done. All of these functions pass the pointer-to-pointer p around, because as I said earlier, that's how all of these functions keep track of how they're moving through the string as they parse it.
int evalterm(const char **);
int gettok(const char **, int *);
void ungettok(int, const char **);
int evalexpr(const char **p)
{
int r = evalterm(p);
while(1) {
int op = gettok(p, NULL);
switch(op) {
case '+': r += evalterm(p); break;
case '-': r -= evalterm(p); break;
default: ungettok(op, p); return r;
}
}
}
This is some pretty dense code, Stare at it carefully and convince yourself that it's doing what I described. It calls evalterm() once, to get the first subexpression, and assigns the result to the local variable r. Then it enters a potentially infinite loop, because it can handle an arbitrary number of added or subtracted terms. Inside the loop, it gets the next operator in the expression, and uses it to decide what to do. (Don't worry about the second, NULL argument to gettok; we'll get to that in a minute.)
If it sees a +, it gets another subexpression (another term) and adds it to the running sum. Similarly, if it sees a -, it gets another term and subtracts it from the running sum. If it gets anything else, this means it's done, so it "ungets" the operator it doesn't want to deal with, and returns the running sum -- which is literally the value it has evaluated. (The return statement also breaks the "infinite" loop.)
At this point you're probably feeling a mixture of "Okay, this is starting to make sense" but also "Wait a minute, you're playing pretty fast and loose here, this is never going to work, is it?" But it is going to work, as we'll see.
The next function we need is the one that collects the "terms" or subexpressions to be added (and subtracted) together by evalexpr(). That function is evalterm(), and it ends up being very similar -- very similar -- to evalexpr. Its job is to collect a series of one or more subexpressions joined by * and/or /, and multiply and divide them. At this point, we're going to call those subexpressions "primaries". Here is the code:
int evalpri(const char **);
int evalterm(const char **p)
{
int r = evalpri(p);
while(1) {
int op = gettok(p, NULL);
switch(op) {
case '*': r *= evalpri(p); break;
case '/': r /= evalpri(p); break;
default: ungettok(op, p); return r;
}
}
}
There's actually nothing more to say here, because the structure of evalterm ends up being exactly like evalexpr, except that it does things with * and /, and it calls evalpri to get/evaluate its subexpressions.
So now let's look at evalpri. Its job is to evaluate the three lowest-level, but highest-precedence elements of an expression: actual numbers, and parenthesized subexpressions, and the unary - operator.
int evalpri(const char **p)
{
int v;
int op = gettok(p, &v);
switch(op) {
case '1': return v;
case '-': return -evalpri(p);
case '(':
v = evalexpr(p);
op = gettok(p, NULL);
if(op != ')') {
fprintf(stderr, "missing ')'\n");
ungettok(op, p);
}
return v;
}
}
The first thing to do is call the same gettok function we used in evalexpr and evalterm. But now it's time to say a little more about it. It is actually the lexical analyzer used by our little parser. A lexical analyzer returns primitive "tokens". Tokens are the basic syntactic elements of a programming language. Tokens can be single characters, like + or -, or they can also be multi-character entities. An integer constant like 123 is considered a single token. In C, other tokens are keywords like while, and identifiers like printf, and multi-character operators like <= and ++. (Our little expression evaluator doesn't have any of those, though.)
So gettok has to return two things. First it has to return a code for what kind of token it found. For single-character tokens like + and - we're going to say that the code is just the character. For numeric constants (that is, any numeric constant), we're going to say that gettok is going to return the character 1. But we're going to need some way of knowing what the value of the numeric constant was, and that, as you may have guessed, is what the second, pointer argument to the gettok function is for. When gettok returns 1 to indicate a numeric constant, and if the caller passes a pointer to an int value, gettok will fill in the integer value there. (We'll see the definition of the gettok function in a moment.)
At any rate, with that explanation of gettok out of the way, we can understand evalpri. It gets one token, passing the address of a local variable v in which the value of the token can be returned, if necessary. If the token is a 1 indicating an integer constant, we simply return the value of that integer constant. If the token is a -, this is a unary minus sign, so we get another subexpression, negate it, and return it. Finally, if the token is a (, we get another whole expression, and return its value, checking to make sure that there's another ) token after it. And, as you may notice, inside the parentheses we make a recursive call back to the top-level evalexpr function to get the subexpression, because obviously we want to allow any subexpression, even one containing lower-precedence operators like + and -, inside the parentheses.
And we're almost done. Next we can look at gettok. As I mentioned, gettok is the lexical analyzer, inspecting individual characters and constructing full tokens from them. We're now, finally, starting to see how the passed-around pointer-to-pointer p is used.
#include <stdlib.h>
#include <ctype.h>
void skipwhite(const char **);
int gettok(const char **p, int *vp)
{
skipwhite(p);
char c = **p;
if(isdigit(c)) {
char *p2;
int v = strtoul(*p, &p2, 0);
*p = p2;
if(vp) *vp = v;
return '1';
}
(*p)++;
return c;
}
Expressions can contain arbitrary whitespace, which is ignored, so we skip over that with an auxiliary function skipwhite. And now we look at the next character. p is a pointer to pointer to that character, so the character itself is **p. If it's a digit, we call strtoul to convert it. strtoul helpfully returns a pointer to the character following the number it scans, so we use that to update p. We fill in the passed pointer vp with the actual value strtoul computed for us, and we return the code 1 indicating an integer constant.
Otherwise -- if the next character isn't a digit -- it's an ordinary character, presumably an operator like + or - or punctuation like ( ), so we simply return the character, after incrementing *p to record the fact that we've consumed it. Properly "incrementing" p is mildly tricky: it's a pointer to a pointer, and we want to increment the pointed-to pointer. If we wrote p++ or *p++ it would increment the pointer p, so we need (*p)++ to say that it's the pointed-to pointer that we want to increment. (See also C FAQ 4.3.)
Two more utility functions, and then we're done. Here's skipwhite:
void skipwhite(const char **p)
{
while(isspace(**p))
(*p)++;
}
This simply skips over zero or more whitespace characters, as determined by the isspace function from <ctype.h>. (Again, we're taking care to remember that p is a pointer-to-pointer.)
Finally, we come to ungettok. It's a hallmark of a recursive descent parser (or, indeed, almost any parser) that it has to "look ahead" in the input, making a decision based on the next token. Sometimes, however, it decides that it's not ready to deal with the next token after all, so it wants to leave it there on the input for some other part of the parser to deal with later.
Stuffing input "back on the input stream", so to speak, can be tricky. This implementation of ungettok is simple, but it's decidedly imperfect:
void ungettok(int op, const char **p)
{
(*p)--;
}
It doesn't even look at the token it's been asked to put back; it just backs the pointer up by 1. This will work if (but only if) the token it's being asked to unget is in fact the most recent token that was gotten, and if it's not an integer constant token. In fact, for the program as written, and as long as the expression it's parsing is well-formed, this will always be the case. It would be possible to write a more complicated version of gettok that explicitly checked for these assumptions, and that would be able to back up over multi-character tokens (such as integer constants) if necessary, but this post has gotten much longer than I had intended, so I'm not going to worry about that for now.
But if you're still with me, we're done! And if you haven't already, I encourage you to copy all the code I've presented into your friendly neighborhood C compiler, and try it out. You'll find, for example, that 1 + 2 * 3 gives 7 (not 9), because the parser "knows" that * and / have higher precedence than + and -. Just like in a real compiler, you can override the default precedence using parentheses: (1 + 2) * 3 gives 9. Left-to-right associativity works, too: 1 - 2 - 3 is -4, not +2. It handles plenty of complicated, and perhaps surprising (but legal) cases, too: (((((5))))) evaluates to just 5, and ----4 evaluates to just 4 (it's parsed as "negative negative negative negative four", since our simplified parser doesn't have C's -- operator).
This parser does have a pretty big limitation, however: its error handling is terrible. It will handle legal expressions, but for illegal expressions, it will either do something bizarre, or just ignore the problem. For example, it simply ignores any trailing garbage it doesn't recognize or wasn't expecting -- the expressions 4 + 5 x, 4 + 5 %, and 4 + 5 ) all evaluate to 9.
Despite being somewhat of a "toy", this is also a very real parser, and as we've seen it can parse a lot of real expressions. You can learn a lot about how expressions are parsed (and about how compilers can be written) by studying this code. (One footnote: recursive descent is not the only way to write a parser, and in fact real compilers will usually use considerably more sophisticated techniques.)
You might even want to try extending this code, to handle other operators or other "primaries" (such as settable variables). Once upon a time, in fact, I started with something like this and extended it all the way into an actual C interpreter.

Goldbach theory in C

I want to write some code which takes any positive, even number (greater than 2) and gives me the smallest pair of primes that sum up to this number.
I need this program to handle any integer up to 9 digits long.
My aim is to make something that looks like this:
Please enter a positive even integer ( greater than 2 ) :
10
The first primes adding : 3+7=10.
Please enter a positive even integer ( greater than 2 ) :
160
The first primes adding : 3+157=160.
Please enter a positive even integer ( greater than 2 ) :
18456
The first primes adding : 5+18451=18456.
I don't want to use any library besides stdio.h. I don't want to use arrays, strings, or anything besides for the most basic toolbox: scanf, printf, for, while, do-while, if, else if, break, continue, and the basic operators (<,>, ==, =+, !=, %, *, /, etc...).
Please no other functions especially is_prime.
I know how to limit the input to my needs so that it loops until given a valid entry.
So now I'm trying to figure out the algorithm.
I thought of starting a while loop like something like this:
#include <stdio.h>
long first, second, sum, goldbach, min;
long a,b,i,k; //indices
int main (){
while (1){
printf("Please enter a positive integer :\n");
scanf("%ld",&goldbach);
if ((goldbach>2)&&((goldbach%2)==0)) break;
else printf("Wrong input, ");
}
while (sum!=goldbach){
for (a=3;a<goldbach;a=(a+2))
for (i=2;(goldbach-a)%i;i++)
first = a;
for (b=5;b<goldbach;b=(b+2))
for (k=2;(goldbach-b)%k;k++)
sum = first + second;
}
}
Have a function to test primality
int is_prime(unsigned long n)
And then you only need to test whether a and goldbach - a are both prime. You can of course assume a <= goldbach/2.
And be sure to handle goldbach = 4 correctly.
If the requirements don't allow defining and using your own functions, ignore them first. Solve the problem using any functions you deem helpful and convenient. When you have a working solution using disallowed functionality, then you start replacing that with allowed constructs. Self-defined functions can be inlined directly, replacing the return with an assignment, so instead of if (is_prime(a)), you have the code to determine whether a is prime and instead of returning the result you assign it is_prime = result; and test that variable if (is_prime). Where you have used library functions, reimplement them yourself - efficiency doesn't matter much - and then inline them too.

Resources