i have two problems first on the compile time warning : warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
MenuFunction fp;
and second i am always end to "Error: buffer overflow. Please try again, entering less data" what i am doing wrong i have no idea , please help me to figure this out.
typedef void (*MenuFunction)(System*);
int main(int argc, char ** argv)
{
...
/* While loop for my menu */
while(1)
{
printf("Main Menu\n");
printf("%s\n", menu[0].text);
printf("%s\n", menu[1].text);
printf("%s\n", menu[2].text);
printf("Select your option (1-3): ");
MenuFunction fp;
fp = getMenuChoice(menu);
if(fp == NULL){
fprintf(stderr, "invalid choice\n");
}
else{
(*fp)(&system);
}
}
}
/* Function that points to the menu function */
MenuFunction getMenuChoice(MenuItem * menu)
{
MenuFunction function = NULL;
char select[50];
fgets(select, 50, stdin);
if(select[strlen(select)-1] == '\n')
{
switch(select[0])
{
case '1':
function = menu[0].function;
break;
case '2':
function = menu[1].function;
break;
case '3':
function = menu[2].function;
exit(0);
break;
default:
printf("Invalid option\n");
}
}
else
{
readRestOfLine();
printf("Error: buffer overflow. Please try again, entering less data");
}
return function;
}
Related
I am attempting to parse a command line argument, which in turn will execute an associated case within a switch statement. When I parse an integer argument (as seen in the code below), the associated case executes correctly. When I attempt to parse a string such as "CPU", I do not get the correct output.
Functioning code (parsing an integer e.g. an argument of 4 gives athe correct output of hello):
#include <stdio.h>
int main(int argc, char *argv[]) {
char execution_mode = atoi (argv[1]);
switch (execution_mode)
{
case (4) :
printf("Hello");
getchar();
break;
case (8) :
printf("Goodbye");
getchar();
break;
default:
printf("Error! execution mode is not correct");
getchar();
break;
}
return 0;
}
My attempt at parsing a string e.g. the argumentCPU:
#include <stdio.h>
int main(int argc, char *argv[]) {
typedef enum MODE { CPU, OPENMP } MODE;
MODE execution_mode = (char)argv[1];
switch (execution_mode)
{
case (CPU) :
printf("Hello");
getchar();
break;
case (OPENMP) :
printf("Goodbye");
getchar();
break;
default:
printf("Error! execution mode is not correct");
getchar();
break;
}
return 0;
}
You cannot convert a string to an enumerate like this. What you're doing is just converting the pointer to the string to char. Which fails.
One alternative (besides comparing first argument with strcmp) to avoid this would be to give a character value to your enumerates:
typedef enum { CPU='C', OPENMP='O' } MODE;
and now you can pick the first letter of the first argument and convert it:
MODE execution_mode = (MODE)argv[1][0];
The letters must be of course all different. And check argc>1 to see if argv[1] is valid, of course
If you want full string match, you have no other choice than using strcmp:
const char *execution_mode = argv[1];
if (strcmp(execution_mode,"CPU")==0)
{
// do something
}
else if (strcmp(execution_mode,"OPENMP")==0)
{
// do something else
}
With the help of the users who have answered this question, I have found a working solution by using strcmp as seen below. I have also added some error checking to ensure enough arguments have been enterred on the command-line.
#include <stdio.h>
int main(int argc, char *argv[]) {
//Ensure there are enough arguments
if (argc < 2)
{
printf("Error: not enough arguments");
exit(1);
}
typedef enum MODE { CPU, OPENMP, CUDA, ALL } MODE;
MODE execution_mode = (MODE)argv[1];
//Compare string with command-line arguments
if (strcmp("CPU", execution_mode) == 0)
{
//selects CPU case
execution_mode = CPU;
}
else if (strcmp("OPENMP", execution_mode) == 0)
{
//selects OPENMP case
execution_mode = OPENMP;
}
else
{
printf("invalid arg");
}
//Switch statement
switch (execution_mode)
{
case (CPU) :
printf("CPU MODE SELECTED");
getchar();
break;
case (OPENMP) :
printf("OPENMP MODE SELECTED");
getchar();
break;
default:
printf("Error: execution mode is not correct");
getchar();
break;
}
return 0;
}
#include<stdio.h>
#include<string.h>
void createIndexFile(char[]);
int main()
{
FILE *fp;
char fname[40];
int option;
printf("\nEnter the filename to open: ");
scanf("%s",fname);
fp=fopen(fname,"r");
if(fp==NULL)
{
printf("\nCannot open the file\n");
return 0;
}
else
{
printf("\n%s",fname);
createIndexFile(fname);
}
while(1)
{
printf("\n*****MENU*****\n");
printf("\n1.Display ......\n2.Insert new data\n3.Find data\n4.Display data\n5.Exit\n");
printf("\nChoose an operation: ");
scanf("%d",&option);
switch(option)
{
case 1: break;
case 2: break;
case 3: break;
case 4: break;
case 5: return 0;
default: printf("\nInvalid selection\n");
}
}
}
void createIndexFile(char fname[])
{
int i=0;
char tempFile[40];
char indexFile[40];
printf("\n%s",fname);
strcpy(indexFile,"xyz");
strcpy(tempFile,fname);
while(tempFile[i]!='.')
{
if(tempFile[i]=='/')
tempFile[i]='_';
}
strcat(tempFile,".idx");
strcat(indexFile,tempFile);
printf("\nIndex File Name: %s",indexFile);
}
It is a program where after a filename is entered suppose /home/abc.txt and my name is xyz then an index file should be created xyz_home_abc.idx.
After the filename is entered and if it is present, it should go to else part and function
createIndexFile(fname);
should be called. But inside the function, nothing is working properly. If we print a character or something, it is printed. But if I try to give another printf it is not working.
Corrected your function
void createIndexFile(char fname[])
{
int i=0;
char tempFile[40];
char indexFile[40];
printf("\n%s",fname);
strcpy(indexFile,"");
while(fname[i]!='.')
{
if(fname[i]=='/')
tempFile[i]='_';
else
tempFile[i]=fname[i];
i++;
}
tempFile[i]='\0';
strcat(tempFile,".idx");
strcat(indexFile,tempFile);
printf("\nIndex File Name: %s",indexFile);
}
SO i created a program that converts from infix to post fix and prefix which works just fine. The thing is that I am using C-LION which has its own debugger that allows me to go step by step and I do that the program works fine and outputs the expected results BUT then when I run it normally IT DOES NOT WORK AND GIVES ME A "main.c not working " ERROR.
This the main function that has the menu:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <tgmath.h>
char*infixToPostfix(char *infinx);
char* postixToinfix(char *infinx);
char* postixToprefix(char *infinx);
char* prefixToinfix(char *infinx);
char* prefixTopostfix(char *infinx);
char* infixToPrefix(char *infinx);
char*evaluate(char *infinx );
int exp_det(char*exp);
typedef struct node
{
char *op;
int p;
struct node *next; /* Pointer to the next node. Notice that the
existence of the structure tag enables us to declare its type. */
} node;
node *head=NULL; /* Global pointer that always points to the head of the
stack. */
int precedence(char symbol);
void add_stack(const node *p);
void pop(void);
int main(void)
{
char postfix[100];
int choice;
//converting from ininfinx to postfix
printf("\t\t***** Conversion Calculator 1.0 ******\t\t\n");
printf("\t\t1.Convert\n\t\t2.Evaluate\n\t\t3.Exit\nEnter Choice : ");
scanf("%d",&choice);
//switch (choice){
if (choice==1) {
printf("\n\t\t1.Input from File\n\t\t2.standered input\nEnter Choice :");
int ch2;
scanf("%d", &ch2);
switch (ch2) {
case 1:
printf("FILE MANGAMENT STILL NOT DONE !!!");
break;
case 2:
printf("Enter Expression : ");
char line[256];
scanf(" %[^\n]s", postfix);
char in2[100] = {'\0'};
char in3[100] = {'\0'};
char *conv;
char *conv2;
strcpy(in2, postfix);
strcpy(in3, postfix);
int exp = exp_det(in2);
if (exp == 1) {
printf("\nThis is a Prefix expression do you want to\n\t\t1.Infix\n\t\t2.Postfix\n\t\t3.Both\nEnter Choice :");
int ch3;
scanf("%d", &ch3);
switch (ch3) {
case 1:
conv = prefixToinfix(in3);
printf("Expression in Infix form: %s \n", in3);
break;
case 2:
conv = prefixTopostfix(in3);
printf("Expression in Postfix form: %s \n", in3);
break;
case 3:
conv = prefixToinfix(in3);
conv2 = prefixTopostfix(postfix);
printf("Expression in Infix form: %s \n", conv);
printf("Expression in Postfix form: %s \n", conv2);
break;
default:
printf("ERROROR WHEN EXPRESSION IN PREFIX ");
break;
}
} else if (exp == 2) {
printf("\nThis is a Infix expression do you want to\n\t\t1.Prefix\n\t\t2.Postfix\n\t\t3.Both\nEnter Choice :");
int ch3;
scanf("%d", &ch3);
switch (ch3) {
case 1:
printf("Expression in prefix form: %s \n", infixToPrefix(postfix));
break;
case 2:
printf("Expression in Postfix form: %s \n", infixToPostfix(postfix));
break;
case 3:
printf("Expression in prefix form: %s \n", infixToPrefix(postfix));
printf("Expression in Postfix form: %s \n", infixToPostfix(postfix));
break;
default:
printf("ERROROR R");
break;
}
} else if (exp == 3) {
printf("This is a Postfix expression do you want to\n\t\t1.Infix\n\t\t2.Prefix\n\t\t3.Both\nEnter Choice :");
int ch3;
scanf("%d", &ch3);
switch (ch3) {
case 1:
printf("Expression in Infix form: %s \n", postixToinfix(postfix));
break;
case 2:
printf("Expression in prefix form: %s \n", postixToprefix(postfix));
break;
case 3:
printf("Expression in Infix form: %s \n", postixToinfix(postfix));
printf("Expression in Prefix form: %s \n", postixToprefix(postfix));
break;
default:
printf("ERROR... 3:(\n");
break;
}
}
break;//for the switch with ch2 case 1
default:
printf("ERROR... 2:(\n");
break;
}
//break;
}if(choice==2) {
printf("Enter Expression : ");
scanf(" %[^\n]s", postfix);
char in2[100] = {'\0'};
char in3[100] = {'\0'};
char *conv;
char *conv2;
strcpy(in2, postfix);
conv = evaluate(in2);
printf("\nExpression evaluated = %s \n", conv);
//break;
}if(choice==3) {
printf("BYE...... :D\n");
}
system("PAUSE");
}
OK Now after much trials I am starting to think that the problem is in the conversion itself. This is one of the functions i am using for me it looks fine. If anyone has another opinion help is greatly appropriated.
char* infixToPostfix(char *infinx){
char* token;
char * infinx1=malloc(sizeof(infinx)+1);
infinx1=strcpy(infinx1,infinx);
token = strtok(infinx1," ");
char* res;
res=malloc(sizeof(infinx)+sizeof(head->op)*strlen(infinx));
strcpy(res," ");
if(*token=='\n' ){token=strtok(NULL," ");}
while( token != NULL ) {
node n;
n.op=token;
n.p=precedence(*token);
if(isalpha(*token) || isdigit(*token)){
// strcat(result,infinx[i]);
//printf("%c",infinx[i]);
res=strcat(res,token);
res=strcat(res," ");
}
//case when encounter a left paranthessisis
else if(*token=='(' || *token==')'){
if (*token=='('){
add_stack(&n);
}else if(*token==')') {
while (*head->op != '(') {
// strcat(result, n.op);
//printf("%c",(char)head->op);
res=strcat(res,head->op);
res=strcat(res," ");
pop();
}
pop();
}
}
//if head if null meaning the stack is empty or if the presendance of the head is less thatn or equal to new character
else if(head==NULL || head->p < n.p ){
if (head->p == n.p){}
add_stack(&n);
}
//in case the head has higher presendance he we pop and print untill we reach the same presedance
else {
while( head!=NULL && head->p >= n.p){
//strcat(result,n.op);
//printf("%c",(char)head->op);
res=strcat(res,head->op);
res=strcat(res," ");
pop();
}
add_stack(&n);
}
token=strtok(NULL," ");
}
while(head!=NULL){
//strcat(result,head->op);
//printf("%c",(char)head->op);
res=strcat(res,head->op);
res=strcat(res," ");
pop();
}
return res;
}
This is the answer to your question "So your saying I should define them outside the switch statement?" which reflects correctly one of the problems in your code.
Either: You can define them outside to solve the issue.
Or: You can introduce appropriate block scopes to solve the issue.
As the former is trivial, I will elaborate the latter:
1. Scope and Variables
The life-time of a local variable starts at its declaration and ends with surrounding block scope.
Example:
int main()
{
int a = 0; /* a starts to live. */
{ /* new scope */
int b = 1; /* b starts to live */
int a = 2; /* a new a starts to live. (The one of out scope is eclipsed.) */
} /* Life of b and the inner a ends. The eclipsed outer a becomes visible again. */
return 0;
}
2. switch and case
In opposition to other languages (like e.g. Pascal), the C switch statement is rather a "goto depending on expression" than a multiway branching with multiple alternatives. (This does not mean that switch cannot be used for the latter but it can be used different as well.) (Please, see Wikipedia: Control Flow: 5.2 Case and switch statements to understand what I mean.)
Imagine the following (wrong) code:
#include <stdio.h>
int main()
{
goto L1;
int i = 1;
L1:
printf("%d\n", i);
return 0;
}
The goto L1; skips the declaration of int i = 1; but after L1: it is used in printf() – ouch!
Out of curiosity, I tried it in ideone.com – it compiled and ran without complaints. Output was 0 although it could have been as well 1, 2, or any other number which can be stored as int.
This is the same in the following (wrong) sample:
#include <stdio.h>
int main()
{
int cond = 2;
switch (cond) {
case 1:
printf("case 1\n");
int i = 1;
case 2:
printf("case 2: %d\n", i);
} /* Here ends the life-time of i */
return 0;
}
Again, I compiled and tested in ideone.com.
Output was case 2: 0. Ouch again!
Solution
To mimic multi-branching correctly, the following things are necessary:
End each case with a break.
Start a scope after each colon of a case.
End this scope before the corresponding break.
Example again:
#include <stdio.h>
int main()
{
int cond = 2;
switch (cond) {
case 0: case 1: { /* <- start scope */
int i = 1;
printf("case 1: %d\n", i);
} break; /* <- end scope and jump to end of switch */
case 2:
printf("case 2: %d\n", i); /* i is recognized as unknown identifier */
}
return 0;
}
Compiled in ideone:
prog.c: In function ‘main’:
prog.c:12:34: error: ‘i’ undeclared (first use in this function)
printf("case 2: %d\n", i); /* i is recognized as unknown identifier */
^
As the scope of variable i is limited to the range from the possible entrance (case 0: case 1:) until the possible exit (break) – no other possible code path may access it.
I try to load the contents of a text file into a structure.
My idea looks like this:
I have two files, struct.h , main.c and a list.txt file .
in file struct.h :
struct analg {
char word[6];
char signature[6];
};
struct analg h[106];
FILE *fp;
In file main.c :
#include<stdio.h>
#include "struct.h"
void load() {
fp = fopen("list.txt", "r");
if(fp == NULL) {
printf("fail");
return 1;
}
else {
printf("file loaded!\n");
}
fclose(fp);
return;
}
void print() {
int i;
for(i=0; i<1000; i++) {
while(fgets(h[i].word, 6, fp)) {
printf("%s", h[i].word);
}
}
return;
}
int main () {
int choice;
do {
printf("choose L or P: ");
scanf("%s", &choice);
switch(choice) {
case 'l':
load();
printf("\n[l]oad - [p]rint\n");
break;
case 'p':
print();
printf("\n[l]oad - [p]rint\n");
break;
default:
break;
}
} while(choice!='q');
return;
}
In file list.txt :
throw
timer
tones
tower
trace
trade
tread
So I try to load the text file by pressing the "L" to the structure, and then when I press the 'p' will be displayed, but it is not!
In your code, I see there are 2 potential issues. The choice has to be a character to be switched based on l or p. You may have to add cases to handle the upper case also.
Another issue is that in load function, you are closing the file pointer. Hence, when you enter the print function fgets may not work as the fp is already closed.
To load your file into structure, the load has to be modified as
void load() {
fp = fopen("list.txt", "r");
if(fp == NULL) {
printf("fail");
return; // There was an error in original code as this was returning 1
}
do{
fgets(h[count++].word, 6, fp); // Count is a global variable - no. of elements read
}while(!feof(fp));
printf("file loaded!\n");
fclose(fp);
return;
}
The corresponding print function would become
void print(){
int i;
printf("Inside print\n");
for(i=0; i < count; i++) {
printf("%s", h[i].word);
}
return;
}
the main function would be,
int main (){
char choice;
do{
printf("choose L or P: ");
scanf("%c", &choice); //Only character is read and hence, %s is not required
switch(choice){
case 'l':
load();
printf("\n[l]oad - [p]rint\n");
break;
case 'p':
print();
printf("\n[l]oad - [p]rint\n");
break;
default:
case 'q':
break;
}
} while(choice !='q');
return 0;
}
One last point. In the scanf statement if scanf("%s", &choice); is employed, then a runtime check error is generated when main exits, with a message that stack is corrupted around the variable choice.
I'll comment up what your code is doing:
void load() {
fp = fopen("list.txt", "r"); // opens the file for reading
if(fp == NULL) {
printf("fail"); // if the file couldn't be opened, return an error
return 1; // (aside: a void function can't return an int)
}
else {
printf("file loaded!\n"); // tell the user that the file was opened
}
fclose(fp); // close the file, having read nothing from it
return;
}
At no point do you read anything from the file. What you have in memory will therefore have no relation to whatever you have on disk.
C has no built-in means for serialising and deserialising structs so what you need to do is define a formal grammar for your file on disk and write code that can parse that grammar into your structs.
I'm new to programming in C. I have a quick question about Switch Statements.
I have a menu that presents a list of options like so:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct Video {
char name[1024]; // Yvideo name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct Video Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void savequit();
void load();
void branching(char);
void menu();
int main()
{
char ch;
load(); // load save data from file
printf("\n\nWelcome\n");
do {
menu();
fflush(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
savequit();
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
so far entering 'i' (for inserting a new entry) and q (for save and quit) work perfectly. However every time I enter 'p' I get the default case. (Error: Invalid Input. Please try again...). What is it that I am doing wrong? I believe the syntax for the switch is correct? I've tried changing the 'p' to a different letter and I still got the the default case. Here is my printall() method if that helps...
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nName: %s", Collection[i].name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
What about something like:
char b[5];
do {
menu();
if(fgets(b,5,stdin)==NULL)
return -1;
ch = tolower(b[0]); // read a char, convert to lower case
while(strlen(b)>=4&&b[3]!='\n'){
check=fgets(b,5,stdin);
if(check==NULL)
return -1;
}
branching(ch);
} while (ch != 'q');
You can output the invalid char in your default case. That may help you understand how your input are handled.
default:
printf("\nError: Invalid Input ('%c'). Please try again...", option);
break;
fflush(stdin) is undefined as fflush is define only for output streams. To clear the newline char, you can simply use another getchar().
Try this for the loop part:
do {
menu();
ch = tolower((unsigned char)getchar());
getchar();
branching(ch);
} while (ch != 'q');