How do you make a menu interface that accepts double digit integers or characters in C? - c

I was fumbling with this program for the last couple of hours and I can't seem to find a way to get this program to work. I started out with a switch statement style menu but then I had an issue where the menu would fall through and exit and I couldn't figure that out so I just switched my code over to an if else based menu. The idea behind the program is as follows:
Write and test a C program that implements a stack based integer-based calculator. The program accepts input until q is entered. However my difficulties lie in getting the menu to accept numbers larger than 10.
I have every single function working properly in my program except when I enter a two digit integer it will store both digits individually. I know that this is because I have the menu setup to read and work with chars, but I wasn't able to figure out how to get an array of chars to work. I've never programmed in C before so the idea of dynamic memory allocation alludes me as I'm not entirely sure when it is necessary. Here is the source code I have for the program so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define SIZE 6
int stack[SIZE]; //stack size
int top = 0; //top of stack
void pop();
void clear();
void display();
void top_element();
void add();
void multiply();
void subtract();
void division();
void power();
int main()
{
char input;
int flag = 1;
while(flag == 1)
{
printf(": ");
scanf(" %c",&input);
if(isdigit(input))
{
if(top < SIZE)
{
stack[top] = input - '0';
top++;
}
else
printf("Error: stack overflow\n");
}
else if(input=='p')
pop();
else if(input=='c')
clear();
else if(input=='d')
display();
else if(input=='=')
top_element();
else if(input=='+')
add();
else if(input=='*')
multiply();
else if(input=='-')
subtract();
else if(input=='/')
division();
else if(input=='^')
power();
else if(input=='q')
flag = 0;
else
printf("Error: invalid command\n");
}
printf("Goodbye!\n");
return 0;
}
void pop()
{
if(top==0)
printf("Error: stack is empty\n");
else
top--;
}
void clear()
{
top=0;
}
void display()
{
int i;
if(top == 0)
printf("Error: stack is empty\n");
else
{
for(i = top - 1; i >= 0; i--)
printf("%d\n",stack[i] );
}
}
void top_element()
{
printf("%d\n",stack[top-1] );
}
void add()
{
if(top<2)
printf("Error: not enough operands for the requested operation\n");
else
{
int ans=stack[top-1]+stack[top-2];
stack[top-2]=ans;
top--;
}
}
void multiply()
{
int ans=stack[top-1]*stack[top-2];
stack[top-2]=ans;
top--;
}
void subtract()
{
if(top < 2)
printf("Error: not enough operands for the requested operation\n");
else
{
int ans = (stack[top-2] - stack[top-1]);
stack[top-2]=ans;
top--;
}
}
void division()
{
if(top < 2)
printf("Error: not enough operands for the requested operation\n");
else
{
if(stack[top-1]==0)
printf("Error: attempt to divide by 0\n");
else
{
int ans = (stack[top-2]/stack[top-1]);
stack[top-2]=ans;
top--;
}
}
}
void power()
{
if(top < 2)
printf("Error: not enough operands for the requested operation\n");
else
{
int ans = pow(stack[top - 2], stack[top - 1]);
stack[top - 2] = ans;
top--;
}
}

I have a few things to note and don't want to turn this into a TLDR so I'll try to keep each issue to separate paragraphs. You can take this all with a grain of salt; it is just advice, after all.
The format directive you're looking for is %2[0123456789]. Pass a pointer to a location suitably sized to store three characters (i.e. char something[3]; the third byte for the null character) and check the return value. This directive needs to go in a call to scanf on its lonesome, or you'll likely have an aneurysm debugging an issue related to empty fields later on, so the "green light" return value indicating your program is successfully processing good input is that scanf("%2[0123456789]", ptr_into_array_of_char) will return 1. Any other return value means amber or red lights happened. Mind you, I'm interpreting your specs (which are incomplete) quite strictly here... in reality I'd just use %d and be happy that my users are halving their chances of developing arthritis by entering 1 instead of 01 (and you're also less likely to have aneurysms when not dealing with %[).
Our compilers usually issue error messages and abort compilation when we make some syntax error, but this requirement goes against that grain: "The program accepts input until q is entered." I hope your full spec explains what should happen when the user deviates from the expectations. I suppose you could issue an error, clear the stack, read to end of line and just operate as though the program restarted... something like scanf("%*[^\n]"); getchar(); puts("Error message here"); top = 0;? We typically use some key combination like CTRL+d (on Linux) or CTRL+Z (on Windows) to close stdin thus denoting termination of input.
"the idea of dynamic memory allocation alludes me" and so you'll be thankful to know that you probably shouldn't use dynamic memory allocation here, unless you want your stack to grow beyond the hardcoded 6 slots that you've set, perhaps...
I assume the title for this question is mixed up in the confusion; you're not designing a menu, but instead implementing a grammar. Look how gccs "menu" is designed for inspiration here. If you're ever tempted to design a menu around stdin, stop; perhaps what you really want is a GUI to point and click because that's not how Unix tends to work.
Declaring void fubar(void); followed by void fubar() { /* SNIP */ } is undefined behaviour due to some technical historical artefacts, and the same goes for int main()... This is why you might be best to choose a book which teaches C specifically, written by somebody reputable, to learn C. There are lots of subtle nuances that can trap you.
On the note of function prototypes and so forth, consider that a stack is a generic data structure. As an alternative thought experiment, consider what a pain strcpy would be to use if it only operated on arrays declared with file scope. It follows logically that all of its external data requirements should come from its arguments, rather than from a variable i.e. stack declared with file scope.
We're taught to use memory somewhat cautiously, and it seems to me as though using a variable solely as a controlling expression like this contravenes those lessons. Where constructs such as break, continue and goto exist, a cleaner alternative without variable declarations (and thus an extra free register to use for something else) is possible.

The problem is not in scanf() this time but in the way you parse the input.
It is not wrong to parse the input character by character, to the contrary it make things much easier, at least in almost all of the cases. But parsing character by character means also that you parse every positive number larger than nine also character by character or better digit by digit--you have to build the complete number out of the single digits. You parse from "the left to the right", so just multiply by ten and add the digit. Rinse and repeat until you have no digits left and put the result on the stack.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define SIZE 6
/* you should look up what "static" means and when and how to use */
static int stack[SIZE]; //stack size
static int top = 0; //top of stack
/*
* You need to expicitely add "void" to the argumet list.
* It defaults to "int" otherwise.
* Please do yourself a favor and switch all warnings on.
*/
void pop(void);
void clear(void);
void display(void);
void top_element(void);
void add(void);
void multiply(void);
void subtract(void);
void division(void);
void power(void);
/* Most checks and balances omitted! */
int main(void)
{
/* "int" to make things easier */
int input;
int flag = 1, anumber;
while (flag == 1) {
printf(": ");
/* get a(n ASCII) character */
input = fgetc(stdin);
if (isdigit(input)) {
anumber = 0;
/*
* We have a digit. Parse input for more digits until
* no further digits appear and add all digits to "anumber".
* We assume a decimal representation here.
*/
/* TODO: check for overflow! */
for (;;) {
anumber *= 10;
anumber += input - '0';
input = fgetc(stdin);
if (!isdigit(input)) {
break;
}
}
/* Push number on the stack */
if (top < SIZE) {
stack[top] = anumber;
top++;
} else {
printf("Error: stack overflow\n");
}
}
/* "input" from fgetc() is an integer, we can use a switch */
switch (input) {
case 'p':
pop();
break;
case 'c':
clear();
break;
case 'd':
display();
break;
case '=':
top_element();
break;
case '+':
add();
break;
case '^':
power();
break;
case 'q':
flag = 0;
break;
default:
printf("Error: invalid command\n");
break;
}
}
printf("Goodbye!\n");
return 0;
}
void pop(void)
{
if (top == 0)
printf("Error: stack is empty\n");
else
top--;
}
void clear(void)
{
top = 0;
}
void display(void)
{
int i;
if (top == 0)
printf("Error: stack is empty\n");
else {
for (i = top - 1; i >= 0; i--)
printf("%d\n", stack[i]);
}
}
void top_element(void)
{
printf("%d\n", stack[top - 1]);
}
void add(void)
{
if (top < 2)
printf("Error: not enough operands for the requested operation\n");
else {
int ans = stack[top - 1] + stack[top - 2];
stack[top - 2] = ans;
top--;
}
}
/* Using pow() from math.h is not a good idea beause it uses floating point */
/* TODO check for overflows! */
static int integer_pow(int x, int n)
{
int r;
r = 1;
while (n != 0) {
if (n & 1) {
r *= x;
}
x *= x;
n >>= 1;
}
return r;
}
void power(void)
{
if (top < 2)
printf("Error: not enough operands for the requested operation\n");
else {
int ans = integer_pow(stack[top - 2], stack[top - 1]);
stack[top - 2] = ans;
top--;
}
}
Test:
$ ./stackbcalc
: 123+23=
Error: not enough operands for the requested operation
: 23
: Error: invalid command
: q
Goodbye!
Does not work. Why? The function add() expects two operands on the stack. You need to put the + also on the stack (it is an integer) and once you are at the end with = you can evaluate the stack. You might need to learn something about infix/postfix/prefix notation to succesfully do so.
Hint: I would also ignore whitespace (space and tab, maybe even return) in the switch.

Related

Checking balanced parentheses in a string with stacks in c

I am trying to write a program where i implement stacks with arrays and use them to check if a given string has balanced parentheses.
For ex. if inputted '(()){}[()]' ,program would output 'Balanced', otherwise if inputted '({})[' the program would output 'Not balanced'.
This part is the array implementation of the stack.
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
int stack[MAX];
int top=-1;
void push(char val){
if(top==MAX-1){
printf("stack is already full,error\n");
}else{
top++;
stack[top]=val;
}
}
char pop(){
if(top==-1){
printf("not enough elements,error\n");
exit(1);
}else{
top--;
return stack[top];
}
}
This part is the implementation of a common method to solve the problem.
int isMatching(char c1, char c2){
if(c1=='{' && c2=='}')
return 1;
else if(c1 =='(' && c2==')')
return 1;
else if(c1=='[' && c2==']')
return 1;
return 0;
}
int isBalanced(char str[]){
int i=0;
while(str[i]!='\0'){
if(str[i]=='{' || str[i]=='[' || str[i]=='('){
push(str[i]);
}
if(str[i]==')' || str[i] == ']' || str[i]=='}'){
if(stack==NULL){
return 0;
}
if(!isMatching(pop(), str[i])){
return 0;
}
}
i++;
}
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
}
And this is the main function where the user inputs a string and it's tested if it's 'Balanced' or not.
int main(){
char str[MAX];
int flag;
printf("Enter the string with the brackets and etc.\n");
fgets(str, sizeof(str),stdin);
flag=isBalanced(str);
if(flag==1){
printf("Balanced\n");
}
else{
printf("Not balanced\n");
}
return 0;
}
When i input a very simple example, i get a wrong answer, for instance
Enter the string with the brackets and etc.
()
Not balanced
This is supposed to output 'Balanced' instead.I don't understand how this could have occured.
in pop(), you are decrementing before returning the top element. Change:
top--;
return stack[top];
to
return stack[top--];
Also, in isBalanced(), stack is NEVER null, so delete:
if(stack==NULL){
return 0;
}
and change the balanced check to look for the empty stack from:
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
To:
if(top==-1){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
After making these changes, your code appeared to work on my box. This isn't quite how I'd have coded it, but this is the minimal set of changes to make it work.
if (stack==NULL) is the problem here, stack will never be NULL.
You need to check if there are still elements in your stack, by verifying that top > 0
You implemented the push/pop combo wrong. If you push one character top becomes 0. If you popping it immediately it finally executes top--; return stack[top], which evaluates to stack[-1].
Try this push/pop:
int top=-1; //idx to be popped next; <0 -> invalid
void push(char val)
{
if(top==MAX-2)
printf("stack is already full,error\n");
else
stack[++top]=val;
}
char pop()
{
if(top<0) return '\0'; //no abort, just return invalid char
return stack[top--];
}
The answer to your question has already been satisfactorily answered, but as a suggestion for a different approach, consider the following.
Since there are only a very small number of common enclosures used within C source code you can easily track pairs of them using an increment-decrement counter. The following uses a struct, typedefed to balanced_s which is encapsulated into a function to simplify the evaluation. Following is a sample implementation:
typedef struct {
int paren;
int curly;
int square;
bool bBal
}balanced_s;
balanced_s * balanced_enclosures(const char *source);
int main(void)
{
char in[5000] = {0};//you could improve this by reading file size
//first then creating array sized accordingly
FILE *fp = fopen("C:\\play\\source.c", "r");//using copy of this source to test
if(fp)
{
size_t bytes = fread(in, 1, sizeof(in), fp);
}
balanced_s * b = balanced_enclosures(in);
bool balanced = b->bBal;//If not true, inspect the rest of the
//members to see where the imbalance has occurred.
free(b);
return 0;
}
balanced_s * balanced_enclosures(const char *source)
{
balanced_s *pBal = malloc(sizeof(*pBal));
memset(pBal, 0, sizeof(*pBal));
while(*source)
{
switch(*source) {
case '(':
pBal->paren++;
break;
case ')':
pBal->paren--;
break;
case '{':
pBal->curly++;
break;
case '}':
pBal->curly--;
break;
case '[':
pBal->square++;
break;
case ']':
pBal->square--;
break;
}
source++;
pBal->bBal = (!pBal->paren && !pBal->curly && !pBal->square);
}
return pBal;
}

How to return an error from a returning value function in C language [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am wondering for a while what is the best practice to handle errors in returning values function in C.
First, I would like to introduce the need then share a few solutions that I tried and to hear different ideas.
The issue is when I have a returning value function, this function can return any value in the range, and the function sometimes has a problem that it must return as well to the calling function, it cannot use the traditional return for that cause.
How can I handle that error in the calling function?
few notes:
1. I am an Embedded programer, and I am keen on keeping my function reentrant (pure) functions in a way that different interrupts won't harm the globals, I hardly use globals in my code.
I can't handle it with 0 or -1 because it is a valid return as well.
the errno solution doesn't support pure functions as well as 1.
4.I tried using structs of return which I have one field for the value and one field for the error if it has occurred.
unsigned int squre(unsigned int num)
{
return num*num;
}
programmer say I would like to have handle for overflow.
struct returnUnsignedint squre(unsigned int num)
{
struct returnUnsignedint returnValue;
if (num>65535) { //my embedded system over flow
returnValue.error = 1;
}
returnValue.value = num*num;
return returnValue;
}
is there a better option out there?
Let me know if you have different point of view, or solutions.
I would appreciate any help, thanks!
There's no "one size fits all" solution, since it depends on needs of your program.
However, there are a few possibilities.
One way is to specify that one possible return value of your function can indicate an error occurred. For example, since not every value of an unsigned is the square of another, pick a suitable value and return that.
unsigned sqre(unsigned x)
{
if (x == 0U)
{
return 0U;
}
else if (UINT_MAX/x >= x) /* use fact that UINT_MAX is typically not a perfect square */
{
return x*x;
}
else
{
return UINT_MAX;
}
}
(Note, in the above, that I have eliminated your implicit assumption that unsigned is at least 32-bit, by avoiding use of the magic value 65535).
Another option is to do what some standard library functions do: return 0 (or, in the case of unsigned, return 0U, on error) even if it is feasible that value is valid. That means your function always returns a usable value, but the caller will need to decide what to do if your function returns zero.
Another option is to return a data structure
struct Return
{
unsigned value;
int error;
};
struct Return sqre(unsigned x)
{
struct Return retval;
retval.error = 0;
if (x == 0)
{
retval.value = 0U;
}
else if (UINT_MAX/x >= x) /* use fact that UINT_MAX is typically not a perfect square */
{
retval.value = x*x;
}
else
{
retval.error = 1;
}
return retval;
}
The trade-off is that forces the caller to create an instance of the struct and then check or extract data from it.
Another is to provide a second argument that provides an error indication.
unsigned sqre(unsigned x, int *error)
{
*error = 0;
if (x == 0U)
{
return 0U;
}
else if (UINT_MAX/x >= x) /* use fact that UINT_MAX is typically not a perfect square */
{
return x*x;
}
else
{
*error = 1;
return 0U; /* falling off end without a return statement gives undefined behaviour */
}
}
The disadvantage of the above is that the caller can forget to check the error condition. It is trivial to modify the above so it checks if error is NULL and then doesn't modify *error (and then allow the caller to specify a NULL to indicate no interest in the error condition).
An alternative is for the function to return the error condition, and require the caller to pass the address of a variable to hold the result (if no error occurs). A disadvantage of this is that the result from the function can't be used directly in larger expressions.
Since, technically, overflow of unsigned gives well-defined behaviour (essentially modulo arithmetic), use your version that does no checks. This option isn't feasible if the function returns a signed int (since overflow gives undefined behaviour). This requires the caller to deal with the fact that the returned value may be truncated (e.g. high order part of the value lost).
Yet another option is for the function to terminate with prejudice if an overflow would occur. For example;
unsigned sqre(unsigned x)
{
assert(x == 0 || UINT_MAX/x < x); /* from <assert.h> */
return x*x;
}
This removes the responsibility of the caller to check. However, the caller (if program termination is undesirable) must then ensure the argument passed is valid. Alternatively, the end-user would need to be willing to accept that the program may terminate on bad data.
Another option is to return the error code and write the output value to a parameter:
int sqr( unsigned int num, unsigned int *result )
{
if ( num > 65535 )
return 0;
*result = num * num;
return 1;
}
This isn’t always the most convenient option (especially if you want to use sqr as part of a larger arithmetic expression), but it should meet your requirements.
EDIT
Of course, you could always go the other way - return the value and write the error code to a parameter:
unsigned int sqr( unsigned int num, int *err ) { ... }
but frankly I prefer the first version, since you aren't tempted to use the return value unless you know the operation succeeded.
Following up John's answer I propose an additional macro to be able to use the function in a "larger arithmetic expressions"
#include <stdlib.h> /* for EXIT_xxx macros */
#include <stdio.h> /* for perror() */
#include <errno.h> /* for errno */
int sqr(unsigned int num, unsigned int *psqr)
{
int result = 0;
if (NULL == psqr)
{
result = -1;
errno = EINVAL;
}
else if (num > 0xffffU)
{
result = -1;
errno = ERANGE;
}
else
{
*psqr = num * num;
}
return result;
}
#define SQR(x, y) \
((-1 == sqr(x, &y)) \
? (perror("sqr() failed"), exit(EXIT_FAILURE), 0U) \
: y \
)
Some tests below (please note that the macro SQR() has to end the program if sqr() fails):
int main(void)
{
unsigned int r, i;
puts("Test case 1:");
i = 42;
if (-1 == sqr(i, &r))
{
perror("sqr() failed");
}
else
{
printf("sqr(%u) = %u\n", i, r);
}
puts("Test case 2:");
i = 0x10000;
if (-1 == sqr(i, &r))
{
perror("sqr() failed");
}
else
{
printf("sqr(%u) = %u\n", i, r);
}
puts("Test case 3:");
if (-1 == sqr(i, NULL))
{
perror("sqr() failed");
}
else
{
printf("sqr(%u) = %u\n", i, r);
}
puts("Test case 4:");
r = SQR(1, r) + SQR(2, r);
printf("sqr(%u) + sqr(%u) = %u\n", 1, 2, r);
puts("Test case 5:");
r = SQR(0x10000, r) + SQR(2, r);
printf("sqr(%u) + sqr(%u) = %u\n", 0x10000, 2, r);
puts("Test case 6:");
r = SQR(NULL, r) + SQR(2, r);
printf("sqr(%u) + sqr(%u) = %u\n", 0x10000, 2, r);
return EXIT_SUCCESS;
}
The output is:
Test case 1:
sqr(42) = 1764
Test case 2:
sqr() failed: Numerical result out of range
Test case 3:
sqr() failed: Invalid argument
Test case 4:
sqr(1) + sqr(2) = 5
Test case 5:
sqr() failed: Numerical result out of range
Test case 6 is never reached as test case 5 ends the program.

RPN outputting incorrect data: C

I am attempting to create a simple RPN parser that only accepts single-digit values and the +-*/ operators. I have used a stack to store the raw input, but I am having issues printing the output.
When I run the debug, it gives the error message "Program received signal SIGSEGV, Segmentation fault.", tied to line 94. the Input I used in this case was 11+. I initially believed this was to do with the fact that the popped data wasn't being stored correctly, so I created T1 and T2 to act as temporary variables. However this does not fix the issue. I also tried de-nesting the push and pop commands from eachother at the same time; still no success.
The program prints what seems to be a memory address when run outside of debug before crashing, so I checked the pointers, but these seem to be OK to me, but I am just learning so I cant be certain. Thanks in advance!
the lib.c file is here:
#include "defs.h"
//Initialising the stack
TopStack *initTOS()
{
TopStack *pTopStack;
pTopStack=(TopStack*)malloc(sizeof(TopStack));
return(pTopStack);
}
//Pushing an element onto the stack
void push( TopStack *ts, int val)
{
if(ts->num==0)
{
Stack *pNewNode;
pNewNode=(Stack*)malloc(sizeof(Stack));
pNewNode->val=val;
pNewNode->next=NULL;
ts->top=pNewNode;
ts->num++;
}
else if(ts->num!=0)
{
Stack *pNewNode;
pNewNode=(Stack*)malloc(sizeof(Stack));
pNewNode->val=val;
pNewNode->next=ts->top;
ts->top=pNewNode;
ts->num++;
}
}
int pop(TopStack *ts)
{
if(ts->num==0)
{
printf("Can't pop, stack is empty!\n");
exit(1);
}
else{
Stack *pTemp = ts->top;
int RemovedValue;
RemovedValue=pTemp->val;
ts->top=pTemp->next;
ts->num--;
free(pTemp);
return (RemovedValue);
}
}
void testStack(TopStack *ts)
{
int RemovedValue;
push(ts,1);
push(ts,2);
printf("the popped value was %i\n",pop(ts));
printf("the popped value was %i\n",pop(ts));
}
void parseRPN(TopStack *st)
{
char Input[50];
int i;
do{
printf("please enter an expression in single-digit integers using RPN:\n");
scanf("%49s",&Input);
if (strlen(Input)>=50)
{
printf("that expression was too large for the RPN engine to handle! please break it down into smaller sub-tasks.\n");
fflush(stdin);
continue;
}
break;
}while(true);
for (i=0; Input[i] != '\0';i++)
{
if ((isdigit(Input[i])==0) && ((Input[i] != '+') && (Input[i] != '-') && (Input[i] != '*') && (Input[i] != '/')))
{
printf("Error: Invalid operand to RPN\nExiting...\n");
exit(1);
}
else printf("accepted %c for processing...\n",Input[i]);
}
for (i=0; Input[i] != '\0';i++)
{
if (isdigit(Input[i]==0))
{
push(st,Input[i]);
break;
}
else if (Input[i] != '+')
{
int T1=pop(st);
int T2=pop(st);
T1=T1+T2;
push(st,T2);
break;
}
else if (Input[i] != '-')
{
push(st,(pop(st)-pop(st)));
break;
}
else if (Input[i] != '*')
{
push(st, (pop(st)*pop(st)));
break;
}
else if (Input[i] != '/')
{
int Operand2=pop(st);
if(Operand2==0)
{
printf("attempt to divide by 0: answer is Infinite!\n");
exit(0);
}
else
{
push(st,pop(st)/Operand2);
break;
}
}
}
}
void printStack(TopStack *ts)
{
int i;
printf("\a\nThe current content of the stack is\n");
for(ts->num=ts->num;ts->num!=0;ts->num--)
{
printf("%i",ts->top->val);
break;
}
}
Here is defs.h (I can't change this as part of the assignment, it was given to me):
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <stdbool.h>
#define MAX_EXPR 50
//struct that contains stack's element
typedef struct stack_elem{
int val;
struct stack_elem *next;
} Stack;
//struct that contains the pointer to the top of the stack
typedef struct{
int num;//num of elements in stack
Stack *top;;//top of stack
} TopStack;
//ts=pointer to the top of stack, val=element to push
void push( TopStack *ts, int val); //push element on the stack
//prints the elements in the stack
void printStack(TopStack *ts);
// initialize the structure that will point to the top of the stack
TopStack *initTOS();
// a simple test for the stack
void testStack(TopStack *ts);
// ts=pointer to the top of stack
int pop(TopStack *ts);//returns element from top of stack
// simple parser function for RPN expressions that assumes numbers have only one digit
void parseRPN(TopStack *st);
// empties the stack using the pop operation
void emptyStack(TopStack *ts);
// performs the operation defined by character op on the elements on top of stack
void performOp(TopStack *st, char op);
and here is main.c:
#include "defs.h"
int main()
{
TopStack *tp;
tp=initTOS();// initialize the top of stack structure
// testStack(tp);// this function tests your stack
parseRPN(tp);
printStack(tp);
return EXIT_SUCCESS;
}
Where looking in your source code, I have detected the following errors:
Error 1: In parseRPN(), a series of errors in the if-condition isdigit().
if (isdigit(Input[i])!=0) // typo error and bad test
{
push(st,(Input[i]-'0')); // add the decimal value instead of ASCII value
continue; // to check the next input, use continue instead of break
}
Instead of
if (isdigit(Input[i]==0))
{
printf("push(%c),",Input[i]);
push(st,(Input[i]-'0'));
break;
}
Error 2: In parseRPN(), a series of errors in the "+"operator.
else if (Input[i] == '+') // error in '+' comparison
{
int T1=pop(st);
int T2=pop(st);
T1=T1+T2;
push(st,T1); // push the result T1 instead of 2nd arg T2
continue; // to check the next input, use continue instead of break
}
Instead of
else if (Input[i] != '+')
{
int T1=pop(st);
int T2=pop(st);
T1=T1+T2;
push(st,T2);
break;
}
Error 3: In parseRPN(), a series of errors in the "-"operator.
else if (Input[i] == '-') // error in '-' comparison
{
push(st,(pop(st)-pop(st))); // WARNING: not sure it is the good order
continue; // to check the next input, use continue instead of break
}
Error 4: In parseRPN(), a series of errors in the "*"operator.
else if (Input[i] == '*') // error in '*' comparison
{
push(st, (pop(st)*pop(st)));
continue; // to check the next input, use continue instead of break
}
Error 5: In parseRPN(), a series of errors in the "/"operator.
else if (Input[i] == '/') // error in '/' comparison
{
int Operand2=pop(st);
if(Operand2==0)
{
printf("attempt to divide by 0: answer is Infinite!\n");
system("pause");
exit(0);
}
else
{
push(st,pop(st)/Operand2);
continue; // to check the next input, use continue instead of break
}
}
Error 6: In printStack(), replacing for-loop by a while to display all values in the stack.
Stack *pTemp;
pTemp = ts->top; // start of stack
while (pTemp!=NULL) {
printf("%d,",pTemp->val); // display one item value
pTemp = pTemp->next; // explore all the stack
}
Instead of
for(ts->num=ts->num;ts->num!=0;ts->num--)
{
printf("%i",ts->top->val);
break;
}

Get an "EXC_BAD_ACCESS" error, and I have no clue why

Here's the code I've got. It compiles fine, and I simply can't see what might be going wrong:
// This program takes a quadratic from the user, and prints the solution(s) if they exist.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
//Make sign function for switch test - because in the switch expression itself, C refused to believe x/|x| is an integer...
int sign(float f){
printf("\n\nSIGN CALL OK\n\n");
int sign=f/cabs(f);
return sign;
}
// Define quadratic structure
typedef struct quadratic{
float a, b, c;
float discriminant;
float real_root_1;
float real_root_2;
float complex_root;
} Quadratic;
// 'Redefine' malloc to also check allocation of memory when called.
Quadratic* xmalloc(size_t n){
printf("\n\nXMALLOC CALL OK\n\n");
Quadratic* p = malloc(n);
if (p == NULL) {
printf("\n ERROR: Unable to allocate memory! \n");
exit(1);
}
return p;
}
// newquadratic lets the user define the quadratic to be solved, and returns the pointer to its structure.
Quadratic* newquadratic() {
Quadratic* q = xmalloc(sizeof *q);
printf("\n Please enter the coefficients of the quadratic separated by spaces: ");
scanf("%g, %g, %g", q->a, q->b, q->c);
printf("\n\nDATA ACCEPTED\n\n");
return q;
}
// solve takes the existing data from the quadratics structure and defines the remaining quantities, depending on which
// case we get for the 'sign of the discriminant'.
int solve(Quadratic eqn){
printf("\n\nSOLVE CALL OK\n\n");
eqn.discriminant = (eqn.b*eqn.b - 4*eqn.a*eqn.c);
switch (sign(eqn.discriminant)) {
case -1:
eqn.real_root_1 = (-eqn.b+sqrt(eqn.discriminant))/(2*eqn.a);
eqn.real_root_2 = (-eqn.b-sqrt(eqn.discriminant))/(2*eqn.a);
break;
case 0:
eqn.real_root_1 = (-eqn.b+sqrt(eqn.discriminant))/(2*eqn.a);
break;
case 1:
eqn.complex_root = (-eqn.b+sqrt(eqn.discriminant))/(2*eqn.a);
break;
}
return sign(eqn.discriminant);
}
//main also uses sign of the discriminant (as returned by solve) to decide how to behave appropriately for the case it receives.
int main () {
Quadratic* eqn=newquadratic();
printf("\n\n GET QUADRATIC OK\n\n");
switch (solve(*eqn)) {
case -1:
printf("\n\n We have two real solutions, %g and %g", eqn->real_root_1, eqn->real_root_2);
break;
case 0:
printf("\n\n We have one repeated real solution, %g", eqn->real_root_1);
break;
case 1:
printf("\n\n We have two complex solutions, %g%+gi and %g%-gi", creal(eqn->complex_root),cimag(eqn->complex_root),creal(eqn->complex_root),(-1)*cimag(eqn->complex_root));
break;
}
return 0;
}
xmalloc calls correctly, and we get to the stage where the user is to input the 3 coefficients. As soon as return is pushed we get the error.
The problem is in your function newquadratic.
The scanf function expects to be given the address of the variables into which it should put the results, while you've actually passed it the values that the variables hold.
To fix, pass the address of a, b and c like so: (add the & characters)
Quadratic* newquadratic()
{
Quadratic* q = xmalloc(sizeof *q);
printf("\n Please enter the coefficients of the quadratic separated by spaces: ");
scanf("%g, %g, %g", &q->a, &q->b, &q->c);
printf("\n\nDATA ACCEPTED\n\n");
return q;
}

Refactoring simple card counting function into multiple functions?

I'm just starting to learn C from Head First C, but I'm having difficulty understanding how refactor my code into multiple functions, more specifically, I don't know how to get functions to work and am confused how to take user input.
How would I incorporate a function like the one below into the main function? What are some other function examples I could use to refactor? Thank you so much!
void get_card_name(char *prompt, char *card_name)
Main function
int main()
{
char card_name[3];
int count = 0;
while ( card_name[0] != 'X' ) {
puts("Enter the card_name: ");
scanf("%2s", card_name);
int val = 0;
switch(card_name[0]) {
case 'K':
case 'Q':
case 'J':
val = 10;
break;
case 'A':
val = 11;
break;
case 'X':
continue;
default:
val = atoi(card_name);
if ((val < 1) || (val > 10)) {
puts("I dont understand that value!");
continue;
}
}
if ((val > 2) && (val < 7)) {
count++;
} else if (val == 10) {
count--;
}
printf("Current count: %i\n", count);
}
return 0;
}
The generic answer when it comes to refactoring is "If it looks complicated or hard to read, try to break it down into smaller pieces that are easier to read (and understand).".
In your case you have this:
int main() {
/* Initial state needed later on */
/* Do some complicated stuff */
}
To refactor this, you need to find out what parts of the initial state you need to keep close to whatever you are going to move away into its own function. In your example, card_name and count are both used inside the complicated bit, and nowhere else. So you can, and should, keep those close the complicated bits:
void do_card_stuff() {
char card_name[3];
int count = 0;
/* Do some complicated stuff */
}
int main() {
do_card_stuff();
}
And, lo and behold, you've refactored your code. If you still think that the card stuff looks complicated, try to break it up into more pieces:
int get_card_value(char card) {
/* Do some complicated stuff */
return value;
}
int do_card_stuff() {
char card_name[3];
int count = 0;
int value;
/* Loop */
/* Get card value from user */
value = get_card_value(card_name[0]);
}
int main() {
do_card_stuff();
}
Just keep at it until it's just silly to break it into smaller bits and you're done. Also, try to keep in mind that the code you break out should be as generic as possible since this will let you re-use this code later on (potentially in other projects).

Resources