I have to check if strings given by the user are correct expressions. The strings should look like this:
int1+int2+int3+int4+...
for example:
1+5+21
Is a correct expression, while 1+a is not.
How can I do that?
The problem I encountered is that I define strings like:
char *str;
str = (char*)malloc(1024*sizeof(char));
char **output = strtok(str, "+"); // error
So I get segmentation fault when using strtok function.
Example of using strtok, in your case:
#include <string.h>
#include <stdio.h>
int function()
{
char* str = malloc(80);
strcpy(str,"1+5+21");
const char s[2] = "+";
char *token;
token = strtok(str, s); /* get the first token (1) */
while( token != NULL ) /* walk through other tokens */
{
// characters manipulation for verification
}
free(str);
return(0);
}
Related
I am trying to tokenize a sentence that starts with spaces but I get segmentation fault. I am trying to skip the spaces and store the words. Is there an alternative built-in function to achieve this?
#include <string.h>
#include <stdio.h>
[...]
char *buff = " push me", *token;
token = strtok(buff, " \n");
while (token) {
printf("%s", token);
token = strtok(NULL, " \n");
}
[...]
change to this
char buff[100], *token;
strcpy(buff," push me");
Before you were pointing to a string constant with the buff variable. The compiler will put this in a segment that is read only. If you try to write to that segment you get a segmentation fault. So in the code above we allocate space in read/write memory to store the string and then copy it in.
buff points to a string literal that usually cannot be modified.
strspn and strcspn can be used to parse the sub-strings.
#include <stdio.h>
#include <string.h>
int main ( void) {
char *buff = " push me";
char *token = buff;
size_t span = 0;
if ( ! buff) {
return 1;
}
while ( *token) {
token += strspn ( token, " \r\n\t\f\v"); // count past whitespace
span = strcspn ( token, " \r\n\t\f\v"); // count non-whitespace
if ( span) {
printf ( "%.*s\n", (int)span, token); // precision field to print token
}
token += span; // advance token pointer
}
}
strtok(), like others, are "library functions", not "built-in".
Very intelligent people wrote these functions expecting they would be used in clean, elegant and terse ways. I believe this is what you want:
#include <stdio.h>
#include <string.h>
int main() {
char buf[] = " push me"; // don't point at a "string literal'
for( char *tok = buf; (tok = strtok( tok, " \n") ) != NULL; tok = NULL )
printf( "%s\n", tok ); // added '\n' for clarity
return 0;
}
Output
push
me
Im trying to make a function which cuts and prints/does something with parts of a string.
Say i have this string:
"strings.no.header"
And i would like to split it up so it prints something like this:
strings
no
header
Here is my lousy attempt, where i am first able to (without the else statement) print out "strings". My idea was to make the function recursive so it prints and removes the first part before ".", and then does the same with the rest of the string.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void cut(char string[]);
int main() {
char string[] = "strings.no.header";
cut(string);
}
void cut(char string[]) {
char *toString = malloc(sizeof(char));
int len = strlen(string);
for(int i = 0; i < len; i++) {
int count = 0;
if(string[i] != '.') {
toString[i] = string[i];
} else if(string[i] == '.') {
char *tmp = malloc(sizeof(char));
tmp = string + i;
cut(tmp);
}
}
printf("%s", toString);
}
Would be grateful if someone could point me in the right direction.
I have an idea:
check this web page: https://en.wikibooks.org/wiki/C_Programming/Strings
use strchr to find '.'then, once you know the position, copy the characters in other string, remember that you already know where the '.' appears, so you know exactly what to copy.
Strtok is your friend. No need to reinvent the wheel.
void cut (const char* str){
char * pch;
pch = strtok (str,".");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ".");
}
}
The code is just a quick edit of the sample from the link.
A solution with strtok:
#include <stdio.h>
#include <string.h>
void cut(char string[]);
int main()
{
char string[] = "strings.no.header";
cut(string);
}
void cut(char string[])
{
char *pch;
pch = strtok (string, ".");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ".");
}
}
As others have noted, for something like this, strtok will give you what you need. A word of warning, this function will wreck your string, so it is always advisable to make a copy first.
Basically, what strtok does is replace all characters in the string that match the second argument of strtok and replace them with the '\0' character. The function then returns the pointer to the first "token". Each subsequent call to strtok will return the pointer to the next token. Here is a basic tutorial.
To keep it simple, I kept all the code in the main. You can now use this technique to implement the logic that suits your particular problem.
int main()
{
char string[] = "strings.no.header";
char buffer[50] = { 0 };//make sure big enough
char* token = NULL;
char* nextToken = NULL;
//want to make a copy because strtok will wreck the string
strcpy(buffer, string);
token = strtok_s(buffer, ".", &nextToken);
while (token)
{
printf("%s\n", token);//or do whatever you like.
token = strtok_s(NULL, ".", &nextToken);//pass NULL on subsequent calls
}
getchar();
return 0;
}
You may find this interesting that:
After the first call of token = strtok_s(buffer, ".", &nextToken);,
buffer now contains: "strings\0no.header".
After the second call,
buffer now contains: "strings\0no\0header".
This is the reason why you want to make a copy of the original string before using strtok. If you do not care about the original string, it is ok to use it.
I'm trying to write a string spliter function in C.It uses space as delimiter to split a given string in two or more. It more like the split funtion in Python.Here is the code:-
#include <stdio.h>
#include <string.h>
void slice_input (char *t,char **out)
{
char *x,temp[10];
int i,j;
x = t;
j=0;
i=0;
for (;*x!='\0';x++){
if (*x!=' '){
temp[i] = *x;
i++;
}else if(*x==' '){
out[j] = temp;
j++;i=0;
}
}
}
int main()
{
char *out[2];
char inp[] = "HEllo World ";
slice_input(inp,out);
printf("%s\n%s",out[0],out[1]);
//printf("%d",strlen(out[1]));
return 0;
}
Expeted Output:-
HEllo
World
but it is showing :-
World
World
Can you help please?
out[j] = temp;
where temp is a local variable. It will go out of scope as soon as your function terminates, thus out[j] will point to garbage, invoking Undefined Behavior when being accessed.
A simple fix would be to use a 2D array for out, and use strcpy() to copy the temp string to out[j], like this:
#include <stdio.h>
#include <string.h>
void slice_input(char *t, char out[2][10]) {
char *x, temp[10];
int i,j;
x = t;
j=0;
i=0;
for (;*x!='\0';x++) {
if (*x!=' ') {
temp[i] = *x;
i++;
} else if(*x==' ') {
strcpy(out[j], temp);
j++;
i=0;
}
}
}
int main()
{
char out[2][10];
char inp[] = "HEllo World ";
slice_input(inp,out);
printf("%s\n%s",out[0],out[1]);
return 0;
}
Output:
HEllo
World
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
From the website:
char * strtok ( char * str, const char * delimiters ); On a first
call, the function expects a C string as argument for str, whose first
character is used as the starting location to scan for tokens. In
subsequent calls, the function expects a null pointer and uses the
position right after the end of last token as the new starting
location for scanning.
Once the terminating null character of str is found in a call to
strtok, all subsequent calls to this function (with a null pointer as
the first argument) return a null pointer.
Parameters
str C string to truncate. Notice that this string is modified by being
broken into smaller strings (tokens). Alternativelly [sic], a null
pointer may be specified, in which case the function continues
scanning where a previous successful call to the function ended.
delimiters C string containing the delimiter characters. These may
vary from one call to another. Return Value
A pointer to the last token found in string. A null pointer is
returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
You can use this function to split string into tokens - there is no need to use some own functions. Your code looks like garbage, please format it.
Your source propably would look like this:
char *
strtok(s, delim)
char *s; /* string to search for tokens */
const char *delim; /* delimiting characters */
{
static char *lasts;
register int ch;
if (s == 0)
s = lasts;
do {
if ((ch = *s++) == '\0')
return 0;
} while (strchr(delim, ch));
--s;
lasts = s + strcspn(s, delim);
if (*lasts != 0)
*lasts++ = 0;
return s;
}
Have written following code in c
#include "stdio.h"
#include "string.h"
int main()
{
char str[] = "gatway=10.253.1.0,netmask=255.255.0.0,subnet=10.253.0.0,dns=10.253.0.203";
char name[100],value[100];
char *token1,*token2;
char *commasp = ", ";
char *equ="=";
token1 = strtok(str,commasp);
while(token1 != NULL)
{
token2 = strtok(token1,equ);
sprintf(name,"%s",token2);
token2 = strtok(NULL,commasp);
sprintf(value,"%s",token2);
printf("Name:%s Value:%s\n",name,value);
token1 = strtok(NULL,commasp);
}
return 0;
}
My problem is i got only one printf like Name:gatway Value:10.253.1.0. i know last strtok() in while loop followed by previous strok() which turns to null so token1 get null value and break the loop. Have think solution for it to not use strtok() in while loop for sub token (getting name and value) and use other method to extract name and value but it seems to lengthy code(using for or while loop for character match).So any one have batter solution to packup code in single loop.
You could use strtok_r instead of strtok.
char *key_value;
char *key_value_s;
key_value = strtok_r(str, ",", &key_value_s);
while (key_value) {
char *key, *value, *s;
key = strtok_r(key_value, "=", &s);
value = strtok_r(NULL, "=", &s);
printf("%s equals %s\n", key, value);
key_value = strtok_r(NULL, ",", &key_value_s);
}
gatway equals 10.253.1.0
netmask equals 255.255.0.0
subnet equals 10.253.0.0
dns equals 10.253.0.203
Frankly though I think it would be easier to just look for , and when you find one look for = backwards.
You can do this in two steps, first parse the main string:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "gatway=10.253.1.0,netmask=255.255.0.0,subnet=10.253.0.0,dns=10.253.0.203";
char name[100],value[100];
char *commasp = ", ";
char *ptr[256], **t = ptr, *s = str;
*t = strtok(str, commasp);
while (*t) {
t++;
*t = strtok(0, commasp);
}
for (t = ptr; *t; t++) {
printf("%s\n", *t);
// now do strtok for '=' ...
}
return 0;
}
Then parse individual pairs as before.
The above results in:
gatway=10.253.1.0
netmask=255.255.0.0
subnet=10.253.0.0
dns=10.253.0.203
I learnt C in uni but haven't used it for quite a few years. Recently I started working on a tool which uses C as the programming language. Now I'm stuck with some really basic functions. Among them are how to split and join strings using a delimiter? (I miss Python so much, even Java or C#!)
Below is the function I created to split a string, but it does not seem to work properly. Also, even this function works, the delimiter can only be a single character. How can I use a string as a delimiter?
Can someone please provide some help?
Ideally, I would like to have 2 functions:
// Split a string into a string array
char** fSplitStr(char *str, const char *delimiter);
// Join the elements of a string array to a single string
char* fJoinStr(char **str, const char *delimiter);
Thank you,
Allen
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char** fSplitStr(char *str, const char *delimiters)
{
char * token;
char **tokenArray;
int count=0;
token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));
if (!token) {
return tokenArray;
}
while (token != NULL ) { // While valid tokens are returned
tokenArray[count] = (char*)malloc(sizeof(token));
tokenArray[count] = token;
printf ("%s", tokenArray[count]);
count++;
tokenArray = (char **)realloc(tokenArray, sizeof(char *) * count);
token = (char *)strtok(NULL, delimiters); // Get the next token
}
return tokenArray;
}
int main (void)
{
char str[] = "Split_The_String";
char ** splitArray = fSplitStr(str,"_");
printf ("%s", splitArray[0]);
printf ("%s", splitArray[1]);
printf ("%s", splitArray[2]);
return 0;
}
Answers: (Thanks to Moshbear, Joachim and sarnold):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char** fStrSplit(char *str, const char *delimiters)
{
char * token;
char **tokenArray;
int count=0;
token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));
tokenArray[0] = NULL;
if (!token) {
return tokenArray;
}
while (token != NULL) { // While valid tokens are returned
tokenArray[count] = (char*)strdup(token);
//printf ("%s", tokenArray[count]);
count++;
tokenArray = (char **)realloc(tokenArray, sizeof(char *) * (count + 1));
token = (char *)strtok(NULL, delimiters); // Get the next token
}
tokenArray[count] = NULL; /* Terminate the array */
return tokenArray;
}
char* fStrJoin(char **str, const char *delimiters)
{
char *joinedStr;
int i = 1;
joinedStr = realloc(NULL, strlen(str[0])+1);
strcpy(joinedStr, str[0]);
if (str[0] == NULL){
return joinedStr;
}
while (str[i] !=NULL){
joinedStr = (char*)realloc(joinedStr, strlen(joinedStr) + strlen(str[i]) + strlen(delimiters) + 1);
strcat(joinedStr, delimiters);
strcat(joinedStr, str[i]);
i++;
}
return joinedStr;
}
int main (void)
{
char str[] = "Split_The_String";
char ** splitArray = (char **)fStrSplit(str,"_");
char * joinedStr;
int i=0;
while (splitArray[i]!=NULL) {
printf ("%s", splitArray[i]);
i++;
}
joinedStr = fStrJoin(splitArray, "-");
printf ("%s", joinedStr);
return 0;
}
Use strpbrk instead of strtok, because strtok suffers from two weaknesses:
it's not re-entrant (i.e. thread-safe)
it modifies the string
For joining, use strncat for joining, and realloc for resizing.
The order of operations is very important.
Before doing the realloc;strncat loop, set the 0th element of the target string to '\0' so that strncat won't cause undefined behavior.
For starters, don't use sizeof to get the length of a string. strlen is the function to use. In this case strdup is better.
And you don't actually copy the string returned by strtok, you copy the pointer. Change you loop to this:
while (token != NULL) { // While valid tokens are returned
tokenArray[count] = strdup(token);
printf ("%s", tokenArray[count]);
count++;
tokenArray = (char **)realloc(tokenArray, sizeof(char *) * count);
token = (char *)strtok(NULL, delimiters); // Get the next token
}
tokenArray[count] = NULL; /* Terminate the array */
Also, don't forget to free the entries in the array, and the array itself when you're done with it.
Edit At the beginning of fSplitStr, wait with allocating the tokenArray until after you check that token is not NULL, and if token is NULL why not return NULL?
I'm not sure the best solution for you, but I do have a few notes:
token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));
if (!token) {
return tokenArray;
}
At this point, if you weren't able to find any tokens in the string, you return a pointer to an "array" that is large enough to hold a single character pointer. It is un-initialized, so it would not be a good idea to use the contents of this array in any way. C almost never initializes memory to 0x00 for you. (calloc(3) would do that for you, but since you need to overwrite every element anyway, it doesn't seem worth switching to calloc(3).)
Also, the (char **) case before the malloc(3) call indicates to me that you've probably forgotten the #include <stdlib.h> that would properly prototype malloc(3). (The cast was necessary before about 1989.)
Do note that your while() { } loop is setting pointers to the parts of the original input string to your tokenArray elements. (This is one of the cons that moshbear mentioned in his answer -- though it isn't always a weakness.) If you change tokenArray[1][1]='H', then your original input string also changes. (In addition to having each of the delimiter characters replaced with an ASCII NUL character.)