My problem statement was to accept a string of numbers and display the different numbers on screen. So i tried to use strtok() to divide the string to different numbers and atoi() to convert these to numbers. But I'm getting runtime error.. I have also attached a sample code.
Input
1 22 123 89 12 as a string
Output
1 22 123 89 12 as numbers
I need to do mathematical operations on these numbers. So I must convert from integer to string.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main ()
{
int i,j;
char buffer [256];
char *token;
const char s[2]= " ";
fgets (buffer, 256, stdin);
token=strtok(buffer,s);
i = atoi (token);
printf("%d \n",i);
while (token!=NULL)
{token=strtok(buffer,s);
i = atoi (token);
printf("%d ",i);
}
return 0;
}
Besides changing the argument to your strtok calls in the loop, you need to change the order in which you call strtok and atoi. Right now, what if strtok in the loop returns NULL, which it will do sooner or later?
So instead do e.g.
token=strtok(buffer,s);
while (token!=NULL)
{
i = atoi (token);
printf("%d ",i);
token = strtok(NULL, " ");
}
You need to check the token for NULL before first atoi() itself. Alongside, usage of strtol() is preferred over atoi().
That said, I think, to serve your purpose,
while (token!=NULL)
{token=strtok(buffer,s);
should be
while (token!=NULL)
{token=strtok(NULL,s);
Otherwise, you'll end up parsing the input from starting over and over again.
Next, to avoid the \n read by fgets(), use delimiter string like
char * s = " \n";
As per the man page of strtok():
The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL.
char *strtok(char *str, const char *delim);
So modify your while loop as follows (Look at the order of atoi() and strtok() function calls):
while (token!=NULL)
{
i = atoi (token);
printf("%d ",i);
token=strtok(NULL,s);
}
You can also use strtol which is obviously better than atoi.
Related
So I need to be able to input a string as a phone number like so:
(555)-444-3333.
After that I need to use strtok to remove the parentheses and dashes, and convert the strings area code and the rest of the phone number to just integers and print them out all together
My problem is using strtok to get rid of the ( , because if I don't the area code will just print 0 when it's converted to an int. Here's what I have:
int main()
{
phone[14];
int* area_code;
int* digits;
int* i, j;
printf("Enter a phone number: ");
scanf("%s", phone);
strtok( phone, "(" );
area_code = strtok( phone, ")" );
j = atoi(area_code);
printf("%d", j);
while((digits = strtok(NULL, "-")) != NULL )
{
i = atoi(digits);
printf("%d", digits);
}
return 0;
}
The problem is right here:
strtok( phone, "(" );
area_code = strtok( phone, ")" );
Because the second call passes a non-NULL pointer, it doesn't continue processing the first string, it starts over beginning at the pointer passed, which is now a string of length zero.
In any case, overwriting the string you are parsing is bad style. If you use strtol, a single call will give you BOTH the numeric value of a group of digits AND a pointer following the digits, where you can start processing the next group of digits.
But if you just are going to print the digits back out, you don't need a numeric conversion at all. Just remove all punctuation.
Despite having 5/6 characters the same, strtok is not part of the str-to-x family of functions. Those are strtol returning a long integer, and strtod returning a double.
In your strtok calls, specify the delimiters as "()-".
Best of luck.
I'm currently having trouble with appending an equal sign, before and after my string is split into tokens. It leads me to the conclusion that I must replace the newline character at some point with my desired equal sign after splitting my string. I've tried looking at the c string.h library reference to see whether or not there is a way to replace the newline char using strstr to see whether or not there was already an "\n" in the tokenized string, but ran into an infinite loop when I tried that. I also thought about trying to replace the newline character, which should be the string length minus 1, and I admit, I have low familiarity in C. If you could take a look at my code, and provide some feedback, I would greatly appreciate it. Thank you for your time. I will admit I have low familiarity with C, but am currently reading the reference libraries.
// main method
int main(void){
// allocate memory
char string[256];
char *tokenizedString;
const char delimit[2] = " ";
const char *terminate = "\n";
do{
// prompt user for a string we will tokenize
do{
printf("Enter no more than 65 tokens:\n");
fgets(string, sizeof(string), stdin);
// verify input length
if(strlen(string) > 65 || strlen(string) <= 0) {
printf("Invalid input. Please try again\n"); }
} while(strlen(string) > 65);
// tokenize the string
tokenizedString = strtok(string, delimit);
while(tokenizedString != NULL){
printf("=%s=\n", tokenizedString);
tokenizedString = strtok(NULL, delimit);
}
// replace newline character implicitly made by enter, it seems to be adding my newline character at the end of output
} while(strcmp(string, "\n"));
return 0;
}// end of method main
OUTPUT:
Enter no more than most 65 tokens:
i am very tired sadface
=i=
=am=
=very=
=tired=
=sadface
=
DESIRED OUTPUT
Enter no more than 65 tokens:
i am very tired sadface
=i=
=am=
=very=
=tired=
=sadface=
Since you are using strlen(), you can do this instead
size_t length = strlen(string);
// Check that `length > 0'
string[length - 1] = '\0';
Advantages:
This way you would call strlen() only once. Calling it multiple times for the same string is inefficient anyway.
You always remove the trailing '\n' from the input string to your tokenization will work as expected.
Note: strlen() would never return a value < 0, because what it does is count the number of characters in the string, which is only 0 for "" and > 0 otherwise.
Well, you have two ways to do it, the simplest is to add a \n to the token delimiter string
const char delimit[] = " \n";
(you don't need to use an array size if you are going to initialize a string array with a string literal)
so it eliminates the final \n that comes in with your input. Another way is to search for it on reading and eliminate it from the input string. You can use strtok(3) for this purpose also:
tokenizedString = strtok(string, "\n");
tokenizedString = strtok(tokenizedString, delimit);
This question already has answers here:
scanning a string to hex char array
(3 answers)
Closed 8 years ago.
Here is my Code :
char a[18], b[18];
char oper, clear;
char *test;
init_8051();
test="0x1234567890123456 + 0x1234567890123456\0";
printf("Please enter an equation: %s \n",test );
sscanf(test,"0x%s %c 0x%s",a,&oper,b);
printf(" a= %s \n" ,a);
printf(" oper= %s \n" ,oper);
printf(" b= %s \n" ,b);
I want to accept to hex numbers with an operation as a string and to be able to seperate those 2 numbers into 2 separate char arrays but it doesnt wanna work, here is the output of the following code :
Please enter an equation: 0x1234567890123456 + 0x1234567890123456
a= 1234567890123456
oper= Ò
b= 1234567890123456
As you can see the operation is not recognized and also i have to use spaces which i wish i didnt have to use i wish it to be in the format of 0x1234567890123456+0x1234567890123456
with no spaces between the plus and the number.
Thanks
From the sscanf manual
s Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the
terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
It means that %s consumes the + and the rest of the characters, leaving b and oper uninitalized, abd overflowing a since it only has space for 18 characters.
So when the input string is lacking the space after the first operand, sscanf will continue reading until it finds a whitespace character. Hence when the string does not contain the separating space between the operands and the operator, sscanf consumes all the input.
I'll append here a different approach to your problems solution
We copy the string, this is required by strtok you can't pass an inmutable string, there are plenty of methods to copy this string, you just have to pick the appropriate one for your case
input = strdup("0x1234567890123456 + 0x1234567890123456\0");
Now, we use strpbrk to find the operator
pointer = strpbrk(input, "+-*/" /* here go the operators */);
if (pointer != NULL)
oper = *pointer; /* this will contain the operator ascii value */
Create a string containing the operator as a delimiter
operstr[0] = oper;
operstr[1] = '\0'; /* strings must be null terminated */
Now, we use strtok to tokenize the string, and find the operands
pointer = strtok(input, operstr);
if (pointer != NULL)
fprintf(stderr, "first operand: %s\n", pointer); /* you can copy this string if you need to */
printf("Operator: %s \n", operstr);
Second call to strtok needs NULL first argument
pointer = strtok(NULL, operstr);
if (pointer != NULL)
fprintf(stderr, "second operand: %s\n", pointer); /* you can copy this string if you need to */
And finally free our copy of the input string.
free(input);
It is better to use strtok_r the reentrant version. But for now you could test my suggestions and may be, it is what you need.
Even though this will work for this particular situation it is not the preferred way of doing this kind of thing, you can try writing a parser and use Reverse Polish Notation, or you can try with a lexical analyzer and a parser generator like flex and bison.
My previous answer was downvoted, and didn't address all of OP's requirements, so I have rewritten this answer.
OP wants flexible input, either spaces or no spaces. I suggest not using sscanf() but the methods below. First the program finds a valid operator by using strcspn(), then breaks the string using strtok() on operators and whitespace. But using strtok() on a string literal is UB so I copy the "equation" to another string first.
I also corrected the printf() field spec for the operator, and made a and b different - it's always a bad idea using the same values for different variables in an example.
#include <stdio.h>
#include <string.h>
#define OPERATORS "+-*/"
#define DELIMS " \t\n" OPERATORS
int parse (char *test)
// return 1 if parsed successfully
{
char a[50], b[50];
char oper;
char *ptr;
int opind;
opind = strcspn (test, OPERATORS); // find operator
if (opind < 1) return 0; // fail
oper = test[opind]; // collect operator
ptr = strtok (test, DELIMS); // find a
if (ptr == NULL) return 0; // fail
strcpy (a, ptr); // collect 1st arg
ptr = strtok (NULL, DELIMS); // find b
if (ptr == NULL) return 0; // fail
strcpy (b, ptr); // collect 2nd arg
printf(" a %s \n" ,a);
printf(" oper %c \n" ,oper); // corrected format
printf(" b %s \n" ,b);
return 1;
}
int main (void)
{
char test[100];
strcpy (test, "0x123456789ABCDEF0+0xFEDCBA9876543210");
if (!parse (test))
printf("Failed\n");
printf("\n");
strcpy (test, "0x123456789ABCDEF0 + 0xFEDCBA9876543210");
if (!parse (test))
printf("Failed\n");
return 0;
}
Program output
a 0x123456789ABCDEF0
oper +
b 0xFEDCBA9876543210
a 0x123456789ABCDEF0
oper +
b 0xFEDCBA9876543210
Forgive the basic question, but i'm missing something foundational. Recently found myself having to code after 8 years of complete programming inactivity.
What i'm trying to do is read in a string (known amount of tokens within it), and then take these characters and convert them to integers.
This second part is my problem. I'm sure it's the way i'm handling the pointers,but am unsure exactly where i'm going wrong.
Any tips would be welcome, i'm sure there are several issues below.
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="20\n3000 53\n96";
char * pch;
int num_one = 0;
int num_two = 0;
int num_three = 0;
int num_four = 0;
printf ("Splitting string \"%s\" into tokens:\n",str);
printf("\n");
pch = strtok (str," \n");
num_one = atoi(&pch);
printf ("%s\n",pch);
printf ("%u\n",num_one);
pch = strtok (NULL, " \n");
printf ("%s\n",pch);
num_two = atoi(&pch);
printf ("%u\n",num_two);
pch = strtok (NULL, " \n");
num_three = atoi(&pch);
printf ("%s\n",pch);
printf ("%u\n",num_three);
pch = strtok (NULL, " \n");
num_four = atoi(&pch);
printf ("%s\n",pch);
printf ("%u\n",num_four);
return 0;
}
Current output(can't get it to format correctly, but the \n are behaving as they should):
Splitting string "20
3000 53
96" into tokens:
20
0
3000
0
53
0
96
0
Firstly note that your string constants are const - you cannot modify them. strtok() will modify the calling string, so this can give rise to a GPF or core dump, unless you copy them.
I see you are calling atoi(&pch) which is incorrect - that should be atoi(pch); You gave it a pointer to a pointer to the string, and not a pointer to the string.
This would probably be much simpler using sscanf(), it will do it all in a single call.
Your format string would become something like "%d %d %d %d", since newline is just whitespace to sscanf().
If your input is "entrenched" you might also need to use %n to figure out many characters of input were consumed. This is helpful to skip to the next "record". Also remember to check the return value to know whether the call suceeded or not.
This is my code:
char str[] ="";
scanf("%s",&str);
char * pch;
pch = strtok (str,"#");
printf ("%s\n",pch);
return 0;
I need to render an input of "1#2#3" to three integers first, second and third.
My code above tackles only the first variable and prints the first string "1" but i want to save it to an int variable.
I tried:
int first = atoi(&pch)
But 'first' get's the value 0 instead of 1. How can i parse a pointer of an array char to int?
If you know the precise layout of the input, and the exact number of ints, you can simplify this greatly:
scanf("%d#%d#%d", &a, &b, &c);
Here is a link to a demo on ideone.
The code has undefined behaviour as str is not large enough to handle any input. str can hold at most 1 char and scanf() will append a null terminator when it reads in a string. If the user enters a single character and hits return then scanf() will write beyond the bounds the array str.
To correct, decide the maximum length of string that is acceptable and prevent scanf() by reading more:
char str[1024];
if (1 == scanf("%1023s", str))
{
}
Note that atoi() produces a result of 0 for invalid input or for "0", which is not helpful. Use strtol() instead or see the answer from dasblinkenlight for a simpler solution.
You pass a char* to atoi(), not a char**. Just call it as atoi(pch)
You have declared str as char str[] ="";. This would allocate only one byte to str.
Is it working correctly. I hope I am not missing something here.
As for strtok, you need to use it in a while loop
pch = strtok (str,"#");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, "#");
}