C Calculator Program with Stack - c

Hi I am completely stuck on this basic calculator. It runs almost perfectly but something goes wrong in the stack when I try inputting "5 / 5 + 9 * 2". The 1 from 5 / 5 seems to disappear when it is supposed to be addes to the 18 for the last loop. Happens for simular inputs like 2 * 2 - 9 / 2. Just need help finding this weird error that I have spent many hours trying to figure out with no luck! Thank you!
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#include <limits.h>
#include <curses.h>
#include<ctype.h>
struct StackNode
{
char* data;
struct StackNode* next;
};
struct StackNode* newNode(char* data)
{
struct StackNode* stackNode =
(struct StackNode*) malloc(sizeof(struct StackNode));
stackNode->data = data;
stackNode->next = NULL;
return stackNode;
}
int isEmpty(struct StackNode *root)
{
return !root;
}
void push(struct StackNode** root, char* data)
{
struct StackNode* stackNode = newNode(data);
stackNode->next = *root;
*root = stackNode;
printf("%s pushed to stack\n", data);
}
char* pop(struct StackNode** root)
{
if (isEmpty(*root))
return NULL;
struct StackNode* temp = *root;
*root = (*root)->next;
char* popped = temp->data;
free(temp);
printf("Popped: %s\n", popped);
return popped;
}
char* peek(struct StackNode* root)
{
if (isEmpty(root))
return NULL;
return root->data;
}
char buffer[64];
char *ca = &buffer[0];
size_t size = 64;
int bufferIndex;
int first = 0;
int isWhiteSpace (char c) {
if ((c == ' ') || (c == '\t') || (c == '\r')) {
return 1;
}
else {
return 0;
}
}
char* getToken() {
char* token = malloc(64);
int i = 0;
while ((isWhiteSpace(buffer[bufferIndex])) && bufferIndex < strlen(buffer)-1) {
bufferIndex++;
}
while (bufferIndex < strlen(buffer)-1) {
int num = isWhiteSpace(buffer[bufferIndex]);
if (num == 0) {
token[i] = buffer[bufferIndex];
i++;
bufferIndex++;
//printf("%s\n", token);
}
else {
bufferIndex++;
break;
}
}
token[i] = '\0';
first++;
return token;
}
int main() {
while (1) {
char* token = "test";
char* postFix = "test";
char* hold = malloc(64);
postFix = malloc(64);
int total = 0;
int pres1 = 0;
int pres2 = 0;
struct StackNode* root = NULL;
printf("Enter line: ");
getline(&ca,&size,stdin);
bufferIndex = 0;
if ((strcmp(token, "quit") == 0)) {
token = getToken();
if (strcmp(token, "") == 0) {
break;
}
else {
printf("Too many arguments. Try again.\n");
}
}
else {
while (strcmp(token, "") != 0) {
token = getToken();
//printf("%s\n", token);
//printf("Top of stack: %s\n", peek(root));
if (isdigit(*token) == 1) {
strcat(postFix, token);
strcat(postFix, " ");
printf("%s\n", postFix);
}
else if (peek(root) == NULL) {
push(&root, token);
}
else {
printf("Peek: %s\n", peek(root));
if (strcmp(token, "*") == 0) {
pres1 = 2;
}
else if (strcmp(token, "/") == 0) {
pres1 = 2;
}
else if (strcmp(token, "-") == 0) {
pres1 = 1;
}
else if (strcmp(token, "+") == 0) {
pres1 = 1;
}
else {
pres1 = 0;
}
if (strcmp(peek(root), "*") == 0) {
pres2 = 2;
}
else if (strcmp(peek(root), "/") == 0) {
pres2 = 2;
}
else if (strcmp(peek(root), "-") == 0) {
pres2 = 1;
}
else if (strcmp(peek(root), "+") == 0) {
pres2 = 1;
}
while((peek(root) != NULL) && (pres2 > pres1)) {
strcat(postFix, peek(root));
strcat(postFix, " ");
pop(&root);
printf("Postfix: %s\n", postFix);
}
push(&root, token);
}
}
do {
//printf("Peek in DO/WHILE: %s\n", peek(root));
strcat(postFix, peek(root));
strcat(postFix, " ");
pop(&root);
} while ((peek(root) != NULL));
printf("Postfix: %s\n", postFix);
//ca = NULL;
token = "1";
bufferIndex = 0;
for (int i = 0; i < strlen(postFix) + 1; i++) {
buffer[i] = postFix[i];
}
//size = strlen(postFix)+1;
//printf("TOKEN: %s\n", token);
while (strcmp(token, "") != 0) {
token = getToken();
if (isdigit(*token) == 1) {
//printf("--Token: %s\n", token);
push(&root, token);
}
else {
int operand1;
//operand1 = malloc(64);
int operand2;
//total = malloc(64);
printf("Peek: %s\n", peek(root));
operand2 = atoi(peek(root));
pop(&root);
printf("Operand2: %d\n", operand2);
if (strcmp(token, "") != 0) {
printf("Peek: %s\n", peek(root));
operand1 = atoi(peek(root));
pop(&root);
printf("Operand1: %d\n", operand1);
printf("Token: %s\n", token);
if (strcmp(token, "+") == 0) {
total = operand1 + operand2;
}
else if (strcmp(token, "/") == 0) {
total = operand1 / operand2;
}
else if (strcmp(token, "-") == 0) {
total = operand1 - operand2;
}
else if (strcmp(token, "*") == 0) {
total = operand1 * operand2;
}
sprintf(hold,"%d",total);
//printf("Peek: %s\n", peek(root));
push(&root, hold);
//pop(&root);
printf("Total: %d\n", total);
}
else {
//printf("Peek: %s\n", peek(root));
break;
}
}
}
}
printf("Total: %d\n", total);
}
return 0;
}
I am supposed to/am using this as a reference for the assignment: http://condor.depaul.edu/ichu/csc415/notes/notes9/Infix.htm

isdigit() should only be tested for zeroness
Instead of:
if (isdigit(*token) == 1) {
use:
if (isdigit((unsigned char)*token)) {
pointers make it easy to overwrite memory used elsewhere
The code does:
char* hold = malloc(64);
and then later on loops doing:
while (/* ... */) {
// ...
sprintf(hold,"%d",total);
push(&root, hold);
// ...
}
This causes all the values stored on the stack to share the same storage and to be overwritten whenever hold is changed.
The allocation must happen on every use:
char *hold;
// ...
while (/* ... */) {
// ...
hold = malloc(64);
sprintf(hold,"%d",total);
push(&root, hold);
// ...
}

Related

Popping a float into a char to use as ascii code gives off a crash

while (!isEmpty(s))
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
This is where the crash happens specifically at the *c line. When i display the stack it has a value of 43.00000 which means it contains the '+' in ASCI code.
I also used these 3 lines above this specific one in two loops which gave no error.
float pop(stack *s)
{
float x = s->top->data;
node *temp = s->top;
s->top = s->top->next;
free(temp);
return x;
}
Here is the pop function.
Also this works in vscode and the crashes happen in codeblocks only
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
typedef struct node
{
float data;
struct node *next;
} node;
typedef struct
{
node *top;
} stack;
node *newNode(float x)
{
node *n = malloc(sizeof(node));
n->data = x;
n->next = NULL;
return n;
}
stack *init()
{
stack *s = malloc(sizeof(stack));
s->top = NULL;
return s;
}
float pop(stack *s)
{
float x = s->top->data;
node *temp = s->top;
s->top = s->top->next;
free(temp);
return x;
}
void push(stack *s, float x)
{
node *n = newNode(x);
if (s->top == NULL)
s->top = n;
else
{
n->next = s->top;
s->top = n;
}
}
float peek(stack *s)
{
float x = s->top->data;
return x;
}
int isEmpty(stack *s)
{
return (s->top == NULL);
}
void display(stack *s)
{
stack *temp = init();
while (!isEmpty(s))
push(temp, pop(s));
while (!isEmpty(temp))
{
printf("%f ", peek(temp));
push(s, pop(temp));
}
printf("\n");
}
int priority(char op)
{
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
if (op == '^')
return 3;
else
return 0;
}
int isOperator(char op[5])
{
if (!strcmp(op, "+") || !strcmp(op, "-") || !strcmp(op, "*") || !strcmp(op, "/") || !strcmp(op, "^") || !strcmp(op, "(") || !strcmp(op, ")"))
return 1;
else
return 0;
}
int isDigit(char digit[20])
{
int i = 0;
if (digit[0] == '-')
i++;
for (i; digit[i] != '\0'; i++)
if (!isdigit(digit[i]) && digit[i] != '.')
return 0;
return 1;
}
char *infixToPostfix(char *infix)
{
char postfix[100] = "", tokens[20][2000], *temptok, *c;
int i = 0;
temptok = strtok(infix, " ");
strcpy(tokens[i++], temptok);
while (temptok != NULL)
{
temptok = strtok(NULL, " ");
if (temptok != NULL)
strcpy(tokens[i++], temptok);
}
int ntok = i;
stack *s = init();
for (i = 0; i < ntok; i++)
{
if (isDigit(tokens[i]) && strcmp(tokens[i], "-"))
{
strcat(postfix, tokens[i]);
strcat(postfix, " ");
}
else if (isOperator(tokens[i]))
{
if (isEmpty(s))
push(s, tokens[i][0]);
else if (tokens[i][0] == '(')
push(s, tokens[i][0]);
else if (tokens[i][0] == ')')
{
while (peek(s) != '(')
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
pop(s);
}
else
{
while (!isEmpty(s) && priority(peek(s)) >= priority(tokens[i][0]) && tokens[i][0] != '(')
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
push(s, tokens[i][0]);
}
}
}
display(s);
system("pause");
while (!isEmpty(s))
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
strcpy(infix, postfix);
return infix;
}
int main()
{
char infixExpr[256] = "";
printf("Enter an expression you want to evaluate or Ctrl+Z to exit: ");
while (fgets(infixExpr, 255, stdin) != NULL)
{
replaceNewLineBySpace(infixExpr);
char *postfix = infixToPostfix(infixExpr);
printf("Postfix : %s\n", postfix);
float result = evaluatePostfix(postfix);
printf("Result: %f\n", result);
system("pause");
// exit(1);
}
return 0;
}

Why gdb showed /stdlib/strtol_l.c: No such file or directory? Do I missing something to install?

I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0, loc=0x7ffff7fb04a0 <_nl_global_locale>)
at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: No such file or directory.
I tried reinstalling gdb to get it working again, but I failed. It still shows the same error message. I later found the problem myself and marked it in the code below. I'm just curious why something like this sometimes happens when I try to debug some string functions? Like strdup, strtok, strtol, etc.. Am I missing something to install? I hope I can solve this problem completely.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char buff[255];
#define NUM_BUCKETS 32
typedef struct Customer {
char* email;
char* name;
int shoesize;
char* food;
struct Customer* next;
} Customer ;
unsigned long hash(char *str) {
unsigned long hash = 0;
int c;
while (*str != '\0') {
c = *str;
hash = ((hash << 5) + hash) + (unsigned char)c;
str++;
}
return hash;
}
Customer *add_friend_to_list(char *email, char *name, int shoesize, char *food, Customer *bucket) {
Customer* customer;
customer = malloc(sizeof(Customer));
customer->name = strdup(name);
customer->food = strdup(food);
customer->shoesize = shoesize;
customer->email = strdup(email);
customer->next = bucket;
return customer;
}
void add_consumer_to_hashtable(char *name, char *food, char *email, int shoesize, Customer **buckets, size_t num_buckets) {
size_t which_bucket = hash(name) % num_buckets;
buckets[which_bucket] = add_friend_to_list(email, name, shoesize, food, buckets[which_bucket]);
}
int main() {
Customer* buckets[NUM_BUCKETS] = {NULL};
int ittime = 0;
FILE *fp = NULL;
fp = fopen("customers.tsv", "r");
while (true) {
fgets(buff, 255, fp);
if (feof(fp)) {
break;
}
ittime++;
}
fclose(fp);
fp = NULL;
char *email = (char *)malloc(5 * sizeof(char));
char *name = (char *)malloc(5 * sizeof(char));
int shoesize;
char *food = (char *)malloc(5 * sizeof(char));
const char s[2] = "\t";
fp = fopen("customers.tsv", "r");
for (int i = 0; i < ittime + 1; i++) { //This line cause the Segmentation Fault
fgets(buff, 255, fp);
char *token;
token = strtok(buff, s);
email = token;
token = strtok(NULL, s);
name = token;
token = strtok(NULL, s);
shoesize = atoi(token);
token = strtok(NULL, s);
food = token;
add_consumer_to_hashtable(name, food, email, shoesize, buckets, NUM_BUCKETS);
}
fclose(fp);
while (true) {
char *cmd = (char *)malloc(5 * sizeof(char));
printf("command: ");
scanf("%s", cmd);
if (strcmp(cmd, "add") == 0) {
char *email1 = (char *)malloc(5 * sizeof(char));
char *name1 = (char *)malloc(5 * sizeof(char));
int shoesize1;
char *food1 = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", email1);
printf("name? ");
scanf(" %[^\n]", name1);
printf("shoe size? ");
scanf("%d", &shoesize1);
printf("favorite food? ");
scanf("%s", food1);
add_consumer_to_hashtable(name1, food1, email1, shoesize1, buckets, NUM_BUCKETS);
free(name1);
free(food1);
free(email1);
} else if (strcmp(cmd, "lookup") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "delete") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
free(cus->email);
free(cus->food);
free(cus->name);
free(cus);
cus->shoesize = EOF;
cus = NULL;
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "list") == 0) {
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
if (cus->next != NULL) {
cus = cus->next;
printf("\n");
} else {
break;
}
}
}
} else if (strcmp(cmd, "quit") == 0) {
break;
} else if (strcmp(cmd, "save") == 0) {
fp = fopen("customers.tsv", "w");
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
fprintf(fp, "%s\t%s\t%d\t%s", cus->email, cus->name, cus->shoesize, cus->food);
if (cus->next != NULL) {
cus = cus->next;
fprintf(fp, "\n");
} else {
break;
}
}
}
fclose(fp);
} else {
printf("unknown command\n");
}
}
for (int i = 0; i < 32; i++) {
Customer *tmp;
Customer *cus = buckets[i];
if (cus == NULL) {
continue;
}
if (cus->next != NULL) {
tmp = cus;
cus = cus->next;
} else {
break;
}
while ((tmp != NULL)) {
if (tmp->shoesize != EOF) {
free(tmp->email);
free(tmp->food);
free(tmp->name);
free(tmp);
}
cus->shoesize = EOF;
cus = NULL;
}
if (tmp != NULL) {
free(tmp);
}
if (cus != NULL) {
free(cus);
}
}
return 0;
}
I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
The error message means:
crash happened inside GLIBC strtol_l_internal() function
GDB can't show you the source of that function because libc6-src (or similar) package is not installed.
Now, looking at the source for strtol_l_internal() is not going to be helpful -- the root cause of the problem is that you called it with incorrect parameter.
You should read man strtol and verify that you satisfied its preconditions.
It looks like you called strtol(NULL, NULL, ...), which is not a valid thing to do. You could use (gdb) up command to find out where the wrong call came from, and fix the caller.

reversed string not being returned in a c function in program of infix to prefix

Below is the code for infix to prefix conversion. My code works fine until the use of reverse function where it does not print any string after copying. I have tried using a for loop to copy the reversed string but the outcome remains the same and the program terminates without giving proper output. Print statements in the reverse function work before copying but not after that. Could anyone let me know where the problem is?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stack{
int size;
int top;
char *arr;
};
void display(struct stack *ptr)
{
if(ptr->top == -1)
{
printf("Stack is Empty");
}
else
{
for(int i = ptr->top ; i>=0 ; i--)
{
printf("Element: %d\n",ptr->arr[i]);
}
}
}
int isEmpty(struct stack *ptr)
{
if(ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr)
{
if(ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
void push(struct stack *ptr,int data)
{
if(isFull(ptr))
{
printf("Stack Overflow");
}
else
{
ptr->top = ptr->top + 1;
ptr->arr[ptr->top] = data;
}
}
char pop(struct stack *ptr)
{
if(isEmpty(ptr))
{
printf("Stack Underflow");
return 0;
}
else
{
char ch = ptr->arr[ptr->top];
ptr->top = ptr->top - 1;
return ch;
}
}
char stackTop(struct stack *ptr)
{
return ptr->arr[ptr->top];
}
int isOperator(char a)
{
if(a == '+'|| a == '-'|| a == '*'|| a == '/')
{
return 1;
}
else
{
return 0;
}
}
int precedence(char a)
{
if(a == '*' || a == '/')
{
return 3;
}
else if(a == '+' || a == '-')
{
return 2;
}
else
{
return -1;
}
}
char * reverse(char exp[])
{
int l = strlen(exp);
int j = 0;
char temp[l];
for(int i=l-1;i>=0;i--,j++)
{
temp[j] = exp[i];
}
temp[j] = '\0';
printf("prefix is %s",temp);
strcpy(exp,temp);
// for(int i=0;i<=l;i++)
// {
// exp[i] = temp[i];
// }
printf("prefix is %s",exp);
return exp;
}
char * infix_prefix(char *infix)
{
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));
sp->size = 100;
sp->top = -1;
sp->arr = (char *) malloc(sp->size * sizeof(char));
char *prefix = (char *) malloc((strlen(infix+1)) * sizeof(char));
infix = reverse(infix);
int i=0;
int j=0;
while(infix[i] != '\0')
{
if(infix[i] == ')')
{
push(sp,infix[i]);
i++;
}
else if(infix[i] == '(')
{
while(!isEmpty(sp) && stackTop(sp) != ')')
{
prefix[j] = pop(sp);
j++;
}
if(!isEmpty(sp))
{
pop(sp);
i++;
}
else
{
printf("Incorrect Expression");
exit(0);
}
}
else if(!isOperator(infix[i]))
{
prefix[j] = infix[i];
i++;
j++;
}
else if(isOperator(infix[i]))
{
while(!isEmpty(sp) && precedence(infix[i])<=precedence(stackTop(sp)))
{
prefix[j] = pop(sp);
j++;
}
push(sp,infix[i]);
i++;
}
else
{
printf("Incorrect expression");
exit(0);
}
}
while(!isEmpty(sp) && stackTop(sp) != '(')
{
prefix[j] = pop(sp);
j++;
}
if(stackTop(sp) == ')')
{
printf("Incorrect expression");
exit(0);
}
prefix = reverse(prefix);
prefix[j] = '\0';
return prefix;
}
int main(void)
{
char *infix = "(x-y/z-k*d)";
printf("prefix is %s",infix_prefix(infix));
return 0;
}
The reverse indeed has a problem: the temp array is defined with a length of l: that's not long enough to store the null terminator at temp[j] after the loop, causing undefined behavior.
There are more problems:
char *prefix = (char *) malloc((strlen(infix+1)) * sizeof(char)); does not allocate enough space for a copy of infix. You should write char *prefix = malloc(strlen(infix) + 1);
infix = reverse(infix); will crash because the argument to infix_prefix is a string literal which must not be modified. You should declare the argument as const char *infix and make a modifiable copy with strdup() if reversing is really needed, which I doubt very much.
Here is a modified version of reverse that performs the reverse operation in place:
char *reverse(char exp[]) {
int i = 0;
int j = strlen(exp);
while (j-- > i) {
char c = exp[j];
exp[j] = exp[i];
exp[i++] = c;
}
return exp;
}

string BUG in c project for school

I need to program a small airport management system for a school project and I have a terrible bug in my code.
As soon as I initialize the airportManager with more than one airport, all the IATA codes in the airports array get the name of the last airport that was input.
I have tried debugging it a lot of time but without any success. Everything is fine until I print the IATA code or use it. I will be glad for any help.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define TEMP_STR_LEN 255
#define IATA_SIZE 3
// Airport struct:
struct Airport
{
char name[TEMP_STR_LEN];
char country[TEMP_STR_LEN];
char iata[IATA_SIZE];
} typedef airport;
// Airport functions:
int compareAirports(airport const *airport1, airport const *airport2)
{
if (strcmp(airport1->iata, airport2->iata) != 0)
return 0;
else
return 1;
}
int compareIataCode(airport *airport1, char const *iata)
{
if (strcmp(airport1->iata, iata) != 0)
return 0;
else
return 1;
}
void NameArrange(char *name)
{
char tmpString[255];
tmpString[0] = '\0';
char *token = strtok(name, " ");
int i, place = 0, strTotalLen = 0, lastTokenLen = 0;
while (token != NULL)
{
place++;
if (strlen(token) % 2 == 0)
{
for (i = 0; i < strlen(token) - 1; i++)
{
if (token[i] >= 'a' && token[i] <= 'z')
{
token[i] -= 32; // by ascii table
}
if ((token[i + 1] >= 'A' && token[i + 1] <= 'Z'))
token[i + 1] += 32; // by ascii table
i++;
}
}
else if (token[0] >= 'a' && token[0] <= 'z')
token[0] -= 32;
if (place != 1)
strcat(tmpString, " ");
strncat(tmpString, token, strlen(token));
strTotalLen += strlen(token);
lastTokenLen = strlen(token);
token = strtok(NULL, " ");
}
strTotalLen += (place - 1) * 2;
if (lastTokenLen % 2 != 0)
tmpString[strTotalLen - lastTokenLen] += 32;
strcpy(name, tmpString);
}
// ***Airport manager struct***
struct AirportManager
{
int airportsCount;
airport *airportArr;
} typedef airportMan;
// airportManager functions
void addAirport(airportMan *airportManager, airport *airportToAdd)
{
airportManager->airportArr = (airport *) realloc(airportManager->airportArr, (airportManager->airportsCount + 1) * (sizeof(airport)));
strcpy(airportManager->airportArr[airportManager->airportsCount].name, airportToAdd->name);
strcpy(airportManager->airportArr[airportManager->airportsCount].country, airportToAdd->country);
strcpy(airportManager->airportArr[airportManager->airportsCount].iata, airportToAdd->iata);
airportManager->airportsCount++;
printf(" BUG!!! %s\n", airportManager->airportArr[0].iata);
}
bool airportFind(airportMan *airportManager, char *iataCode)
{
int i;
printf("%s", airportManager->airportArr[0].iata );
char airportIata[IATA_SIZE];
char airportIata2[IATA_SIZE];
strcpy(airportIata, iataCode);
strcpy(airportIata2, airportManager->airportArr[0].iata);
if (strcmp(airportIata, airportIata2) == 0)
return true;
// for (i = 1; i < airportManager->airportsCount; i++) {
// printf("%s",airportManager->airportArr[0].iata );
// return true;
// }
puts("Airport not found");
return false;
}
bool checkDuplicatedIata(const airportMan *airportManger, const char *iata)
{
// checks if there is already airport with the same iata code as the input
int i;
for (i = 0; i < airportManger->airportsCount; i++)
{
if (compareIataCode(&(airportManger->airportArr[i]), iata))
{
puts("This IATA code is already exists, please try again");
return true;
}
}
return false;
}
bool checkIataSize(const char *iata)
{
if (strlen(iata) != IATA_SIZE)
{
puts("The IATA code must be 3 letters");
return false;
}
return true;
}
bool checkIataLetters(const char *iata)
{
// checks if all the letters in a given iata code are all capital
int i;
for (i = 0; i < strlen(iata); i++)
{
if (iata[i] >= 'a' && iata[i] <= 'z')
{
puts("The IATA code must be in capital letters");
return false;
}
}
return true;
}
bool checkIataOk(const char *iata, const airportMan *airportManager)
{
if (checkDuplicatedIata(airportManager, iata) == false
&& checkIataSize(iata) && checkIataLetters(iata))
return true;
else
return false;
}
airport *initAirport(airportMan *airportManager)
{
// asks the user to input an airport
airport *iniAirport;
iniAirport = (airport *) malloc(sizeof(airport));
char tmpStr[TEMP_STR_LEN];
char *ptr;
bool iataOk = false;
printf("please enter airport details (press enter to confirm):\nName:");
fflush(stdin);
fgets(tmpStr, 255, stdin);
if ((ptr = strchr(tmpStr, '\n')) != NULL)
*ptr = '\0';
strcpy(iniAirport->name, tmpStr);
NameArrange(iniAirport->name);
printf("Country:");
fgets(iniAirport->country, 255, stdin);
if ((ptr = strchr(iniAirport->country, '\n')) != NULL)
*ptr = '\0';
while (!iataOk)
{
printf("IATA code:");
fgets(iniAirport->iata, TEMP_STR_LEN, stdin);
fflush(stdin);
if ((ptr = strchr(iniAirport->iata, '\n')) != NULL)
*ptr = '\0';
iataOk = checkIataOk(iniAirport->iata, airportManager);
}
return iniAirport;
}
airportMan *initAirportManager()
{
airportMan *airportManager = (airportMan *) malloc(sizeof(airportMan));
if (airportManager == NULL)
return NULL;
airportManager->airportsCount = 0;
int airportsCount = 0, i = 0;
puts("Please enter how much airports you want to add");
scanf("%d", &airportsCount);
getchar();
for (i = 0; i < airportsCount; i++)
{
airport *airport = initAirport(airportManager);
addAirport(airportManager, airport);
}
return airportManager;
}
// ****Struct date*******
struct Date
{
int day;
int month;
int year;
} typedef date_t;
bool checkDateFormat(char *dateString)
{
char tmpString[TEMP_STR_LEN] = "";
strcpy(tmpString, dateString);
char *token = strtok(tmpString, "/");
if (strlen(token) == 2)
{
token = strtok(NULL, "/");
if (strlen(token) == 2)
{
token = strtok(NULL, "/");
if (strlen(token) == 4)
return true;
puts("Please enter the date in the correct format");
return false;
}
puts("Please enter the date in the correct format");
return false;
}
puts("Please enter the date in the correct format");
return false;
}
bool checkDate(date_t *date)
{
int daysArr[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (date->month > 0 && date->month <= 12)
{
if (date->day > 0 && date->day <= daysArr[date->month - 1])
{
if (date->year >= 2020)
return true;
puts("Invalid year, please try again");
return false;
}
puts("Invalid day, please try again");
return false;
}
puts("Invalid month, please try again");
return false;
}
date_t *initDate()
{
date_t *date;
char tmpDateString[TEMP_STR_LEN];
char *ptr;
bool checkFormat = false;
bool checkValid = false;
date = (date_t *) malloc(sizeof(date_t));
while ((!checkFormat) || (!checkValid))
{
puts("Please enter date in the following format: dd/mm/yyyy ");
fgets(tmpDateString, TEMP_STR_LEN, stdin);
if ((ptr = strchr(tmpDateString, '\n')) != NULL)
*ptr = '\0';
checkFormat = checkDateFormat(tmpDateString);
char *token = strtok(tmpDateString, "/");
date->day = atoi(token);
token = strtok(NULL, "/");
date->month = atoi(token);
token = strtok(NULL, "/");
date->year = atoi(token);
checkValid = checkDate(date);
}
return date;
}
// ***Flight struct***
struct Flight
{
char departureAirport[TEMP_STR_LEN];
char arrivalAirport[TEMP_STR_LEN];
int takeofTime;
date_t *date;
} typedef flight_f;
// ***flight functions
bool checkTakeOffTime(const flight_f *flight)
{
if ((flight->takeofTime >= 0 && flight->takeofTime <= 23))
return true;
puts("Invalid time");
return false;
}
bool compareFlightIata(const char *srcIata, const char *destIata)
{
return strcmp(srcIata, destIata) == 0;
}
bool compareFlightPath(const char *srcIata, const char *destIata)
{
if (compareFlightIata(srcIata, destIata))
{
puts("Flight must have different destination and source airports ");
return false;
}
return true;
}
flight_f *initFlight(airportMan *airportManager)
{
flight_f *flight;
char *ptr;
bool checkIata = false;
bool takeoffCheck = false;
bool airportExists = false;
flight = (flight_f *) malloc(sizeof(flight_f));
puts("Please enter flight details ");
while (!checkIata || !airportExists)
{
puts("\nSrc airport:");
fgets(flight->departureAirport, TEMP_STR_LEN, stdin);
if ((ptr = strchr(flight->departureAirport, '\n')) != NULL)
*ptr = '\0';
checkIata = (checkIataSize(flight->departureAirport)
&& checkIataLetters(flight->departureAirport));
if (checkIata)
airportExists = airportFind(airportManager, flight->departureAirport);
}
checkIata = false;
airportExists = false;
while (!checkIata || !airportExists)
{
puts("\nDec airport:");
fgets(flight->arrivalAirport, TEMP_STR_LEN, stdin);
if ((ptr = strchr(flight->arrivalAirport, '\n')) != NULL)
*ptr = '\0';
checkIata = (checkIataSize(flight->arrivalAirport)
&& checkIataLetters(flight->arrivalAirport)
&& compareFlightPath(flight->departureAirport,
flight->arrivalAirport));
if (checkIata)
airportExists = airportFind(airportManager, flight->arrivalAirport);
}
while (!takeoffCheck)
{
puts("\nTakeoff time: ");
scanf("%d", &flight->takeofTime);
getchar();
takeoffCheck = checkTakeOffTime(flight);
}
flight->date = initDate();
return flight;
}
bool checkFlightPath(flight_f flight, char const *departureFrom,
char const *arrivingTo)
{
if (strcmp(flight.departureAirport, departureFrom) == 0
&& strcmp(flight.arrivalAirport, arrivingTo) == 0)
return true;
else
return false;
}
int flightPathFind(flight_f **flightsArr, char const *departureFrom,
char const *arrivingTo, int size)
{
int count = 0;
int i;
for (i = 0; i < size; i++)
{
if (checkFlightPath((*flightsArr)[i], departureFrom, arrivingTo))
{
count++;
}
}
return count;
}
// Struct airline
struct Airline
{
char name[TEMP_STR_LEN];
int filghtsCount;
flight_f **flightsArr;
} typedef airline_a;
void addFlightToAirline(airline_a *airline, airportMan *airportManager)
{
airline->flightsArr = (flight_f **) realloc(airline->flightsArr,
(airline->filghtsCount + 1) * sizeof(flight_f *));
flight_f *flightToAdd = initFlight(airportManager);
airline->flightsArr[airline->filghtsCount] = flightToAdd;
airline->filghtsCount++;
}
void airlineFlightsCount(airline_a *airline, char const *departureFrom,
char const *arrivingTo)
{
int i;
int count = 0;
for (i = 0; i < airline->filghtsCount; i++)
{
if (checkFlightPath(*(airline->flightsArr[i]), departureFrom, arrivingTo))
count++;
}
printf("%s airline has %d flights in that path\n", airline->name, count);
}
airline_a *initAirline()
{
airline_a *airline;
airline = (airline_a *)malloc(sizeof(airline_a));
if (airline == NULL)
return NULL;
char *ptr;
puts("Please enter airline name:");
fgets(airline->name, TEMP_STR_LEN, stdin);
if ((ptr = strchr(airline->name, '\n')) != NULL)
*ptr = '\0';
airline->filghtsCount = 0;
airline->flightsArr = NULL;
return airline;
}
int main()
{
airportMan *airportManager = initAirportManager();
return 0;
}

AddNumber function in program not working

I am having trouble understanding what I should do in the AddNumber function of my program. When the AddNumber function is called in main a pointer variable previous is created, and it takes the user's input and points it at the address of the variable newNum. I created an if statement for it to do that, but I was informed it doesn't do anything.
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
typedef struct A_NewNumber{
struct A_NewNumber *next;
double newNum;
} NewNumber;
NewNumber *AddNumber(NewNumber *previous, char *input){
//char input[16];
//double numEntered = 0;
NewNumber *newNum = malloc(sizeof(NewNumber));
sscanf(input, "%lf", &newNum->newNum);
//sscanf(input, "%s", newNum->enterNumber);
//numEntered = atof(input);
/*if (previous != NULL){
previous->newNum;
}*/
newNum->next = NULL;
newNum->newNum = 0;
return newNum;
}
void PrintList(NewNumber *start){
NewNumber *currentNumber = start;
int count = 0;
while(currentNumber != NULL){
count++;
printf("Numbers:%lf\n",
currentNumber->newNum);
currentNumber = currentNumber->next;
}
printf("Total Numbers Entered%d\n", count);
}
void CleanUp(NewNumber *start){
NewNumber *freeMe = start;
NewNumber *holdMe = NULL;
while(freeMe != NULL){
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
}
int main(){
//indexNum = 0;
char command[16];
char input[16];
//float userInput;
NewNumber *userEnter = NULL;
NewNumber *start = NULL;
NewNumber *newest = NULL;
while(fgets(input, sizeof input, stdin)){
printf("Please enter a number->");
printf("Enter 'quit' to stop or 'print' to print/calculate");
sscanf(input, "%s", command);
if(newest == NULL){
start = AddNumber(NULL, input);
newest = start;
}else{
newest = AddNumber(newest, input);
}if(strncmp(command, "print", 5) == 0){
PrintList(start);
}else if(strncmp(command, "quit", 4)== 0){
printf("\n\nQuitting....\n");
break;
//userInput = enterNumber;
}
}
CleanUp(start);
return 0;
}
}
It was not that bad, was just in need of a bit of clean-up.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// ALL CHECKS OMMITTED!
typedef struct A_NewNumber {
struct A_NewNumber *next;
double newNum;
} NewNumber;
NewNumber *AddNumber(NewNumber * previous, char *input)
{
int res;
// allocate new node
NewNumber *newNum = malloc(sizeof(NewNumber));
if (newNum == NULL) {
fprintf(stderr, "Malloc failed in AddNUmber()\n");
return previous;
}
// convert input string to float
res = sscanf(input, "%lf", &newNum->newNum);
if (res != 1) {
fprintf(stderr, "Something bad happend in AddNUmber()\n");
return previous;
}
// terminate that node
newNum->next = NULL;
// if this is NOT the first node
// put new node to the end of the list
if (previous != NULL) {
previous->next = newNum;
}
// return pointer to new node at end of the list
return newNum;
}
void PrintList(NewNumber * start)
{
NewNumber *currentNumber = start;
int count = 0;
while (currentNumber != NULL) {
count++;
printf("Numbers:%lf\n", currentNumber->newNum);
currentNumber = currentNumber->next;
}
printf("Total Numbers Entered %d\n", count);
}
void CleanUp(NewNumber * start)
{
NewNumber *freeMe = start;
NewNumber *holdMe = NULL;
while (freeMe != NULL) {
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
}
int main()
{
char input[16];
NewNumber *start = NULL;
NewNumber *newest = NULL;
int res;
// infinite loop
while (1) {
// give advise
printf("Please enter a number or\n");
printf("'quit' to stop or 'print' to print/calculate\n");
// get input from user
res = scanf("%s", input);
if (res != 1) {
if (res == EOF) {
fprintf(stderr, "Got EOF, bailing out\n");
break;
} else {
fprintf(stderr, "something bad happend, bailing out\n");
break;
}
}
// check if a command was given
if (strncmp(input, "print", 5) == 0) {
PrintList(start);
continue;
} else if (strncmp(input, "quit", 4) == 0) {
printf("\n\nQuitting....\n");
break;
}
// otherwise gather numbers
if (newest == NULL) {
start = AddNumber(NULL, input);
if (start == NULL) {
fprintf(stderr, "AddNumber returned NULL\n");
break;
}
newest = start;
} else {
newest = AddNumber(newest, input);
if (newest == NULL) {
fprintf(stderr, "AddNumber returned NULL\n");
break;
}
}
}
CleanUp(start);
return 0;
}
You should really make a habit of checking all returns and if you don't: be able to give a good reason why you didn't.
Don't forget to switch on all warnings your compiler offers. Even if you don't understand them now, Google might have an answer and if not some people here do (in that order, thank you).

Resources