calculator in C - input a whole formula - c

I'm trying to code a calculator in C, and want to make one that can calculate a multiple inputs, eg, (5*9 + 1 -2). These inputs can be completely random and I'm stuck on how to do this.
I know how to initialize a variable, and ask the user input a number and all that, but if the user wanted to add up 50 random numbers, that calculator wouldn't be able to do that.
Hope you can help, or share some tips
Thanks !

You will need to implement an expression parser that will take operator precedence into account. To me the two simplest ways to do this would be to either implement a recursive decent parser or to implement the Shunting yard algorithm.
See this for an example.

In order to do this, you need to read the entire line (it shouldn't be too hard),
then you need to parse it and store it into some data structures.
Here are two ways I know to store and use it :
The first one : it's easy to do, easy to use, but not beautiful nor fast :
A double linked-list with each link containing an operator or a number and a priority if it's an operator (you can use an enum + union if you want something cleaner):
struct list {
struct list *prev;
struct list *next;
char operator;
int number;
unsigned int priority;
}
You loop trough your string and apply an easy algorithm for priority (pseudocode):
var priority = 0
var array = cut string // ["5", "+", "3", "*", "(", "6", "-", "2", ")"]
check string // verify the string is correct
for each element of array :
if (element is number)
store in list
else if (element is operator)
store in list
if (element is '*' or '/' or '%')
set his priority to priority + 1
else
set his priority to priority
else if (element is open parenthesis)
priority += 2
else if (element is close parenthesis)
priority -= 2
For example :
string:
5 + 3 * (6 - 2) - 1
priorities:
0 1 2 0
Then, to do your calculations :
while list isn't empty:
find operator with the highest priority // if there is more than one, take the first
calculate this operator // with the element prev and next
replace by result in list // operator, but also prev and next
An example, again, with 5 + 3 * (6 - 2) - 1 :
first iteration:
5 + 3 * 4 - 1
then
5 + 12 - 1
then
17 - 1
then
16
The other (and better, even though it is a little bit harder if you're not familiar with recursion) one : A binary tree using the reverse polish notation
(see here and here)
This one is more common, so I won't explain it.

You can use a string when you read and divide that string when you find {+,-,*,/}. And what you find between them are your numbers.
Try to add your code!
Good luck!

It's not a complete solution but hey it's something...
try this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE (1000)
static char tempNumStr[50] = {0};
static double parsedDoubleArr[5] = {0};
static char parsedOperators[5] = {0};
void flushTempArr(char tmpArr[50]){
for(int i=0; i< 50; i++)
tmpArr[i] = 0 ;
}
int tempNumStrIterator=0;
int parsedDoubleArrIterator=0;
int parsedOperatorsIterator=0;
int main(void)
{
char operator;
char sourceStr[] = "(17.5 + 8)";
for(int i = 0; sourceStr[i] != '\0'; ++i) /*iterate over string till \0 */
{
if (IsDigit(sourceStr[i]))
{
while(sourceStr[i] != '\0' && IsDigit(sourceStr[i]))
{
tempNumStr[tempNumStrIterator++] = sourceStr[i];
++i;
}
sscanf(tempNumStr, "%lf", &parsedDoubleArr[parsedDoubleArrIterator++]);
flushTempArr(tempNumStr);
tempNumStrIterator = 0;
}
if (IsCalcOperator(sourceStr[i]))
{
parsedOperators[parsedOperatorsIterator++] = sourceStr[i];
}
else if (IsBracket(sourceStr[i]))
{
//do something
continue;
}
}
//do what you want with parsedDoubleArr and parsedOperators
return EXIT_SUCCESS;
}

Related

Access and store value by index in a pointer

I've got an assignment where I have to sum whole numbers up to 100 digits.
They gave me this struct to represent big numbers (I think there are better ways to represent this, but I'm not allowed to modify it):
typedef struct {
char* string;
int lengthError;
} BigNumber;
Where string is the number itself and lengthError is the length of the number or an error that is a previously defined enum.
I've also have the implementation of the sum function
BigNumber *sum(BigNumber* num1, BigNumber* num2) {
BigNumber* result = malloc(sizeof(BigNumber));
int limit = getLength(num1->lengthError, num2->lengthError);
result->string = malloc(limit);
int digitResult;
int index = limit -1;
int carry = 0;
while(index != -1) {
int d1 = ((int)num1->string[index]) - ((int)'0');
int d2 = ((int)num2->string[index]) - ((int)'0');
digitResult = d1 + d2 + carry;
if (digitResult > 9) {
digitResult = digitResult - 10;
carry = 1;
} else {
carry = 0;
}
itoa(digitResult, &result->string[index], 10); //I think this is the problem
index--;
}
result->string[limit] = '\0';
printf("result: %s\n", result->string);
return result;
}
I haven't finished writing that function, I know there are a lot of flaws in it, but the problem is that I can't get to sum 12 + 12. The result I get is 2.
I thought approaching this problem by picking the lasts character of both numbers, transform them into an int and sum them having in mind the carry digit. After I got the result in digitResult I try to convert it to a char and store it in the corresponding position of the result->string pointer
Once it has finished the operation, I add an \0 at the last position of the result->string.
So the question is, how do I make this operation to work as desired? Debugging the code, I noticed that the first time it stores the first result in result->string, following the example above this would be a number 4, it stores trash in that position instead. In the second addition, I store a number 2 correctly and that's the final result I get in when I print the result.
Your use of the itoa function is a problem (though, as you have also suggested, maybe not the only one).
The itoa function converts its first argument into a null-terminated string - so, as well as writing the character representation of digitResult at the indicated place in the string, it also adds a '\0' character after it. Thus, your string will always be terminated immediately after the last digit you write, and 12 + 12, giving 24 will appear to be just the first character: 2.
What you can do instead is to convert the digit yourself (reversing the operation you used to get the d1 and d2 values), then just directly set the string element to the converted digit.
So, instead of:
itoa(digitResult, &result->string[index], 10);
use:
result->string[index] = (char)(digitResult + '0');

6-bit binary counter in C (compiles, but then Windows encounters error) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am extremely new to C and trying to make a 6-bit binary counter, where each return has all 6 digits listed (i.e 000000, 000001,...). Currently, my solution compiles but does not execute once compiled (I get a warning that says something to the effect of "A problem caused Windows to stop working" and then no output is displayed). If anyone could help figure out why this happens, or suggest a better way to do this since I know my approach is extremely convoluted, I'd appreciate the help!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
long * convert(long dec){
if(dec == 0){
return 0;
}else{
return(long *)(dec % 2 + (10 * *convert(dec / 2)));
}
}
char* long_enough(char* num){
char* have_one = "0000";
char* have_two = "0000";
char* have_three = "000";
char* have_four = "00";
char* have_five = "0";
if(strlen(num) == 2){
strcat(have_one, num);
}else if(strlen(num) == 3){
strcat(have_two, num);
}else if(strlen(num) == 4){
strcat(have_three, num);
}else if(strlen(num) == 5){
strcat(have_four, num);
}else if(strlen(num) == 6){
strcat(have_five, num);
}
}
char main(){
int i;
int count = -1;
printf("\n");
for(i = 0; i < 5; i++){
count++;
long* binNum = (long *)(convert(count));
char* new;
char done = sprintf(new, "%d", binNum);
long_enough((char *)(intptr_t)done);
printf("%s\n", long_enough((char *)(intptr_t)done));
}
}
I think it has to do with your handling of pointers. #Pete Becker suggestion should get get you started but what also jumped out at me was this line:
return(long *)(dec % 2 + (10 * *convert(dec / 2)));
Here you are multiplying by the raw memory of the convert function result. If your intent is to raise to a power, note that there is no exponent operator in C. Do raise to a power, you'll need to #include <math.h> and use the pow(x,e) function.
You'll definitely want to read up on the pointer and value semantics in C. I'd recommend the book The C Programming Language by Brian W. Kernighan & Dennis M. Ritchie (the creators of the language). It is concise and will likely get you further, faster than a lot of the other books out there.
Are you using a long* to point nowhere?
It makes no sense. A pointer is meant to point to a memmory region and this memory region must have been allocated (either stack or heap).
It makes no sense that you are multiplying a binary number by 10 either.
You need to clarify your thought.
When you say you are making a "binary counter", think first about what it means. Given the code you posted, it looks like you should split your problem in two parts:
Count in binary.
Show the value in a human readable manner.
Once you've splitted the problem in two, I'll help you with one and let the other on your own.
Convert a number into binary:
Well, computer numbers are already binary by construction. Let's suppose you need, for any didactic reason, to reinvent the wheel in such a way that you can address individual values.
You have basically two options: use an array or use a bit-mask.
By using an array you'll waste more memory but printing the result will be easier.
By using a bit-mask you basically will have to allocate a single integer (or even char since you just need 6 bits) and shift it left while testing the original number.
// Example using bit-masks / bit-shifts into an uchar.
unsigned char to_bin6( unsigned int number )
{
unsigned char bin6 = 0;
// Left align and Clear out extra bits since we only care about the lowest 6.
number <<= ( 8 * sizeof( unsigned int ) ) - 6;
for ( int count = 6; count; --count )
bin6 <<= number;
return bin6;
}
Now with arrays.
// Example using char array.
// Array needs to have an additional element for the EoS (end of string) marker.
void to_bin6( unsigned int number, unsigned char bin6[ 7 ] )
{
// Fills the output buffer in the same direction you'd expect to read.
for ( int count = 5; count >= 0; --count )
bin6[ count ] = ( number & ( 1 << count ) ) ?
'1' : '0'; // Feeds character '1' or '0' according to bit value.
bin6[ 6 ] = '\0'; // EoS: Note this is NOT the same as '0'.
}
Show a number as binary for human reading:
That's the part I'll leave for you.
Hint: using array it is very easy.
Tell me if you need more.

Finding derivative of a function stored in a character array

What I need to do is read a file which contains equations. I need to take the derivative of each equation and then write those derivative equations in a different .txt file. I've read all the equations into an array of character arrays and now I don't know what to do once I've stored them into the array. I really don't need help writing the equations into another file; I know I can figure that out.
What I need help on is finding a way to taking the derivative of the functions. The type of equations that are going to be read are not that complicated; they're going to be polynomials that don't need the chain rule or quotient rule. There will be, however, sin x, cos x and tan x. Some sample equations that would be read are.
-2x^2+2x-3
-2x+sinx-3
-x+sin2x-tanx
The trig functions will not have parenthesis and the variable will always be "x".
I just need a push in the right direction, please.
What you're really asking for is a parser.
A parser is basically a set of rules to read those equations and change/read (parse) each of them.
I'd try to iterate over each line of the file, and differentiate it considering you have a specific character set (i.e ^ means power, x is the parameter, etc.);
For example, some pseudo code:
Open the file.
While there's lines to read:
Read a line -
Seperate it by the operands (+,-,/,*)
For each part:
Find the power of x,
Reduce it by one,
...(derivating rules) // no way around, you have to implement each function if you want this to work as others mentioned in the comments.
Reconnect the parts into a string,
Add it to a list.
Print each element of the list.
If you need help translating that into C, just ask for it; I'll happily help you.
What you need to do, by the looks of things, is separate the expression into individual terms so that you can find the derivative of each in turn.
You can define a term as the largest sequence of characters not containing term separators such as (in your examples) + and -.
Hence the terms for your examples are:
-2x^2+2x-3 => 2x^2 2x 3
-2x+sinx-3 => 2x sinx 3
-x+sin2x-tanx => x sin2x tanx
For each term, you then need to evaluate the form of the term. The form will dictate how you create the derivative.
For example, you can detect if it contains a trigonometric function of the form [n]sin[m]x where n and m are optional numbers. To simplify things, you could add in those terms if they're not there, such as sinx becoming 1sin1x (I'll call this the full-form of the term). Being able to assume all subterms are present will greatly ease the derivative calculation.
Let's say the term is sin4x. Expanding that will give you 1sin4x which you can then split into term-multiplier 1, function sin and x-multiplier 4. Then using standard derivative knowledge nsinmx => (n*m)cosmx, this would become 4cos(4x) and that term would be done.
If it doesn't contain a trigonometric function, you can use the same full-form trick to cover all of the power/constant expressions with the following rules in turn:
if it's a constant (all numeric), append x^0 (multiply by 1).
if it ends with x, append ^1, so 4x becomes 4x^1.
if it starts with x, prefix it with 1, so x^3 becomes 1x^3.
Once that's done, you will have a full-form of ax^b and you can then create the derivative (ab)x^(b-1) and post-process it:
if the bit after x is ^0, remove the whole x^0.
if the bit after x is ^1, remove the ^1.
if the bit before the x is 1, remove it.
if the bit before the x is 0, remove the entire term (and preceding term separator, if any).
So, taking a complex combination of your test data:
-2x^2 + 5x + 4sin3x - 3
which can be treated as:
0 - 2x^2 + 5x + 4sin3x - 3
The following actions happen to each term:
0 [0x^1] (derives as) 0, remove it.
2x^2 [2x^2] (derives as) (2*2)x^(2-1) => 4x^1 => 4x
5x [5x^1] (derives as) (5x1)x^(1-1) => 5x^0 => 5
4sin3x [4sin3x] (derives as) 12cos3x
3 [3x^0] (derives as) 0, remove it and preceding '-'
Thus you end up with - 4x + 5 + 12cos3x which, although my calculus education is some thirty years in the past (and I don't think I've used it since, though I will no doubt be using it next year when my eldest hits secondary school), Wolfram Alpha appears to agree with me :-)
This function will parse the text, cut it in to different parts identified by type[i], stores in a structure. It recognizes x, +, -, and numbers. It can be expand it to include other operators etc.
#define maxlen 50
#define idx 0 //X variable
#define idnumber 1 //number
#define idplus 2 //+ sign
#define idminus 3 //- sign
struct foo
{
int type[10];//each type can be a number (idnum), +, -, etc.
int num[10];//if type[i] is number then num[i] identifies that number
int count;//total number of parts
};
void parse_one_line(struct foo *v, const char *s)
{
char buf[maxlen];
memset(buf, 0, maxlen);
int j = 0;
//remove white spaces
for (int i = 0, len = strlen(s); i < len; i++)
{
if (s[i] == ' ') continue;
buf[j] = s[i];
j++;
}
char part[maxlen];
v->count = 0;
for (int i = 0, len = strlen(buf); i < len; i++)
{
char c = buf[i];
if (c == 'x')
{
v->type[v->count] = idx;
v->count++;
}
else if (c == '+')
{
v->type[v->count] = idplus;
v->count++;
}
else if (c == '-')
{
v->type[v->count] = idminus;
v->count++;
}
else if (c >= '0' && c <= '9')
{
int j = 0;
memset(part, 0, maxlen);
for (; i < len; i++)
{
c = buf[i];
if (c >= '0' && c <= '9')
{
part[j] = c;
j++;
}
else
{
break;
}
}
i--;
v->num[v->count] = atoi(part);
v->type[v->count] = idnumber;
v->count++;
}
}
for (int i = 0; i < v->count; i++)
{
switch (v->type[i])
{
case idnumber: printf("%d", v->num[i]); break;
case idx: printf("X"); break;
case idplus: printf("+"); break;
case idminus: printf("-"); break;
default:break;
}
}
printf("\n");
}
int main()
{
struct foo st;
parse_one_line(&st, "-23x + 2 + 2x - 3");
return 0;
}

How to add numbers between two string array in c

Sometimes we need to calculate very long number which couldn't hold any numerical data type of C. As we know all common numerical data type has limitation.
I'm beginner and I think... it is possible by string. My question is:
How can I add two strings?
Sample Input:
String 1: 1234
String 2: 1234
Output
Result : 2468
[Note: Numbers can be very very long in Strings. Unlimited]
Do not convert to a number. Instead, add as you (must) have learned in basic eductation: one pair of digits at a time, starting from the lowest (rightmost) and remember to carry the tens forwards (to the left).
The length of the source strings does not matter, but you must be sure the result char array is large enough for the longest input value plus one (optional) digit.
The algorithm is so simple that I will not "type the code" (which is off-topic for Stack Overflow). It boils down to
carryOver = 0
loop:
result0 = inputA0 + inputB0 + carryOver
if result0 > '9'
carryOver = 1
result0 -= 10
else
carryOver = 0
go to loop while there is still input left ...
where the 0 in the variable names indicate the index of the current digits under consideration.
Edit This Answer does not allow carry overs but infinity long add operations. It does not solve the problem of the user. But it is an implementation example and the user asked for one. This is why I will let the answer stay here and not delete it.
You can use atoi (ascii to int)
Do you realy mean C or C++?
This code can't calculate 8+3 = 11 but 5+3 = 8. There is no carry over.
int temp;
const inst size_of_array;
char one[size_of_array];
char two[size_of_array];
char result[size_of_array];
for(int i = 0; i < size_of_array; i++)
{
temp = atoi(one[i]) +atoi(two[i]);
results[i] = numberToCharacter(temp);
}
char numberToCharacter((int temp)
{
if(temp == 1)
{
return('1'):
} ///..
}
Parse the string variables to integer variables. Calculate sum of them, then parse the result to string.
Here is a fiddler.
Here is the code:
#include <stdio.h>
int main(void) {
//Declaring string variables
char string1[10] = "1234";
char string2[10] = "1234";
//Converting them to integer
int int1 = atoi(string1);
int int2 = atoi(string2);
//Summing them
int intResult = int1 + int2;
//Printing the result
printf("%d", intResult);
return 0;
}

Boyer-Moore Algorithm

I'm trying to implement Boyer-Moore Algorithm in C for searching a particular word in .pcap file. I have referenced code from http://ideone.com/FhJok5. I'm using this code as it is.
Just I'm passing packet as string and the keyword I'm searching for to the function search() in it. When I'm running my code it is giving different values every time. Some times its giving correct value too. But most of times its not identifying some values.
I have obtained results from Naive Algo Implementation. Results are always perfect.
I am using Ubuntu 12.0.4 over VMware 10.0.1. lang: C
My question is It has to give the same result every time right? whether right or wrong. This output keeps on changing every time i run the file on same inputs; and during several runs, it gives correct answer too. Mostly the value is varying between 3 or 4 values.
For Debugging I did so far:
passed strings in stead of packet every time, Its working perfect and same and correct value every time.
checking pcap part, I can see all packets are being passed to the function (I checked by printing packet frame no).
same packets I am sending to Naive Algo code, its giving perfect code.
Please give me some idea, what can be the issue. I suspect some thing wrong with memory management. but how to find which one?
Thanks in advance.
# include <limits.h>
# include <string.h>
# include <stdio.h>
# define NO_OF_CHARS 256
// A utility function to get maximum of two integers
int max (int a, int b) { return (a > b)? a: b; }
// The preprocessing function for Boyer Moore's bad character heuristic
void badCharHeuristic( char *str, int size, int badchar[NO_OF_CHARS])
{
int i;
// Initialize all occurrences as -1
for (i = 0; i < NO_OF_CHARS; i++)
badchar[i] = -1;
// Fill the actual value of last occurrence of a character
for (i = 0; i < size; i++)
badchar[(int) str[i]] = i;
}
/* A pattern searching function that uses Bad Character Heuristic of
Boyer Moore Algorithm */
void search( char *txt, char *pat)
{
int m = strlen(pat);
int n = strlen(txt);
int badchar[NO_OF_CHARS];
/* Fill the bad character array by calling the preprocessing
function badCharHeuristic() for given pattern */
badCharHeuristic(pat, m, badchar);
int s = 0; // s is shift of the pattern with respect to text
while(s <= (n - m))
{
int j = m-1;
/* Keep reducing index j of pattern while characters of
pattern and text are matching at this shift s */
while(j >= 0 && pat[j] == txt[s+j])
j--;
/* If the pattern is present at current shift, then index j
will become -1 after the above loop */
if (j < 0)
{
printf("\n pattern occurs at shift = %d", s);
/* Shift the pattern so that the next character in text
aligns with the last occurrence of it in pattern.
The condition s+m < n is necessary for the case when
pattern occurs at the end of text */
s += (s+m < n)? m-badchar[txt[s+m]] : 1;
}
else
/* Shift the pattern so that the bad character in text
aligns with the last occurrence of it in pattern. The
max function is used to make sure that we get a positive
shift. We may get a negative shift if the last occurrence
of bad character in pattern is on the right side of the
current character. */
s += max(1, j - badchar[txt[s+j]]);
}
}
/* Driver program to test above function */
int main()
{
char txt[] = "ABAAAABAACD";
char pat[] = "AA";
search(txt, pat);
return 0;

Resources