I'm creating a reverse polish notation calculator that can also do a couple of other things using argv[] to enter options. But right now, I just have the RPN calculator option and I'm getting a strange error that I need help on.
I am getting the error:
Undefined first referenced
symbol in file
fmod /var/tmp//ccGTG20S.o
ld: fatal: Symbol referencing errors. No output written to project
collect2: ld returned 1 exit status
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
void push(float stack[], float value, int *currStack)
{
int i = *currStack;
while (i != 0)
{
stack[i] = stack[i-1];
i--;
}
stack[0] = value;
*currStack += 1;
}
void pop(float stack[], char operation, int *currStack)
{
int i;
switch (operation)
{
case 'A':
stack[0] = stack[1] + stack[0];
break;
case 'S':
stack[0] = stack[1] - stack[0];
break;
case 'X':
stack[0] = stack[1] * stack[0];
break;
case 'D':
stack[0] = stack[1] / stack[0];
break;
case 'M':
stack[0] = fmod(stack[1], stack[0]);
break;
default:
printf("error: the symbol %c is neither a supported operator nor an integer\n", operation);
break;
}
for (i=1;i<*currStack;i++)
{
stack[i] = stack[i+1];
}
*currStack -= 1;
}
void decode(char **instring, float *outval, int size)
{
int i=0, currStack=0;
float stack[size/2];
for (i=1;i<size;i++)
{
if (atof(instring[i]))
push(stack, atof(instring[i]), &currStack);
else
pop(stack, *instring[i], &currStack);
*outval = stack[0];
}
}
int evaluate(int argc, char *argv[])
{
float result;
decode(argv, &result, argc);
printf("%.2f\n", result);
return 0;
}
int
main(int argc, char *argv[])
{
if( (argc>1 )&&(strcmp(argv[1],"-e")!=0) && (strcmp(argv[1],"-c")!=0) && (strcmp(argv[1],"-g")!=0)){
fprintf(stderr, "%s: option %s is unsupported\n", argv[0], argv[1]);
}
if ((argc>1) && strcmp(argv[1], "-e")==0)
{
evaluate(argc, argv);
}
else if ((argc>1) && strcmp(argv[1],"-c")==0)
{
}
else if ((argc>1) && strcmp(argv[1],"-g")==0)
{
}
return EXIT_SUCCESS;
}
Related
I have this little piece of C code, which takes a set of command-line arguments --help, -h, -d and -o (each correspondingly representing "Help", "Hexadecimal", "Decimal", "Octal"), and I am calling certain functions depending in which argument is passed, -h will call hexaFlag(), -dh will call hexaFlag() and decFlag(). However, in order to do this, I am employing a block of if else that is messy. Is there any less convoluted way to achieve this? I was told to use a switch statement, but I do not know how I could use it here considering I am checking for different conditions each time.
main() function of the code I am referring to:
int main(int argc, char* argv[]){
if(argc == 1){
printf("%s",usage());
printf("Use --help for more options.\n");
}
else if(strcmp(argv[1], "--help") == 0){
printf("%s", usage());
printf("Options are:\n -h = Hexadecimal values\n -d = Decimal values\n -o = Octal values\n --help = Shows this message\n");
}
else if(strchr(argv[1], '-') != NULL){
if(strchr(argv[1], 'h') != NULL){
hexaFlag(argc, argv);
}
if(strchr(argv[1], 'd') != NULL){
decFlag(2, argc, argv);
}
if(strchr(argv[1], 'o') != NULL){
octaFlag(argc, argv);
}
}
else {
decFlag(1, argc, argv);
}
return 0;
}
I think you should modify the function signature a bit to make them consistent. That would allow you to do something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
void hexaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void decFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void octaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
struct args {
void (*f)(int, int, char **);
int x;
};
void
parse_args(int argc, char *argv[], struct args *A)
{
int c;
if( argc == 1 || !strcmp(argv[1], "--help") ){
printf("usage: %s [-hdo] [--help] arg [arg...]\n",
basename(argv[0]));
exit(EXIT_SUCCESS);
}
A->f = decFlag;
A->x = 1;
while( (c = getopt(argc, argv, "hdo")) != -1 ) {
switch( c ){
case 'h': A->f = hexaFlag; break;
case 'd': A->f = decFlag; A->x = 2; break;
case 'o': A->f = octaFlag; break;
default: exit(EXIT_FAILURE);
}
}
}
int
main(int argc, char* argv[])
{
struct args A;
parse_args(argc, argv, &A);
A.f(A.x, argc, argv);
return 0;
}
You should probably not pass argc/argv directly to the worker functions, but should extract what you need from them into the struct args in parse_args().
My basic switch processing (example), very functional but maybe not beautiful, is:
int main (int argc, char *argv[])
{
int i=0, number, files=0;
/* process switches; other prms are considered files (2)
that are opened for input/output. Files not specified
are taken as stdin and stdout. Prms can be in any order.
*/
while (++i < argc)
switch (argv[i][0]) {
case '-': while (*++argv[i])
switch (*argv[i]) {
case 'N':
++argv[i]; number= 0;
while (isdigit(*argv[i]))
number = number *10 + *argv[i]++ - '0';
argv[i]--;
break;
case 'P' : printf ("Prm: P\n"); break;
case 'O' : printf ("Prm: O\n"); break;
case 'o' : printf ("Prm: o\n"); break;
default :
printf ("Bad switch %c, ignored.\n",*argv[i]);
}
break;
default :
switch (files) {
case 0: if ((inf=fopen(argv[i],"r")) == 0)
pexit("Error opening input file %s.", argv[i]);
files++; break;
case 1: if ((outf=fopen(argv[i],"w")) == 0)
pexit ("Error creating output file %s.", argv[i]);
files++; break;
case 2: fprintf (stderr,"Too many file arguments: %s ignored.\n",argv[i]);
break;
} /* end switch files */
} /* end switch argc */
if (files <1) inf = stdin;
if (files <2) outf = stdout;
The main function has second parameter as char * argv[] , that is an array of pointers.In the same book it has been mentioned that we can't use operations like "++" on array names. But, here we can see ++argv has been used.
#include <stdio.h>
#include <string.h>
#define MAXLINE 1000
int getline(char* line, int max);
/* find: print lines that match pattern from 1st arg */
int main(int argc, char* argv[])
{
char line[MAXLINE];
long lineno = 0;
int c, except = 0, number = 0, found = 0;
while (--argc > 0 && (*++argv)[0] == '-')
{
while (c = *++argv[0])
{
switch (c)
{
case 'x': {
except = 1;
}
break;
case 'n': {
number = 1;
}
break;
default: {
printf("find: illegal option %c\n", c);
argc = 0;
found = -1;
}
break;
}
}
}
if (argc != 1)
{
printf("Usage: find -x -n pattern\n");
}
else
{
while (getline(line, MAXLINE) > 0)
{
lineno++;
if ((strstr(line, *argv) != NULL) != except)
{
if (number)
{
printf("%ld:", lineno);
}
printf("%s", line);
found++;
}
}
}
return found;
}
An array as a parameter to a function is automatically converted to a pointer. So this:
char *argv[]
Is exactly the same as:
char **argv
That's why you're allowed to do argv++.
im having trouble with this code ,its about search string from file after converting to dfa and nfa
whenever i try to access argv value, it give " 0x7fffffffe977 "XDG_MENU_PREFIX=gnom"... " maybe garbage value? though im not increment the argv (?)
though i have parameter in arguments such as -s 'c.h.a.r' /usr/share/dict/words
can someone suggest why this bug happen?
//parameter -s 'c.h.a.r' /usr/share/dict/words
#include "regmatch.h"
#include <string.h>
#include <strings.h>
#define BUFSIZE 256
int debug = 0;
char *reg_string;
static void do_grep(FILE *fp);
static void usage_exit(void);
static void show_region(char *p, char *from, char *to);
static char *match_line(char *str, char **cpp);
static char *match_string(char *str);
static int vflag = 0;
static int sflag = 0;
static int dflag = 0;
static char *progname;
int main(int argc, char *argv[])
{
FILE *fp;
char c, doption = '0';
ptree *root;
if ((progname = strrchr(*argv, '/')) == NULL)
progname = *argv;
else
progname++;
/*option*/
while (--argc > 0 && (*++argv)[0] == '-' ) { //parameter -s 'c.h.a.r' /usr/share/dict/words, but it not detect any string in argv[0] so this not
enter while loop why?
while ((c = *++argv[0])) {
switch(c) {
case 'v':
vflag = 1;
break;
case 's':
sflag = 1;
break;
case 'd':
dflag = 1;
if (!(isdigit(doption = *++argv[0]))) {
fatal_error("error");
usage_exit();
}
break;
default:
fatal_error("there is error in option");
usage_exit();
break;
}
}
}
if (argc-- < 1) {
fatal_error("error");
usage_exit();
}
reg_string = *argv++;
if (dflag) {
if (sflag || vflag) {
fatal_error("cannot input -d and -s option together");
usage_exit();
}
switch(doption) {
case '1':
lexer();
break;
case '2':
parse();
break;
case '3':
make_nfa();
break;
case '4':
make_dfa();
break;
default:
fatal_error("-d option 1 until 4");
usage_exit();
break;
}
exit(0);
}
//make dfa
get_token();
root = eval_expr(); //make tree
if (curr_token != EOREG)
parse_error();
gen_nfa(root); //change to nfa
gen_dfa(); //change to dfa
if (argc < 1) {
do_grep(stdin);
} else { //if parameter include file name
while(*argv){ //here also the value of argv is weird , it give endless loop ....
printf("%s",argv[0]);
while (argc-- > 0) {
if ((fp = fopen(*argv++, "r")) == NULL) {
fatal_error("cant open file");
exit(1);
}
do_grep(fp);
fclose(fp);
}
}
}
return 0;
}
argv change to weird value after programename line
when first debug
You need to breakdown the problem, perhaps ask about specific samples you would create.
There could be multiple issues in this code.
For the segfault I recommend single stepping in a debugger .. (such as gdb). Also, it is best if you isolate the problem to few lines, rather than expect someone to debug your whole code for you.
E.g.:
//parameter -s 'c.h.a.r' /usr/share/dict/words, but it not detect any string in argv[0] so this not enter while loop
Test just this with parameters -a 'c.h.a.r'
/*option*/
while (--argc > 0 && (*++argv)[0] == '-' )
printf("opt=> '%s'\n", argv[0]);
This works fine, picks up the '-'.
And so on.
/*
This is a code that changes infix notation to postfix notation.
I used FILE/IO to get infix notations and the infix.txt file looks like
3
2+4*2-1;
9+3^2^(3-1)*2;
2*((7-2)/3+4)^2%3;
My question is I get error saying "control may reach end of non-void function" on the last two functions, icp and isp. How can I fix this?
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_SIZE 100
#define ENTER 0x000d
void infixtopostfix(char expression[]);
char get_token(char expression[], int *index);
void push(int *top, char token);
int pop(int *top);
int icp(char op);
int isp(char op);
char stack[MAX_SIZE];
int main(void) {
int i, num;
FILE *file;
char expression[MAX_SIZE];
if((file=fopen("infix.txt","r")) == NULL) {
printf("No file.\n");
}
fgets(expression, MAX_SIZE, file);
num = atoi(expression);
for(i=0; i < num; i++) {
fgets(expression, MAX_SIZE, file);
printf("%s", expression);
infixtopostfix(expression);
}
fclose(file);
}
void infixtopostfix(char expression[]) {
char token;
char element;
int top=0;
int index=0;
for(token=get_token(expression, &index); token!=';'; token=get_token(expression, &index)) {
if(isdigit(token)) printf("%c", token);
else if(token == ')') {
while (stack[top] != '(') {
element = pop(&top);
printf("%c", element);
}
pop(&top);
}
else {
while (isp(stack[top])>=icp(token)) {
element = pop(&top);
printf("%c", element);
}
push(&top, token);
}
}
while((token=pop(&top))!=0) printf("%c", token);
printf("\n");
}
char get_token(char expression[], int *index) {
char token=expression[(*index)++];
return token;
}
void push(int *top, char data) {
if(*top < (MAX_SIZE-1)) stack[++(*top)] = data;
}
int pop(int *top) {
if(*top > -1) return stack[(*top)--];
else return 0;
}
int icp(char op) {
switch (op){
case '(' : return 20; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
int isp(char op) {
switch (op){
case '(' : return 0; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
While you may believe that your methods will only ever get one of these 6 characters, the compiler has to assume that any character can be passed in. At the moment, these methods will not return anything if you pass in, for example, 'x'.
You need to specify a default action for all characters not otherwise covered by your switch. Whether this is returning a default value or throwing an exception, that is up to you. But it's nonetheless a possibility your code needs to handle.
like this:
}//end switch
fprintf(stderr, "\nunrecognized OP(%c) is specified.\n", op);// '/', '^'...
return -1;//or exit(-1);
So i keep getting the message invalid expression "..." Bus Error (core dumped)if i type ./rpcalc "..." also if i just type in the command line ./rpcalc 1 i get the Segmentation Fault(core dumped) message. This is my entire code i would appreciate any help.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define max 10
#define NUMBER 'n'
int main(int argc, char *argv[])
{
double tmp;
char c;
if(argc <= 1) {
fprintf(stderr,"invalid call\n");
return 1;
}
while(--argc)
{
c = getop(*++argv);
switch(c)
{
case NUMBER:
push(atof(*argv));
break;
case '+':
push(pop() + pop());
break;
case '-':
tmp = pop();
push(pop() - tmp);
break;
case '*':
push(pop() * pop());
break;
case '/':
tmp = pop();
if(!tmp){
printf("can't divide by 0\n");
}
else{
push(pop()/tmp);
}
break;
default:
printf("invalid expression %s\n", *argv);
}
}
printf("%g\n",pop());
return 0;
}
int push (int stack[max], int *top, int *data)
{
if(*top == max -1)
return(-1);
else
{
*top = *top +1;
stack[*top] = *data;
return(1);
}
}
int pop(int stack[max], int *top, int *data)
{
if(*top == -1)
return(-1);
else
{
*data = stack[*top];
*top = *top - 1;
return(1);
}
}
static int isNumber(const char *s){
if(*s == '-' || *s == '+') s++;
if(*s == '\0'){
return 0;
}
while (isdigit(*s)) s++;
if(*s == 'e' || *s == 'E'){
s++;
while(isdigit(*s)) s++;
}
return *s == '\0';
}
int getop(const char *op){
return isNumber(op) ? NUMBER : *op;
}
gcc -Wall -ansi -pedantic
First, you probably shouldn't be returning a static int. Return either a char or an int or unsigned int.
Next: You're invoking functions with incorrect parameters:
Line 28:
push(atof(*argv));
This is not how you've defined your function.
int push (int stack[max], int *top, int *data);
It requires an array of stack[max], an int pointer, and another int pointer
Passing in a float is not correct.
Actually it looks almost like all of your function calls are with incorrect parameters.