Question:
C calculator can't parse arguments?
?
2013-10-03 12:20:45 UTC
I am trying to make a calculator that can accept arguments in this format "add(2,2)", but i can't get it to extract the arguments from the input format, i want it to separate out the mathematical operation then the two numbers for the specified operation, then do the specified operation.

Here is my program, i think the problem is how i am using "strsep", it gives a segmentation fault error.

#include
#include
#include

int main()
{
char *token;
char *string;
//fgets(string, 16, stdin);
string = "add(2,2)";
token = strsep(string, "(,)");
if (token[0] ="add")
{
printf("%d\n", atoi(token[1])+atoi(token[2]));
}
return 0;
}
Three answers:
?
2013-10-03 13:09:50 UTC
"The strtok() function should be preferred for portability reasons (it conforms to ISO/IEC 9899:1990 ("ISO C90")) but it is unable to handle empty fields, i.e., detect fields delimited by two adjacent delimiter characters, or to be used for more than a single string at a time. The strsep() function first appeared in 4.4BSD."



So I take it you are hosted on Linux or FreeBSD for this work. I'd recommend going back to trying out strtok() for portability, since it is possible to handle cases where there are empty fields, anyway. I would even prefer that you write a real tokenizer (lexer) and parser. It's not that hard to do, especially with a state machine.



But let me take a shot at this first with strsep() under Linux or FreeBSD:



#include

#include

#include

int main( void ) {

    char *token, *p, string[]= "add(2,2)";

        //fgets(string, 16, stdin);

        p= string;

        token= strsep( &p, "(,)" );

        if ( token != NULL && strcmp( token, "add" ) == 0 ) {

            token= strsep( &p, "(,)" );

            if ( token != NULL ) {

                int a= atoi( token );

                token= strsep( &p, "(,)" );

                if ( token != NULL ) {

                    int b= atoi( token );

                    if ( *p == '\0' )

                        printf( "%d\n", a+b );

                    else

                        printf( "Parsing error.\n" );

                }

            }

        }

    return 0;

}



Note that you need to pass a pointer to a pointer as the first parameter to strsep(). It needs writable access to the string pointer so that it can move it along after each call. Also note that strsep() does NOT return an array of string pointers. (Besides, you didn't define token to be right for that even if it did.) Also note that string comparisons are done with strcmp().



Finally, take serious note that I used string[]= and NOT *string= as the method of choice for setting up the string to parse. In normal use with fgets(), this isn't an issue as you'd have to set things up right there. But when you just define a string pointer and point it at a literal string, that literal string can be placed into read-only memory by the compiler (often is.) And both strtok() and strsep() both require writable memory to be used for the string. So you have to provide writable memory for storage of the string. Your method doesn't guarantee that. My method does. So note carefully the difference here.



Here is what similar code might look like using strtok() as a more "portable" alternative:



#include

#include

#include

int main( void ) {

    char *token, string[]= "add(2,2)";

        //fgets(string, 16, stdin);

        token= strtok( string, "(" );

        if ( token != NULL && strcmp( token, "add" ) == 0 ) {

            token= strtok( NULL, "," );

            if ( token != NULL ) {

                int a= atoi( token );

                token= strtok( NULL, ")" );

                if ( token != NULL ) {

                    int b= atoi( token );

                    token= strtok( NULL, "" );

                    if ( token == NULL )

                        printf( "%d\n", a+b );

                    else

                        printf( "Parsing error.\n" );

                }

            }

        }

    return 0;

}
2013-10-03 19:36:49 UTC
I can't remember C that much now, so I can't tell exactly how you can make this but I'll still mention the errors.



~ token[0] is the first *character* of token, so it musn't be compared with a string

~ You are assigning "add" to token[0], not comparing them. Since token[0] is a character, this is prolly where your segmentation fault occured (or started).

~ You should not compare two strings using the "==" operator, use strcmp or strcmpi (if i remember correctly) instead.

~ I guess you wanted an array of strings for token? You can make it like this..



char *token[3] or char **token (?)



.. and assign "add" to token[0], the first number to token[1] and second number to token[2]
gene_frequency
2013-10-03 23:55:18 UTC
One thing I can tell for sure - is this piece of code is improper, and may be producing the fault:



if (token[0] ="add")



... that won't work for a few reasons. First, it attempts to compare a string "add" to

a single character -- token[0].



'token[0]' is the first character of the array - not a string.



2nd problem - we have used the assignment operator '=' to compare.



Remember ... to compare things we use '=='



However, because you are comparing *strings*, even '==' will not work. You must use a function such as strcmp() for that.



if (! strcmp(token, "add") )

{

//if execution comes here, the strings match

}



Here is a nice, small piece of sample code on how to employ strsep()



main()

{

char *buf = "Hello there,stranger";

char **bp = &buf;

char *tok;

while (tok = strsep(bp, " ,"))

printf("tok = `%s'\n", tok);

}



Output:



tok = `Hello'

tok = `'

tok = `there'

tok = `stranger'


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...