Switch case for string using keyfromString function - c

I have use this code to use switch case for a string
#define BADKEY -1
#define b 1
#define s 2
#define r 3
#define p 4
typedef struct { char *key; int val; } t_symstruct;
static t_symstruct lookuptable[] = {
{"b",b},{"s",s},{"r",r,{"p",p}
};
#define NKEYS (sizeof(lookuptable)/sizeof(t_symstruct))
int main () {
what is a mistake here?
int keyfromstring(char *key)
{
int i;
for (i=0; i < NKEYS; i++) {
if (strcmp(lookuptable[i].key, key) == 0)
return lookuptable[i].val;
}
return BADKEY;
}
switch case in c
switch (keyfromstring(field1))
{
case b :
printf(" is b\n" );
break;
case s :
printf("is s\n" );
break;
case r :
printf(" is r\n" );
break;
case ps:
printf("is p\n" );
break;
case BADKEY:
printf("Case: BADKEY \n");
break;
default://case if nothing
printf("Case: nothing happen\n");
}
**I got this message error segmentation fault(core dumped)
after printing some lines correctly,so please what can be the error here?

check the field1 before passing to the function there could be some issue with that. I am not seeing any error here . plus you did not clearly mention when it will crash
if you got the error segmentation fault(core dumped) once at the end of printing the switch case .you could be getting null at the end
check if feild1 is null .

The lookuptable has typos, it should like:
static t_symstruct lookuptable[] = {
{"b",b}, {"s",s}, {"r",r}, {"p",p}
};
Your original version will not even compile. The testing program is presented below:
#include <stdio.h>
#include <string.h>
#define BADKEY -1
#define b 1
#define s 2
#define r 3
#define p 4
typedef struct {
char *key;
int val;
} t_symstruct;
static t_symstruct lookuptable[] = {
{"b",b}, {"s",s}, {"r",r}, {"p",p}
};
#define NKEYS (sizeof(lookuptable)/sizeof(t_symstruct))
int keyfromstring(char *key)
{
int i;
for (i=0; i < NKEYS; i++) {
if (strcmp(lookuptable[i].key, key) == 0)
return lookuptable[i].val;
}
return BADKEY;
}
int main (void) {
char * arr[] = { "b","s","r", "p", "!", NULL} ;
int i;
for (i =0; arr[i] !=NULL; i++)
{
switch (keyfromstring(arr[i]))
{
case b :
printf("%s is b\n", arr[i] );
break;
case s :
printf("%s is s\n", arr[i] );
break;
case r :
printf("%s is r\n", arr[i] );
break;
case p:
printf("%s is p\n", arr[i] );
break;
case BADKEY:
printf("Case: BADKEY: %s \n", arr[i] );
break;
default://case if nothing
printf("Case: nothing happen\n");
break;
}
}
return 0;
}
Test:
b is b
s is s
r is r
p is p
Case: BADKEY: !

Related

How to output elements inside of stack during RPN Calculating

I implemented an RPN Calculator in C. Now I want to output the current iteration meaning
Iteration 1: Contents: [5, 5]
Iteration 2: Contents: [25]
I am not quite sure how i am going to print them. I tried Printing them in the main function, but the output was coming
Iteration 1: Contents: 5
Iteration 2: Contents: 5
10
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_SIZE 100
int stack[MAX_SIZE];
int top = 0;
void makeEmpty()
{
top = 0;
}
bool isEmpty()
{
return top == 0;
}
bool isFull()
{
return top == MAX_SIZE;
}
void push(int value)
{
stack[top++] = value;
}
int pop()
{
if(isEmpty())
{
printf("Not enough operands in expression\n");
exit(EXIT_FAILURE);
}
return stack[--top];
}
//adds 2 integers
int add(int a, int b)
{
return a + b;
}
//subtracts 2 integers
int sub(int a, int b)
{
return a - b;
}
//multiplies 2 integers
int mul(int a, int b)
{
return a * b;
}
//divides 2 integers
int divide(int a, int b)
{
return a / b;
}
int main(void)
{
char ch;
while(1)
{
//Emptying the stack before the user enters another expression
makeEmpty();
printf("Enter an RPN expression: ");
//Reads expression from user
scanf("%c", &ch);
//parse all characters until a newline is reached
while(1)
{
if(ch == '\n')
break;
//if character is an integer
if(ch >= 48 && ch <= 57)
{
if(!isFull())
{
//convert char to int and push integer onto stack
printf("Iteration %d: Contents: %d \n", (top+1), (ch-48));
push(ch - 48);
}
else
{
//stack ran out of space, print error and exit program
printf("Expression is too complex\n");
exit(EXIT_FAILURE);
}
}
switch(ch)
{
case '+':
push(add(pop(), pop()));
break;
case '-':
push(sub(pop(), pop()));
break;
case '*':
push(mul(pop(), pop()));
break;
case '/':
push(divide(pop(), pop()));
break;
case '=':
printf("%d\n", pop());
break;
}
//get next character
scanf("%c", &ch);
}
}
return 0;
}
You can easily workaround it in your program without creating temporary stacks:
void print_stack(void)
{
printf("[");
for(int index = top -1; index >= 0; index--)
{
printf("%d%s", stack[index], index ? ", " : "");
}
printf("]\n");
}

When trying to print from string getting error: Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

I'm writing a function that receives a format normally seen in a printf call and a string of integers separated by an inconsistent amount of spaces. It prints the format how it would've been printed from printf with the correct representation of the integers.
I first tried to create the extractNums function that returns an array of all the integers from the second string sent to the printFormattedIntegers function.
But later in printFormattedIntegers I get a Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT error when I simply try to print the first element of the format string. I found that if I comment out the extractNums function call, I get no error and it works.
I'm not sure why the extractNums call interrupts the rest of the program, any ideas?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define I 1
#define V 5
#define X 10
#define L 50
#define C 100
#define D 500
#define M 1000
void printFormattedIntegers(char* format, char numbers[]);
char converter(char c, int num);
int charToInt(char* str);
int* extendArr(int* arr, int currSize);
int* extractNums(char* nums);
void printDecAsBin(int num);
void printDEC(int num);
void printHEX(int num);
void printOCT(int num);
void printBIN(int num);
void printROM(int num);
void main()
{
char format[100];
char numbers[100];
printFormattedIntegers("Dec: %d Hex: %x Roman: %r", " 123 10 9");
}
void printFormattedIntegers(char* format, char* numbers)
{
int formatInd = 0, numsInd = 0;
int* numsArr = extractNums(numbers);
while (format[formatInd] != '\0')
{
if (format[formatInd] != '%')
printf("%c",format[formatInd]);
else
{
converter(format[formatInd+1], numsArr[numsInd]);
numsInd++;
}
formatInd++;
}
}
char converter(char c, int num)
{
switch(c)
{
case 'd':
printDEC(num);
break;
case 'x':
printHEX(num);
break;
case 'o':
printOCT(num);
break;
case 'b':
printBIN(num);
break;
case 'r':
printROM(num);
break;
case '\0':
printf("%%");
break;
default:
printf("%%%c",c);
break;
}
}
int charToInt(char* str)
{
int mult = 1;
int re = 0;
int len = strlen(str);
for(int i = len -1 ; i >= 0 ; i--)
{
re = re + ((int)str[i] -48)*mult;
mult = mult*10;
}
return re;
}
int* extendArr(int* arr, int currSize)
{
int* newArr;
int i;
newArr = (int*)malloc((currSize+1) * sizeof(int));
if (newArr == NULL)
{
printf("Memory allocation failed.\n");
exit(1);
}
for (i=0;i<currSize;i++)
newArr[i] = arr[i];
free(arr);
return newArr;
}
int* extractNums(char* nums)
{
char *copiedStr, *token;
int *newArr=NULL,counter = 0, intChar;
char sep[] = " ";
strcpy(copiedStr,nums);
token = strtok(copiedStr,sep);
while (token != NULL)
{
intChar = charToInt(token);
newArr = extendArr(newArr,counter);
newArr[counter] = intChar;
counter++;
token = strtok(NULL,sep);
}
}
void printDecAsBin(int num)
{
if (num == 0)
printf("0");
else if (num == 1)
printf("1");
else
{
printDecAsBin(num / 2);
printf("%d", num % 2);
}
}
void printDEC(int num)
{
printf("%d", num);
}
void printHEX(int num)
{
printf("%x", num);
}
void printOCT(int num)
{
printf("%o", num);
}
void printBIN(int num)
{
printDecAsBin(num);
}
void printROM(int num)
{
while (num >= M)
{
num -= M;
printf("M");
}
if (num >= M - C)
{
printf("CM");
num -= (M - C);
}
else if (num >= D)
{
printf("D");
num -= D;
}
while (num >= C)
{
num -= C;
printf("C");
}
if (num >= C - X)
{
printf("XC");
num -= (C - X);
}
else if (num >= L)
{
printf("L");
num -= L;
}
while (num >= X)
{
num -= X;
printf("X");
}
if (num >= X - I)
{
printf("IX");
num -= (X - I);
}
else if (num >= V)
{
printf("V");
num -= V;
}
while (num > 0)
{
num -= I;
printf("I");
}
}
You are writing to unallocated memory. That invokes Undefined Behaviour and from that point anything can happen at any moment:
int* extractNums(char* nums)
{
char *copiedStr, *token; // copiedStr is an initialized pointer here
int *newArr=NULL,counter = 0, intChar;
char sep[] = " ";
strcpy(copiedStr,nums); // use of the initialized pointer: UB!

Using * in main() parameters for command-line calculator

I'm doing a homework problem which is to create a calculator using the argc and argv[] parameters in the main function.
What we were supposed to do, and I did, was to create a char pointer array containing the operators I want to use.
this is what I have:
const int OTabMax = 10;
const char *OTab[] = {
"+",
"-",
"*",
"/",
"quad",
"wurz",
"sinR",
"sinG",
"cosR",
"cosG"
};
int OTabCheck(char S[]) // char *S
{
int n;
for (n = 0; n < OTabMax; n++){
if (strcmp(S, OTab[n]) == 0) {break;}
}
return n;
}
It returns a number depending on which operator was used, which goes into a switch case where the calculation is done.
looks like this:
switch(key){
case 0:
break;
case 1:
break;
case 2:
x = atof(argv[1]);
y = atof(argv[3]);
z = 0;
z = x*y;
printf("%f * %f = %f\n",x,y,z);
break;
case 3-8;
break;
case 9:
break;
default: printf("Wrong input!\n"); exit(0); break;
}
The case in question is case 2: which whenever I do a calculation like calling the program through the terminal with ./"program_name" 2 * 2
it printf's 2.000000 * 0.000000 = 2.000000
here is the MRE:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const int OTabMax = 10;
const char *OTab[] = {
"+",
"-",
"*",
"/",
"quad",
"wurz",
"sinR",
"sinG",
"cosR",
"cosG" };
int OTabCheck(char S[]) // char *S
{
int n;
for (n = 0; n < OTabMax; n++){
if (strcmp(S, OTab[n]) == 0) {break;}
}
return n;
}
int main(int argc,char *argv[]){
float x = 0;
float y = 0;
float z = 0;
int key = 0;
if(argc < 3){
exit(0);
}
if(argc == 4){
key = OTabCheck(argv[2]);
}else if(argc == 3){
key = OTabCheck(argv[1]);
}
switch(key){
case 2:
x = atof(argv[1]);
y = atof(argv[3]);
z = 0;
z = x*y;
printf("%f * %f = %f\n",x,y,z);
exit(0);
break;
default: printf("Wrong input!\n"); exit(0); break;
}
}

Simple program crashes after using switch - C

I just have written a program which suppose to return char which appears the most/least. Program work during the testing without switch statement, but when I added it start to crash. Can you have a look?
Main function
#include <stdio.h>
#include <stdlib.h>
#include "tools.h"
int main(int argc, char *argv[]) {
int count[256] = { 0 };
int c;
while ( (c=getchar())!=EOF ){
count[c]++;
}
switch (argv[1][1]) {
case 'm': case 'M':
mostOften(count);
break;
case 'l': case 'L':
leastOften(count);
break;
default:
mostOften(count);
break;
}
return 0;
}
Tools function
#include <stdio.h>
#include <stdlib.h>
#include "tools.h"
void mostOften(int *s) {
int j;
int max, cha;
for(j=32; j<126; j++){
if(s[j]>max) {
max=s[j];
cha=j;
}
}
printf("char %c: %d times\n", cha, max);
}
void leastOften(int *s) {
int j;
int min=10000, cha;
for(j=32; j<126; j++){
if(s[j] && s[j]<=min) {
min=s[j];
cha=j;
}
}
printf("char %c: %d times\n", cha, min);
}
You are using max uninitialized, thus, reading garbage:
int max, cha;
for(j=32; j<126; j++){
if(s[j]>max) {
Also, you need to check if argv[1][1] exists before using it:
switch ((argc > 1 && argv[1][0]) ? argv[1][1] : 0) {

What is wrong with my program implementing a stack in C

Hi i have a problem with my stack data structure program. It seems that when i define the size of my array/the imaginary size of array just to call it through a loop the size i defined or specified by the user is being depleted or somewhat edited when i enter a data or push.
For ex. i entered 5 for the size and choose push and then add 2. It is working properly. But if i choose to push data again, it is now passing to the size variable. I do not know understand what is happening...
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#define p printf
#define s scanf
int top;
int ar[1];
int size;
main()
{
void push();
int opt, num;
char cont[] = { 'y' };
clrscr();
p("Stacking Program");
p("\n\nData Size: ");
s("%d", &size);
p("\n");
while((cont[0] == 'y') || (cont[0] == 'Y'))
{
clrscr();
p("Stacking Program");
p("\n\nData Size: %d\n\n", size);
p("MAIN MENU\n1. Pop\n2. Push\n3. Pick\n4. View\nChoose: ");
s("%d", &opt);
p("\n");
switch(opt) {
case 1:
pop();
break;
case 2:
if(top > size)
{
p("You can't push more data");
}
else
{
p("Enter data for Data[%d]: ", top);
s("%d", &num);
push(num);
}
break;
case 3:
pick();
break;
case 4:
view();
break;
default:
p("Your choice is not in the list.");
break;
}
p("\n\nDo you want continue\(Y\/N\)?");
s("%s", &cont[0]);
}
}
pop()
{
int a;
if(top < 0)
{
p("Stack empty.");
return 0;
}
else
{
a = ar[top];
p("\(Data[%d] = %d\) removed.", top, a);
top--;
}
}
void push(int b)
{
top++;
ar[top] = b;
}
pick()
{
if(top < 0)
{
p("Nothing to display.");
return 0;
}
else
{
p("\(Data[%d] = %d\) is the last data.", top, ar[top]);
}
}
view()
{
int i;
if(top < 0)
{
p("Nothing to display.");
return 0;
}
else
{
for(i = 1; i < (top + 1); i++)
{
p("Data[%d] = %d\n", i, ar[i]);
}
}
}
You need to define the size of the array at runtime, using the size entered by the user.
instead of:
int top;
int ar[1];
int size;
...
int top = -1;
int *ar = NULL;
int size = 0;
and then after getting size from the user:
if ( size > 0 )
{
ar = malloc(size * sizeof(int));
if ( ar == NULL )
{
printf("ERROR: malloc() failed\n");
exit(2);
}
}
else
{
printf("ERROR: size should be positive integer\n");
exit(1);
}
....
p("\n\nDo you want continue(Y/N)?");
s("%s", &cont[0]);
}
free(ar);
} // end of main
I think the for loop in view() should be:
for(i = 0 ; i <= top ; i++)
also
case 2:
if ( top == ( size - 1 ))
If you don't want to dynamically size the array, another approach is to allocate an array with MAXSIZE elements, where MAXSIZE is "big enough". Also, some other comments:
You declared at the top of your program a character array of size 1:
char cont[] = { 'y' };
But in your scanf line later you try to use this:
s("%s", &cont[0]);
This will overflow your buffer even if the user types just one character, because %s assumes that the buffer has at least two bytes available, one for the character and one for the '\0'. Possible fix:
char cont[] = { 'y', '\0' };
// ...
s("%1s", cont);
Note that cont is the same and more common way of saying &cont[0].
Another problem is with things that might be caught by the compiler if warnings are turned on: all functions should be prototyped before they are mentioned, functions without explicit return type should be declared with type int, and you should not let a function drop off without returning a value even though you declared it to explicitly or implicitly. Also, '(' and ')' do not need to be escaped in string literals.
Here is a modified version with changes noted. I have redefined clrscr() because I don't have conio.h on this system:
#include <stdio.h>
#include <ctype.h>
// #include <conio.h>
#define clrscr() printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define p printf
#define s scanf
#define MAXSIZE 500
// prototypes [Changed]
int pop();
void push(int b);
int pick();
int view();
int top;
int ar[MAXSIZE];
int size;
int main()
{
int opt, num;
char cont[] = { 'y', '\0' }; // [Changed]
clrscr();
p("Stacking Program\n\n");
// keep asking until we get a valid size [Changed]
for (;;)
{
p("Data Size: ");
s("%d", &size);
if (size > 0 && size < MAXSIZE)
break;
printf("Not a valid size!\n");
}
p("\n");
while((cont[0] == 'y') || (cont[0] == 'Y'))
{
clrscr();
p("Stacking Program");
p("\n\nData Size: %d\n\n", size);
p("MAIN MENU\n1. Pop\n2. Push\n3. Pick\n4. View\nChoose: ");
s("%d", &opt);
p("\n");
switch(opt) {
case 1:
pop();
break;
case 2:
if(top > size)
{
p("You can't push more data");
}
else
{
p("Enter data for Data[%d]: ", top);
s("%d", &num);
push(num);
}
break;
case 3:
pick();
break;
case 4:
view();
break;
default:
p("Your choice is not in the list.");
break;
}
p("\n\nDo you want continue(Y/N)?");
s("%1s", cont); // [Changed]
}
return 0;
}
int pop()
{
int a;
if(top == 0) // [Changed]
{
p("Stack empty.");
return 0;
}
else
{
top--; // [Changed]
a = ar[top];
p("(Data[%d] = %d) removed.", top, a);
return a; // [Changed]
}
}
void push(int b)
{
ar[top] = b;
top++; // [Changed]
}
int pick()
{
if(top == 0) // [Changed]
{
p("Nothing to display.");
return 0;
}
else
{
p("(Data[%d] = %d) is the last data.", top, ar[top-1]); // [Changed]
return -1; // [Changed]
}
}
int view()
{
int i;
if(top < 0)
{
p("Nothing to display.");
return 0;
}
else
{
for(i = 0; i < top; i++) // [Changed]
{
p("Data[%d] = %d\n", i, ar[i]);
}
return -1; // [Changed]
}
}

Resources