Infix to postfix conversion and evaluation including whitespaces and double quotes - c

I have the code below, but I need the code to account for white spaces and double digits, for example if i enter (7-3)/(2+2) it should come out 73-22+/ result: 1. If i enter (7 - 3) / (2 + 2) it should come out 7 3 - 2 2 + / result 1. If I enter (22 - 10)/(2 + 2) it should come out 22 10 - 2 2 + / Result: 3
Here is the code I have:
#include<stdio.h>
char stack[100];
int top = 0;
int eval_top = -1;
int eval_stack[100];
void push(char x) // Push char into stack
{
stack[top++] = x;
}
char pop() // Pop char to top of stack
{
if (top == -1)
return -1;
else
return stack[top--];
}
/* functions for evaluation of postfix expression */
// push function
void eval_push(int x) { // Find push result
eval_stack[++eval_top] = x;
}
// pop function
int eval_pop() { // Find pop result
if (eval_top == -1) {
return -1;
} else {
return eval_stack[eval_top--];
}
}
int priority(char x) // check priority order
{
if (x == '(')
return 0;
if (x == '+' || x == '-')
return 1;
if (x == '*' || x == '/')
return 2;
}
// function to evaluate the postfix expression
void EvalPostfix(char postfix[]) {
int A, B;
int val;
char ch;
int i;
//find postfix
for (i = 0; postfix[i] != ')'; i++) {
ch = postfix[i];
if (isdigit(ch)) {
eval_push(ch - '0');
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
A = eval_pop();
B = eval_pop();
switch (ch) {
case '*':
val = B * A;
break;
case '/':
val = B / A;
break;
case '+':
val = B + A;
break;
case '-':
val = B - A;
break;
}
eval_push(val); //send value on top of stack
}
}
printf("\n Result: %d \n", eval_pop());
}
main() {
int i = 0;
char * e, x;
char postfix[100]; // store postfix for later evaluation
char exp[100];
printf("Infix expression : ");
scanf("%s", exp); // asking the user to enter the infix expression
printf("Postfix expression: ");
e = exp;
while ( * e != '\0') {
if (isalnum( * e)) { // if character is alphabet or number , it is printed
printf("%c", * e);
postfix[i++] = * e;
} else if ( * e == '(') // if it is open parenthesis, it is pushed into the stack without any priority
push( * e);
else if ( * e == ')') // if it is closed parenthesis , pop the elements in the stack and print them until the we see ( symbol
{
while ((x = pop()) != '(') {
printf("%c", x);
postfix[i++] = x;
}
} else // if character is symbol like +, -, *, / then based on their priority character is pushed if it high priority otherwise high priority symbols are popped and it is pushed
{
while (priority(stack[top]) >= priority( * e)) {
x = pop();
printf("%c", x);
postfix[i++] = x;
}
push( * e);
}
e++;
}
while (top != -1) // printing remaining elements in the stack
{
x = pop();
printf("%c", x);
postfix[i++] = x;
}
postfix[i] = ')'; // this is to add at the end for detecting end by the evaluation function
EvalPostfix(postfix);
}

There are some problems in your code
your pop is not symmetric with your push, push post increment the index so pop must pre decrement the index, and because of that the first invalid index is not -1 but 0 :
char pop() // Pop char to top of stack
{
if (top == 0)
return -1;
else
return stack[--top];
}
priority does not return a value if all the tests are false, but probably the last test is useless
In
while (priority(stack[top]) >= priority( * e))
you missed to check if the stack is empty, must be :
while ((top != 0) && (priority(stack[top]) >= priority( * e))) {
Because the first invalid index for stack is 0 rather than -1
while (top != -1) // printing remaining elements in the stack
must be
while (top != 0) // printing remaining elements in the stack
When you make the postfix expression there is no separation between the numbers, for instance "12+3" becomes "123+" like "1+23", and in EvalPostfix you consider a number has only one digit (eval_push(ch - '0');), so you do not manage the numbers having more than 1 digit. To manage several digits add a separator after all numbers, for instance a space to have "12 3 +" or "1 23 +" and read the number with scanf etc
You do not make the right postfix expression in all the cases, for instance for 1+2*3 you make 12+3* but it must be 123*+
You do not detect the invalid infix expressions
in
while (priority(stack[top]) >= priority( * e))
I missed to say the top element is not stack[top] but stack[top - 1] so it must be replaced by
while ((top != 0) && (priority(stack[top - 1]) >= priority( * e))) {
adding that correction 1+2*3 produces the right postfix expression 123*+
Note it is more clear to introduce the function empty() and tops(), and in case of an invalid access into the stack print a message and exit rather than to return -1 as a char
int empty()
{
return (top == 0);
}
char tops()
{
if (top == 0) {
fputs("top() on the empty stack, abort", stderr);
exit(-1);
}
return stack[top - 1];
}
char pop() // Pop char to top of stack
{
if (top == 0) {
fputs("pop() on the empty stack, abort", stderr);
exit(-1);
}
return stack[--top];
}
also detect a possible overflow of the stack :
void push(char x) // Push char into stack
{
if (top == sizeof(stack)) {
fputs("stack overflow", stderr);
exit(-1);
}
stack[top++] = x;
}
so now you can do
while (!empty() && (priority(tops()) >= priority( * e))) {
Of course this is the same for the other stack
I need the code to account for white spaces and double digits
double digits is too restrictive, just manage any integer, for that you can extract the number using strtol. You cannot also read the full expression using scanf("%s", exp); because is stops on the first space, use fgets.

Related

Recursive function in C to determine if digits of an integer are sorted ascending, descending or neither

I need to write a recursive function that returns 1 if digits of a whole number are ascending (left to right), return -1 if descending or return 0 if neither.
My solution attempt returns 0 every time and I know why but I don't know how to get around it.
Here's my code:
#include <stdio.h>
int check_order(int n)
{
if (n % 10 > n / 10 % 10)
{
return check_order(n / 10);
if (n == 0)
{
return 1;
}
}
else if (n % 10 < n / 10 % 10)
{
return check_order(n / 10);
if (n == 0)
{
return -1;
}
}
else
{
return 0;
}
}
int main()
{
int n;
printf("enter a whole number (n > 9):");
scanf_s("%d", &n);
printf("function returned: %d\n", check_order(n));
}
Here's a simple recursion:
int f(int n){
if (n < 10)
return 0;
int dr = n % 10; // rightmost digit
n = n / 10;
int dl = n % 10; // second digit from the right
int curr = dl < dr ? 1 : -1; // current comparison
if (dl == dr) curr = 0; // keep strict order
if (n < 10)
return curr;
return curr == f(n) ? curr : 0; // are the comparisons consistent?
}
Explain your algorithm?
Suppose you use the following:
You are given a number.
You need to turn that number into a sequence of digits.
If you are given a number, you can convert that number to a sequence of digits.
If you are given a sequence of digits, use
that.
Compare each pair of digits -> ascending, descending, or neither.
Combine the results from each pair, sequentially/recursively.
We can use a string to make the digit comparisons easier, and accept very long sequences of digits.
We can use an enum(erated) type to represent the ordering.
How do you combine the results? Define a function that combines the order of two adjacent, overlapping pairs, then you can combine results.
#include <stdio.h>
#include <string.h>
typedef enum { descending=-1, other=0, ascending=1 } order_t;
order_t pair_order(int a, int b) {
if( a < b ) return ascending;
if( a > b ) return descending;
return other;
}
//strict (increasing/decreasing)
order_t strict_order( order_t x, order_t y ) {
if( x == y ) return x;
return other;
}
//monotone (increasing/decreasing)
order_t monotone_order( order_t x, order_t y ) {
if( x == y ) return x;
if( other == x ) return y;
if( other == y ) return x;
return other;
}
order_t check_order( char* p, int remain ) {
//printf("p:%s\n",p); //uncomment to watch progress
if( remain<2 ) return other;
if( remain==2 ) return pair_order(p[0], p[1]);
return strict_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
//return monotone_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
}
char* order_name[] = {
"descending",
"other",
"ascending"
""
};
int main()
{
char line[666] = "none";
while ( strlen(line) > 0 ) {
printf("enter a number (at least 2 digits):");
fgets(stdin,line,sizeof(line)-1);
if( strlen(line) > 0 && line[strlen(line)-1] == '\n' )
line[strlen(line)-1] = '\0';
order_t order = check_order(line);
printf("function returned: (%d)%s\n", order, order_name[order+1]);
}
}
I think you were started on the right track but need to flesh out your code more. My solution borrows on that of #ChuckCottrill as I like his enum but I don't like that he doesn't play the ball as it lays (i.e. converts to a string instead of dealing with the int.) I also borrow the nice test examples of #ggorlen but I don't like that solution either as it can take multiple passes through the number to figure out the answer when only one pass should be needed:
#include <stdio.h>
typedef enum { descending=-1, other=0, ascending=1 } order_t; // a la #ChuckCottrill
order_t check_order(int n)
{
if (n > 9) {
int right = n % 10;
int left = n / 10 % 10;
if (right > left) {
n /= 10;
if (n > 9) {
return (ascending == check_order(n)) ? ascending : other;
}
return ascending;
}
if (right < left) {
n /= 10;
if (n > 9) {
return (descending == check_order(n)) ? descending : other;
}
return descending;
}
}
return other;
}
int main() { // a la #ggorlen
printf("12345: %d\n", check_order(12345));
printf("54321: %d\n", check_order(54321));
printf("54323: %d\n", check_order(54323));
printf("454321: %d\n", check_order(454321));
printf("1: %d\n", check_order(1));
printf("12: %d\n", check_order(12));
printf("21: %d\n", check_order(21));
}
OUTPUT
> ./a.out
12345: 1
54321: -1
54323: 0
454321: 0
1: 0
12: 1
21: -1
>
A version that works for any length since it takes the string as parameter.
And feeding the recursive function with previous status (ascending or descending) allows for some shorter code and less functions.
int check_order(char *str, int index, int previous) {
char current = str[index]; // char at index
char next = str[index+1]; // char at index+1
if (current == 0 || next == 0) {
return previous; // End of string
}
// Ascending or descending?
int status = next > current ? 1 : (next < current ? -1 : 0);
if (status == 0 || index > 0 && status != previous) {
// If neither -1/1 nor status == previous (while not initial call)
return 0;
}
return check_order(str, index+1, status); // Check from next index
}
The main function must ensure the string is at least 2 chars
int main(int argc, char **argv) {
char *str = *++argv;
// Some optional checks on str here... (like this is a number)
int status = 0; // Default value if string length < 2
if (strlen(str) >= 2) {
status = check_order(str, 0, 0);
}
printf("Check order for %s is %d\n", str, status);
return 0;
}
Code after a return statement like this is unreachable:
return check_order(n / 10);
if (n == 0)
{
return -1;
}
Beyond this, you're on the right track of checking the current digit against the next digit, but I don't see a clear base case (when n < 10, that is, a single digit).
Trying to check ascending and descending in one recursive function is difficult to manage. In particular, communicating state between stack frames and determining which cases are still valid at a given call suggests that the return value is overworked.
To save having to return a struct or use an enum or magic numbers as flags, I'd write two general helper functions, ascending_digits and descending_digits.
#include <stdbool.h>
#include <stdio.h>
bool ascending_digits(int n) {
if (n < 10) return true;
if (n % 10 < n / 10 % 10) return false;
return ascending_digits(n / 10);
}
bool descending_digits(int n) {
if (n < 10) return true;
if (n % 10 > n / 10 % 10) return false;
return descending_digits(n / 10);
}
int check_order(int n) {
if (ascending_digits(n)) return 1;
if (descending_digits(n)) return -1;
return 0;
}
int main() {
printf("12345: %d\n", check_order(12345));
printf("54321: %d\n", check_order(54321));
printf("54323: %d\n", check_order(54323));
printf("454321: %d\n", check_order(454321));
printf("1: %d\n", check_order(1));
printf("12: %d\n", check_order(12));
printf("21: %d\n", check_order(21));
return 0;
}
Output:
12345: 1
54321: -1
54323: 0
454321: 0
1: 1
12: 1
21: -1
Not only are these functions easier to understand and maintain individually, they're also more reusable than if they were inseparably tied together.
This doesn't handle negative numbers--you could apply abs and go from there if you want. Same goes for handling equal values; this implementation accepts numbers such as 1223 but you could use <= to enforce strict ordering.

Error in using atof() and strtod() when trying to convert numerical string into float

I've made code to read expressions from a file in postfix notation (RPN) and output the value. While it is correctly reading the values and displaying outputs for expressions without any numbers that use decimal places, it defaults to error for any expression containing a float value.
Basically, if a digit is found within a string read from file, it needs to be converted to a float.
I've unsuccesfully tried setting the data value equal to atof(str) and strtod(const char *str, char **endptr), but I'm still getting the error.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
int top = -1;
float stack[500];
/* push the given data into the stack */
void push (int data) {
stack[++top] = data;
}
/* Pop the top element from the stack */
float pop () {
float data;
if (top == -1)
return -1;
data = stack[top];
stack[top] = 0;
top--;
return (data);
}
int main() {
char str[500];
FILE *p;
if((p=fopen("testfile1.txt","r"))==NULL){
printf("\n Unable to open file string.txt");
return 1;
}
while(fgets(str,500,p)!='\0'){
float data = -1, operand1, operand2, result;
for (int 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);
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:%3.2f\n", stack[top]);
else
printf("have given wrong postfix expression\n");
return 1;
}
}
There are 5 postfix expressions in the file, and they are as follows:
13 1 - 2 / 3 155 + *
100 100 100 100 + + +
10.33 2 2 2 2 2 * * * * *
30 10 - 10 - 10 - 2 *
300 13.25 - 11 3 - / 4 5 - * 3 /
But, the output of the program denies the third expression because it contains 10.33, which is not an integer value.
Output:
Output: 948.00
Output: 400.00
have given wrong postfix expression
Output: 0.00
Output: 300.00
Does anyone know how to modify this code to handle floats?
Cheers.
You could try to manually process decimal values almost the same you process integers, but in C it would be simpler to directly iterate a number in a single pass:
while(fgets(str, sizeof(str), stdin) != NULL) {
unsigned int i;
for (i=0; i<strlen(str); i++) {
if (isdigit(str[i])) {
data = str[i++] - '0'; // initialize data with first digit
while(isdigit(str[i])) {
data = data * 10 + (str[i++] - '0'); // increment with other digits
}
if (str[i] == '.') { // decimal part
double mult = .1;
i++;
while(isdigit(str[i])) {
data = data + mult * (str[i++] - '0'); // increment with decimal part
mult *= .1;
}
}
push(data);
}
...
But in fact strtod does it for you...:
while(fgets(str, sizeof(str), stdin) != NULL) {
unsigned int i;
for (i=0; i<strlen(str); i++) {
if (isdigit(str[i])) {
char *end;
data = ::strtod(str+i, &end);
i = end - str; // that's all we are past the number...
push(data);
}
...

Obtain the best move from MiniMax algorithm in Tic-Tac-Toe game

I'm trying to implement MiniMax algorithm based on Wikipedia pseudocode in Tic-Tac-Toe game written in C. However, I can't manage to obtain the best possible move. Here's my code:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
// compile and run: gcc minimax.c -std=c99 && ./a.out
int max(int x, int y) {
return x > y ? x : y;
}
int min(int x, int y) {
return x < y ? x : y;
}
int whoWon(char ch) {
switch (ch) {
case 'O':
return -1;
break;
case 'X':
return 1;
break;
}
}
void printArray(char array[]) {
printf("# START\n"
"%c | %c | %c\n"
"--|---|--\n"
"%c | %c | %c\n"
"--|---|--\n"
"%c | %c | %c\n"
"# END\n\n", array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7], array[8]);
}
int anyWinners(char board[])
{
int i;
/* check every row */
for(i = 0; i < 7; i += 3)
if(board[i] != ' ' && board[i] == board[i+1] && board[i] == board[i+2])
return whoWon(board[i]);
/* check every column */
for(i = 0; i < 3; i++)
if(board[i] != ' ' && board[i] == board[i+3] && board[i] == board[i+6])
return whoWon(board[i]);
/* check diagonals */
if(board[4] != ' ' && ((board[0] == board[4] && board[0] == board[8]) || (board[2] == board[4] && board[2] == board[6])))
return whoWon(board[4]);
return 0;
}
int fullBoard(char board[]) {
for (int i = 0; i < 9; ++i) {
if (board[i] == ' ')
return 0;
}
return 1;
}
int minimax(char node[], int depth, bool maximizingPlayer, int * move) {
int terminalNode = anyWinners(node);
if (depth == 0 || terminalNode || fullBoard(node)) {
printf("################## END OF SUBTREE ##################\n");
return terminalNode;
}
int bestValue, val;
if (maximizingPlayer) {
bestValue = -2;
for (int i = 0; i < 9; ++i) {
if (node[i] == ' ') {
char child[9];
strcpy(child, node);
child[i] = 'X';
// debug
printArray(child);
val = minimax(child, depth - 1, false, move);
// debug
printf("X: ^^ i = %d ^^ depth = %d ^^ val = %d\n", i, depth, val);
//bestValue = max(bestValue, val);
if (val > bestValue) {
bestValue = val;
if (depth == 9) *move = i;
}
}
}
return bestValue;
} else {
bestValue = 2;
for (int i = 0; i < 9; ++i) {
if (node[i] == ' ') {
char child[9];
strcpy(child, node);
child[i] = 'O';
// debug
printArray(child);
val = minimax(child, depth - 1, true, move);
// debug
printf("O: ^^ i = %d ^^ depth = %d ^^ val = %d\n", i, depth, val);
bestValue = min(bestValue, val);
}
}
return bestValue;
}
}
int main() {
int move = -999; // initialize only for debug
// X will always win no matter what, first best move for X is 8
// char board[] = {'O', ' ', ' ',
// ' ', ' ', ' ',
// 'X', 'X', ' '};
// best move for X is 3
char board[] = {'O', 'O', ' ',
' ', 'X', 'X',
' ', ' ', ' '};
// Initial call for maximizing player
int result = minimax(board, 9, true, &move);
printf("minimax returned: %d\n", result);
printf("chosen move: %d\n", move);
return 0;
}
Code prints board for each move with state of all variables. There are also two failing tests commented out in main. Right now algorithm returns bad moves and I can't find the error.
I see two problems:
The heuristic is wrong
There is a problem with strcpy.
The heuristic is wrong
The Wikipedia pseudo-code says:
if depth = 0 or node is a terminal node
return the heuristic value of node
Your implementation does this:
if depth = 0 or node is a terminal node
return 1 if X wins, -1 if O wins, 0 if it is a draw
But that isn't a very good heuristic. With that heuristic, all the possible ways that X could win are equally weighted. So if X finds a way to win in 3 moves, that is weighted just the same as if X finds a way to win in 2 moves, and that is weighted just the same as if X finds a way to win in 1 move.
So, here is what happens in your test case:
X tries position 2.
O tries position 3.
X tries position 6.
This is a terminal node. X wins. So return positive 1.
Heuristic for this decision path = 1
Another possibility it hits is:
X tries position 3.
This is a terminal node. X wins. So return positive 1.
Heuristic for this decision path = 1
Since both of these solutions have the same heuristic, so they are both of equal value. You probably meant for this solution to be suboptimal, because it took too many moves to win. I suggest a heuristic based on the number of moves it took to get here, multiplied who the winner is. So if X wins in 1 moves, heuristic is 5000. If X wins in 2 moves, then heuristic is 2500. If O wins in 2 moves, heuristic is -2500. Something like that.
There is a problem with strcpy
This line:
strcpy(child, node);
should be:
memcpy(child, node, 9*sizeof(char));
Because "node" is not a null terminated string. When I run this on VS2013/Windows 8.1 my output is garbage because. You might be getting lucky on your platform.

Can't decode a polynomial properly

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct polynomial{
int coeff;
char var;
int exp;
struct polynomial *link;
} poly;
poly* decode(char*);
main()
{
char polynomial[100];
poly *first, *second;
printf("\n---Enter 1st polynomial---\n\n");
scanf("%s",polynomial);
first=decode(polynomial);
printf("\n---Enter 2nd polynomial---\n\n");
scanf("%s",polynomial);
second=decode(polynomial);
//More statements further
return 0;
}
/*--- Decoding Polynomial ---*/
poly* decode(char *polynomial)
{
poly *p=NULL, *q=NULL, *temp=NULL;
int i=0, sign;
short coeff_entry=TRUE, exp_entry=FALSE, var_visited=FALSE, exp_visited=FALSE, coeff_visited=FALSE;
while(polynomial[i]!='\0')
{
temp=(poly*)malloc(sizeof(poly));
if(!temp)
{
printf("Error! Memory not allocated\n");
exit(1);
}
if(polynomial[i]==43) {i++; sign=1;}
if(polynomial[i]==45) {i++; sign=-1;}
while(1)
{
if((polynomial[i]>=48&&polynomial[i]<=57)&&coeff_entry==TRUE)
{
temp->coeff=10*(temp->coeff)+(polynomial[i]-48);
coeff_visited=TRUE;
}
else if((polynomial[i]>=65&&polynomial[i]<=90)||(polynomial[i]>=97&&polynomial[i]<=122))
{
temp->var=polynomial[i];
coeff_entry=FALSE;
exp_entry=TRUE;
var_visited=TRUE;
}
else if((polynomial[i]>=48&&polynomial[i]<=57)&&exp_entry==TRUE)
{
temp->exp=10*(temp->exp)+(polynomial[i]-48);
exp_visited=TRUE;
}
else if(polynomial[i]==43||polynomial[i]==45||polynomial[i]=='\0')
{
exp_entry=FALSE;
coeff_entry=TRUE;
if(var_visited&&!exp_visited)
{
temp->exp=1;
!var_visited;
!exp_visited;
}
if(!coeff_visited)
{
!coeff_visited;
temp->coeff=1;
}
temp->coeff*=sign;
break;
}
i++;
}
//These lines are for debugging purpose only
printf("\nCoefficient of the term is: %d\n",temp->coeff);
printf("Variable of the term is: %c\n",temp->var);
printf("Exponent of the term is: %d\n",temp->exp);
temp->link=NULL;
if(p==NULL) p=q=temp;
else
{
q->link=temp;
q=q->link;
}
}
return p;
}
In my code I am asking user to input a polynomial in the form like: -5x^2+7y^3-19z+5
Everything seems fine but two problems in decoding this polynomial and storing in the linked list form:
First bug comes when the first-most coefficient is positive in polynomial like 17x^3-13z+5
In this case a very long integer value (most probably garbage value) gets store in the respected node of linked list.
Second bug is when there is no first coefficient like x^7-18y^3+z-13
In this case 0 gets stored in the respected node of linked list. In other terms of polynomial, like z in example above, where there is no coefficient 1 gets stored in the coeffient part of the node.
So problem arises with the first coefficient only that too a 'positive coeff' or 'no coefficient' at all.
There are many errors in your code, the most important is the expresions like
!value;
you need to assign to it, lik
value = !value;
And you are not initializing sign when there is not '+' sign in front of the next token, you need to initialize it to 1, check if there is a '-' and set it to -1 otherwise ignore the '+'.
Now I appended the fixed code, try it
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct _polynomial {
int coeff;
char var;
int exp;
struct _polynomial *link;
} poly;
poly *decode(char*);
int
main()
{
char string[100];
printf("\n---Enter 1st polynomial---\n\n");
scanf("%99s", string);
decode(string);
printf("\n---Enter 2nd polynomial---\n\n");
scanf("%99s", string);
decode(string);
//More statements further
return 0;
}
/*--- Decoding Polynomial ---*/
poly* decode(char *polynomial)
{
poly *p = NULL, *q = NULL, *temp = NULL;
int i = 0, sign;
short coeff_entry=TRUE, exp_entry=FALSE, var_visited=FALSE, exp_visited=FALSE, coeff_visited=FALSE;
while (polynomial[i] != '\0')
{
temp = malloc(sizeof(poly));
if (temp == NULL)
{
printf("Error! Memory not allocated\n");
exit(1);
}
sign = 1;
if (polynomial[i] == 43)
i++;
if (polynomial[i] == 45)
{
i++;
sign=-1;
}
while (1)
{
if ((polynomial[i] >= 48 && polynomial[i] <= 57) && coeff_entry == TRUE)
{
temp->coeff = 10 * temp->coeff + polynomial[i] - 48;
coeff_visited = TRUE;
}
else if ((polynomial[i] >= 65 && polynomial[i] <= 90) || (polynomial[i] >= 97 && polynomial[i] <= 122))
{
temp->var = polynomial[i];
coeff_entry = FALSE;
exp_entry = TRUE;
var_visited = TRUE;
}
else if ((polynomial[i] >= 48 && polynomial[i] <= 57) && exp_entry == TRUE)
{
temp->exp=10*(temp->exp)+(polynomial[i]-48);
exp_visited=TRUE;
}
else if (polynomial[i] == 43 || polynomial[i] == 45 || polynomial[i] == '\0')
{
exp_entry=FALSE;
coeff_entry=TRUE;
if (var_visited && !exp_visited)
{
temp->exp = 1;
var_visited = !var_visited;
exp_visited = !exp_visited;
}
if (!coeff_visited)
{
coeff_visited = !coeff_visited;
temp->coeff = 1;
}
temp->coeff *= sign;
break;
}
i++;
}
printf("\nCoefficient of the term is: %d\n", temp->coeff);
printf("Variable of the term is: %c\n", temp->var);
printf("Exponent of the term is: %d\n", temp->exp);
temp->link = NULL;
if (p == NULL)
p = q = temp;
else
{
q->link = temp;
q = q->link;
}
}
return p;
}

atoi implementation in C

I can't understand the following atoi implementation code, specifically this line:
k = (k << 3) + (k << 1) + (*p) - '0';
Here is the code:
int my_atoi(char *p) {
int k = 0;
while (*p) {
k = (k << 3) + (k << 1) + (*p) - '0';
p++;
}
return k;
}
Can someone explain it to me ?
Another question: what should be the algorithm of atof implementation ?
<< is bit shift, (k<<3)+(k<<1) is k*10, written by someone who thought he was more clever than a compiler (well, he was wrong...)
(*p) - '0' is subtracting the value of character 0 from the character pointed by p, effectively converting the character to a number.
I hope you can figure out the rest... just remember how the decimal system works.
Here is a specification for the standard function atoi. Sorry for not quoting the standard, but this will work just as fine (from: http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/ )
The function first discards as many whitespace characters (as in
isspace) as necessary until the first non-whitespace character is
found. Then, starting from this character, takes an optional initial
plus or minus sign followed by as many base-10 digits as possible, and
interprets them as a numerical value.
The string can contain additional characters after those that form the
integral number, which are ignored and have no effect on the behavior
of this function.
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed and zero is returned.
k = (k << 3) + (k << 1);
means
k = k * 2³ + k * 2¹ = k * 8 + k * 2 = k * 10
Does that help?
The *p - '0' term adds the value of the next digit; this works because C requires that the digit characters have consecutive values, so that '1' == '0' + 1, '2' == '0' + 2, etc.
As for your second question (atof), that should be its own question, and it's the subject for a thesis, not something simple to answer...
#include <stdio.h>
#include <errno.h>
#include <limits.h>
double atof(const char *string);
int debug=1;
int main(int argc, char **argv)
{
char *str1="3.14159",*str2="3",*str3="0.707106",*str4="-5.2";
double f1,f2,f3,f4;
if (debug) printf("convert %s, %s, %s, %s\n",str1,str2,str3,str4);
f1=atof(str1);
f2=atof(str2);
f3=atof(str3);
f4=atof(str4);
if (debug) printf("converted values=%f, %f, %f, %f\n",f1,f2,f3,f4);
if (argc > 1)
{
printf("string %s is floating point %f\n",argv[1],atof(argv[1]));
}
}
double atof(const char *string)
{
double result=0.0;
double multiplier=1;
double divisor=1.0;
int integer_portion=0;
if (!string) return result;
integer_portion=atoi(string);
result = (double)integer_portion;
if (debug) printf("so far %s looks like %f\n",string,result);
/* capture whether string is negative, don't use "result" as it could be 0 */
if (*string == '-')
{
result *= -1; /* won't care if it was 0 in integer portion */
multiplier = -1;
}
while (*string && (*string != '.'))
{
string++;
}
if (debug) printf("fractional part=%s\n",string);
// if we haven't hit end of string, go past the decimal point
if (*string)
{
string++;
if (debug) printf("first char after decimal=%c\n",*string);
}
while (*string)
{
if (*string < '0' || *string > '9') return result;
divisor *= 10.0;
result += (double)(*string - '0')/divisor;
if (debug) printf("result so far=%f\n",result);
string++;
}
return result*multiplier;
}
Interestingly, the man page for atoi doesn't indicate setting of errno so if you're talking any number > (2^31)-1, you're out of luck and similarly for numbers less than -2^31 (assuming 32-bit int). You'll get back an answer but it won't be what you want. Here's one that could take a range of -((2^31)-1) to (2^31)-1, and return INT_MIN (-(2^31)) if in error. errno could then be checked to see if it overflowed.
#include <stdio.h>
#include <errno.h> /* for errno */
#include <limits.h> /* for INT_MIN */
#include <string.h> /* for strerror */
extern int errno;
int debug=0;
int atoi(const char *c)
{
int previous_result=0, result=0;
int multiplier=1;
if (debug) printf("converting %s to integer\n",c?c:"");
if (c && *c == '-')
{
multiplier = -1;
c++;
}
else
{
multiplier = 1;
}
if (debug) printf("multiplier = %d\n",multiplier);
while (*c)
{
if (*c < '0' || *c > '9')
{
return result * multiplier;
}
result *= 10;
if (result < previous_result)
{
if (debug) printf("number overflowed - return INT_MIN, errno=%d\n",errno);
errno = EOVERFLOW;
return(INT_MIN);
}
else
{
previous_result *= 10;
}
if (debug) printf("%c\n",*c);
result += *c - '0';
if (result < previous_result)
{
if (debug) printf("number overflowed - return MIN_INT\n");
errno = EOVERFLOW;
return(INT_MIN);
}
else
{
previous_result += *c - '0';
}
c++;
}
return(result * multiplier);
}
int main(int argc,char **argv)
{
int result;
printf("INT_MIN=%d will be output when number too high or too low, and errno set\n",INT_MIN);
printf("string=%s, int=%d\n","563",atoi("563"));
printf("string=%s, int=%d\n","-563",atoi("-563"));
printf("string=%s, int=%d\n","-5a3",atoi("-5a3"));
if (argc > 1)
{
result=atoi(argv[1]);
printf("atoi(%s)=%d %s",argv[1],result,(result==INT_MIN)?", errno=":"",errno,strerror(errno));
if (errno) printf("%d - %s\n",errno,strerror(errno));
else printf("\n");
}
return(errno);
}
Here is my implementation(tested successfully with cases containing and starting with letters, +, - and zero's).
I tried to reverse-engineer atoi function in Visual Studio. If the input string only contained numerical characters, it could be implemented in one loop. but it gets complicated because you should take care of -,+ and letters.
int atoi(char *s)
{
int c=1, a=0, sign, start, end, base=1;
//Determine if the number is negative or positive
if (s[0] == '-')
sign = -1;
else if (s[0] <= '9' && s[0] >= '0')
sign = 1;
else if (s[0] == '+')
sign = 2;
//No further processing if it starts with a letter
else
return 0;
//Scanning the string to find the position of the last consecutive number
while (s[c] != '\n' && s[c] <= '9' && s[c] >= '0')
c++;
//Index of the last consecutive number from beginning
start = c - 1;
//Based on sign, index of the 1st number is set
if (sign==-1)
end = 1;
else if (sign==1)
end = 0;
//When it starts with +, it is actually positive but with a different index
//for the 1st number
else
{
end = 1;
sign = 1;
}
//This the main loop of algorithm which generates the absolute value of the
//number from consecutive numerical characters.
for (int i = start; i >=end ; i--)
{
a += (s[i]-'0') * base;
base *= 10;
}
//The correct sign of generated absolute value is applied
return sign*a;
}
about atoi() hint code from here:
and based on the atoi(), my implementation of atof():
[have same limitation of original code, doesn't check length, etc]
double atof(const char* s)
{
double value_h = 0;
double value_l = 0;
double sign = 1;
if (*s == '+' || *s == '-')
{
if (*s == '-') sign = -1;
++s;
}
while (*s >= 0x30 && *s <= 0x39)
{
value_h *= 10;
value_h += (double)(*s - 0x30);
++s;
}
// 0x2E == '.'
if (*s == 0x2E)
{
double divider = 1;
++s;
while (*s >= 0x30 && *s <= 0x39)
{
divider *= 10;
value_l *= 10;
value_l += (double)(*s - 0x30);
++s;
}
return (value_h + value_l/divider) * sign;
}
else
{
return value_h * sign;
}
}

Resources