I was trying to write a calculator program and so part of this I need to evaluate an expression.
So I need to perform the operation based on the operator given. I am taking the whole expression into a string.
For example it might be 5+6 or 5*6.
So I have written it in this way:
char input1[20] = "";
char input2[20] = "";
char output[20] = "";
char *arg1= NULL, *arg2 = NULL;
int value;
getinput ( input1); //Function for getting the expression
strcpy (input2, input1);
if ( arg1 = strtok (input1, "*"))
{
arg2 = strtok (NULL, "");
value = atoi(arg1) * atoi(arg2);
}
else
{
char* arg1, *arg2;
arg1 = strtok ( input2, "+");
arg2 = strtok ( NULL, "");
value = atoi (arg1) + atoi(arg2);
}
sprintf (output,"%d", value);
printf ("The output value is %s", output);
This code works only if I give expression having multiplication. For example it works only if I give 5*6. This is not working if I give 5+6.
The problem is in the else part. It is not able to tokenize the string input2.
Can't I tokenize two different strings in a single program.
Where am I wrong? Can someone explain me this concept of why strtok is not working for secong string?
the first strtok will not return NULL for "3+5", but rather a pointer to the token "3+5"
(so the else statement won't get executed).
now the problem is that the second call to strtok (around line #12 in your code) will return NULL, and the subsequent call atoi(NULL) will segfault.
The first strtok call will not return NULL (unless your input string is either empty or only contains '*' characters), so the else statement will not be executed for a string like "5+6".
You probably want to use strchr (or similar) to figure out what operation is to be performed, and then get the operands.
case of input "3+5" result of strtok(input1, "*") is "3+5", That else clause is not executed because it should not be NULL.
Second parameter for strtok is an array use like this strtok (input1, "+*"). That means that it will tokenize if they get '*' or '+'.
I code this like below:
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ss[100] = "123+321";
int a = atoi(ss);
int aLength = (int)floor(log10((double)a))+1;
int b = atoi(ss+aLength);
if(ss[aLength] == '+')
printf("%d + %d = %d\n", a, b, (a+b));
else
printf("%d * %d = %d\n", a, b, (a*b));
return 0;
}
Related
I am trying to run the following code, but during execution, the code does not go into the if condition.
Why does the code not enter the if condition during runtime? I have marked the problem condition.
Running this program on Windows 10.
Thread model: posix
gcc version 5.1.0 (tdm64-1)
I have tried using the ternary operator and the if statement with a different string, and strchr works fine in that case.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main() {
static char str[] = "hello world";
static char inputTime[] = "12:05:10PM";
char *result = strchr(str, 'w');
long int tempNum = 0;
char *token, tempStr[10], delimit[] = ":";
if (strchr(str, 'w'))
printf("\nFound w");
else
printf("\nDid not find w");
(strchr(inputTime, 'P')) ? printf("\nTrue") : printf("\nFalse");
token = strtok(inputTime, delimit);
if (strchr(inputTime, 'P')) {
printf("Found PM\n");
tempNum = strtol(token, NULL, 10);
if (tempNum != 12)
tempNum += 12;
sprintf(tempStr, "%lu", tempNum);
}
printf("\ntempStr: %s", tempStr);
}
The above code gives me this output:
C:\Users\XX\Documents\Tests\c-programming>a.exe
Found w
True
tempStr: σ#
The strtok function splits the given input string into tokens. It does this by modifying the string to tokenize, placing a null byte in place of the delimiter to search for.
So after the call to strtok, inputTime looks like this:
{ '1','2','\0','0','5',':','1','0','P','M','\0' }
A null byte is put in place of the first :. So if you were to print inputTime you would get 12, meaning you won't find a P.
Because the input string is modified, you should search for P before calling strtok.
Having trouble with the converting of strings to doubles. I've tried using strtod, but that does the same thing. It seems like this should work just find but perhaps using strtok has something to do with it. data[i].calories is a double of course.
data[i].calories = atof(strtok(NULL, ","));
It seems to assign either a positive or negative really big number to calories (a double, which means it must be reading the value wrong.
Data Expected:
12cx7,23:55:00,->0.968900025,(this could also be a double),0,74,0,2,
What it instead actually gets:
12cx7,23:55:00,->-537691972,0,0,74,0,2,
EDIT:
IM AN IDIOT I WAS DISPLAYING IT AS AN INT PFFFFFFFFFFFFFFFF.
Assuming we have an input like this,
12cx7,23:55:00,0.968900025,,0,74,0,2,
And we would like to,
"Having trouble with the converting of strings to doubles."
That is we would like to separate the alphanumeric data . And then the remaining ints and floats, we would like to print in the correct format, I would do something like the following:
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int isNumeric (const char * s)
{
if (s == NULL || *s == '\0' || isspace(*s)) {
return 0;
}
char * p;
strtod (s, &p);
return *p == '\0';
}
bool isInteger(double val)
{
int truncated = (int)val;
return (val == truncated);
}
int main() {
// If this is your input:
char input[100] = "12cx7,23:55:00,0.968900025,0,74,0,2,";
// Then step 1 -> we split the values
char *token = std::strtok(input, ",");
while (token != NULL) {
// Step 2 -> we check if the values in the string are numeric or otherwise
if (isNumeric(token)) {
// printf("%s\n", token);
char* endptr;
double v = strtod(token, &endptr);
// Step 3 -> we convert the strings containing no fractional parts to ints
if (isInteger(v)) {
int i = strtol(token, &endptr, 10);
printf("%d\n", i);
} else {
// Step 4 -> we print the remaining numeric-strings as floats
printf("%f\n", v);
}
}
else {
// What is not numeric, print as it is, like a string
printf("%s,",token);
}
token = std::strtok(NULL, ",");
}
}
For the isInteger() function, I took the idea/code from this accepted answer. The rest is quite original and probably could be refined/improved.
This produces then this output:
12cx7,23:55:00,0.968900,0,74,0,2,
which is basically the output that we want, except with the very important difference that the input was a whole single string and the output is doubles/floats, ints and strings correctly identified and printed with the correct formatting.
EDIT:
I am not any doing error-handling here. This code is just to give the OP a proof-of-concept. Check and control for any errors returned from the used strtoX functions.
I'm making a very simple C program that simulates the export command, getting an input with fgets().
Input example:
KEY=VALUE
Has to be converted to:
setenv("KEY", "VALUE", 1);
That's easy to solve with something similar to this code:
key = strtok(aux, "=");
value = strtok(NULL, "=");
The problem comes when the user input a value that start with one or several equals = characters. For example:
KEY===VALUE
This should be converted to:
setenv("KEY", "==VALUE", 1);
But with my current code it is converted to:
setenv("KEY", NULL, 1);
How I can solve this?
Thanks in advice.
Your second strtok() should not use = as the delimiter. You would only do that if there were another = that ended the value. But the value ends at the end of the string. Use an empty delimiter for this part.
key = strtok(aux, "=");
value = strtok(NULL, "");
strtok is probably overkill (and non-reentrant) when it's just one token. This will do,
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char *key, *equals, *value;
if(argc != 2 || !(equals = strchr(key = argv[1], '=')))
return fprintf(stderr, "KEY=VALUE\n"), EXIT_FAILURE;
value = equals + 1;
*equals = '\0';
printf("key: <%s>; value: <%s>.\n", key, value);
return EXIT_SUCCESS;
}
Although strtok is probably easier to read. One may try strsep, but it is GNU C.
I have a value in the format of "xxx/yyy" , i used following method to extract the two values before and after "/"
char * ptr = "xxx/yyy";
part2 = strchr( ptr, '/');
if ( part2 != NULL)
part2++;
part1 = strtok(ptr,"/");
Result: part1 = xxx
part2 = yyy
This works fine, but when i have the value of ptr like "/yyy" , my result is
***part1 = yyy !!!!!! IT should be an empty char!!!!***
part2 = yyy
Thanks in advance
The strtok function skips all characters that you pass in the second string. Therefore you get the first string that does not include these characters for the first call. When you need a different behavior you should consider implementing my_strtok().
Harper has already given you the explanation for the behaviour you observe with strtok. Luckily, you have already done the work that strtok would do in your case: You have found the location of the slash. If there's a slash, you could do what strtok would do: Terminate the first string with a zero by overwriting the slash:
int main()
{
char ptr[] = "xxx/yyy";
char *part1, *part2;
part1 = ptr;
part2 = strchr(ptr, '/');
if (part2 != NULL) *part2++ = '\0';
printf("'%s', '%s'\n", part1, part2);
return 0;
}
Note that the input string must be modifiable, which your string literal is not. (It happens to be modifiable on your platform, but you should not rely on it; use a char array ptr[] instead of a pointer to a string literal, *ptr.)
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
void main(void)
{
char *a=malloc(strlen(ptr)/2);
char *b=malloc(strlen(ptr)/2);
int i=0;j=0,w;
while(*(ptr+i)!='/') {
*(a+j)=*(ptr+i);
j++; i++;
}
*(a+j)='\0';
j=0;
for(w=i+1;w<=strlen(ptr);w++) {
*(b+j)=*(ptr+w);
j++;
}
printf("pure string : %s \ntoken1 : %s \ntoken2= %s", ptr, a, b);
free(a);
free(b);
}
I have a string that contains with spaces, such as "print 2" or "print 3 test". I'm trying to remove the first argument - in these examples, the print.
I tried strtok():
char *test;
test = strtok(COMMAND, " ");
printf("%s\n", test);
However printing test will segfault. I tried making a function, and it works fine from main() but when called from the function I need it in, it also segfaults.
char* split(char S[], int N) {
printf("Running split() on %s\n", S);
int Spaces = 1;
int i = 0;
for (i; i<strlen(S) && Spaces <=N; i++) {
if (S[i] == ' ') {
Spaces++;
}
}
printf("split: %s\n", &S[i]);
//return "0";
return &S[i];
}
I'm guessing it's some kind of pointer problem. Command is being passed into the print function like so:
Print(File, Lines, COMMAND);
I don't know what COMMAND is in your test sample, but you should test, if strtok returns null (when strtok can't find a token).
printf with a nullpointer will give you a seg vault.
Normally you call strtok from a loop:
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
always test the return value of strtok()!
If no such byte (2nd parameter) is found, ie. no tokens exist in the string pointed to by the 1st parameter, a null pointer is returned.