I have a string that includes two names and a comma how can i take them apart nd write them to seperate strings.
Example
char *line="John Smith,Jane Smith";
I am thinking of using sscanf function.
sscanf(line,"%s,%s",str1,str2);
What should i do?
note: I can change comma to space character.
I am thinking of using sscanf function.
Don't even think about it.
char line[] = "John Smith,Jane Smith";
char *comma = strchr(line, ',');
*comma = 0;
char *firstName = line;
char *secondName = comma + 1;
Here's how you could do it using strtok:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// Your string.
char *line = "John Smith,10,Jane Smith";
// Let's work with a copy of your string.
char *line_copy = malloc(1 + strlen(line));
strcpy(line_copy, line);
// Get the first person.
char *pointer = strtok(line_copy, ",");
char *first = malloc(1 + strlen(pointer));
strcpy(first, pointer);
// Skip the number.
strtok(NULL, ",");
// Get the second person.
pointer = strtok(NULL, ",");
char *second = malloc(1 + strlen(pointer));
strcpy(second, pointer);
// Print.
printf("%s\n%s", first, second);
return 0;
}
Related
I would like to extract only /home/user01\ruuidd:x:108:114::/run/uuuidd:/usr/sbin/nologin from the code string below. What should I do?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char str[1024]="\r\n\033[?2004l\r/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
char *ptr = strtok(str + 1, "\r");
strcpy(str, ptr + 1);
ptr = strtok(str, "\r\n\033");
printf("%s\n",ptr);
return 0;
}
The execution result of the code I made is as follows.
root#audit:~# ./test
output : [?2004l
strtok replaces the first delimiter found with the null-terminating byte, and returns the token that precedes it.
Additionally, strtok does not handle empty tokens, treating a series of adjacent delimiters as a single delimiter.
The following
/* first CR removed, as is the effect of the first `strtok` and `strcpy` in the example */
char str[] = "\n\033[?2004l\r/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
char *token = strtok(str, "\r\n\033")
results in a null-terminating byte being placed in str and token being equal to str + 2
/* start of token --v v-- NUL byte */
char str[] = "\n\033[?2004l\0/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
Here are a couple of naive examples that work with the exact string in question.
Using strchr and strstr:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[] = "\r\n\033[?2004l\r/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
char *base = strchr(str, '/');
char *tail = strstr(base, "\r\n");
/* for printing purposes remove the CR */
*strchr(base, '\r') = '_';
printf("%.*s\n", (int) (tail - base), base);
}
Using strchr and strcspn:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[] = "\r\n\033[?2004l\r/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
char *base = strchr(str, '/');
size_t length = strcspn(base, "\n");
/* for printing purposes remove the CR */
*strchr(base, '\r') = '_';
/* `length - 1` removes the trailing CR */
printf("%.*s\n", (int) (length - 1), base);
}
Both of these find the span of characters ('\r' replaced with '_' for display purposes):
/home/user01_uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
Note that strchr and strstr can return NULL, and passing NULL to any of these functions results in Undefined Behaviour. strcspn can obviously return 0, in which case subtracting one from this value would result in SIZE_MAX. These situations should all be considered and guarded against in a real program.
Undefined behavior
strcpy(str, ptr + 1); is (UB) is it attempts to copy a string where the source and destination overlap. Don't do that.
char *strcpy(char * restrict s1, const char * restrict s2);
The restrict in strcpy() implies the caller should not pass in pointers to overlapping areas.
Research strspn() and strcspn() as a replacement for strtok(). Used as pair, they work like strtok() without changing the source string.
Something like below. Notice that the str[1024] is even const.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str[1024] =
"\r\n\033[?2004l\r/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
const char *start1 = str + 1;
const char *token = "\r";
const char *end1 = start1 + strcspn(start1, token);
printf("%.*s\n", (int) (end1 - start1), start1);
const char *start2 = end1 + strspn(end1, token);
const char *end2 = start2 + strcspn(start2, token);
printf("%.*s\n", (int) (end2 - start2), start2);
const char *start3 = end2 + strspn(end2, token);
token = "\r\n\033";
const char *end3 = start3 + strcspn(start3, token);
printf("%.*s\n", (int) (end3 - start3), start3);
return 0;
}
Output
[?2004l
/home/user01
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
Or perhaps with a loop?
int main(void) {
const char str[1024] =
"\r\n\033[?2004l\r/home/user01\ruuidd:x:108:114::/run/uuidd:/usr/sbin/nologin\r\n\033[?2004h\033]0;user01#audit: ~\auser01#audit:~$ ";
const char *token = "\r\n\033";
const char *ptr = str;
size_t offset;
while ((offset = strspn(ptr, token)) != 0) {
const char *start = ptr + offset;
const char *end = start + strcspn(start, token);
printf("%.*s\n", (int) (end - start), start);
ptr = end;
}
return 0;
}
Output
[?2004l
/home/user01
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
[?2004h
]0;user01#audit: ~user01#audit:~$
I have read through countless strtok posts, even copied some directly in their entirety into a new int main, but I can't figure out how to create the functions get_first and get_second.
get_first("This is a sentence."); //returns "This"
get_rest("This is a sentence."); //returns "is"
This is what I have so far, I have had nothing but trouble with strtok, but I don't know what else to use.
#include <stdio.h>
#include <string.h>
char * get_first(char * string) {
string = strtok(string, " ");
return string;
}
char * get_second(char * string) {
string = strtok(string, " ");
string = strtok(NULL, " ");
return string;
}
int main(int argc, char * argv[]) {
char * test_string = "This is a sentence.";
char * first = get_first(test_string);
char * second = get_second(test_string);
printf("%s\n", first);
printf("%s\n", second);
}
Getting no faults compiling with gcc -g -Wall, but it always seg faults. I think I have tried every permutation of char c[] and char * c there is.
strtok changes the string. (but String literals are not allowed to change.)
So create a copy.
Do the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * get_first(const char *string){
char *clone = strdup(string);//create copy, strdup is non standard. malloc and copy.
char *token = strtok(clone, " ");
if(token)
token = strdup(token);
free(clone);
return token;
}
char * get_second(const char *string) {
char *clone = strdup(string);
char *token = strtok(clone, " ");
if(token && (token = strtok(NULL, " ")))
token = strdup(token);
free(clone);
return token;
}
int main(void) {
char * test_string = "This is a sentence.";
char * first = get_first(test_string);
char * second = get_second(test_string);
printf("%s\n", first);
printf("%s\n", second);
free(first);
free(second);
}
I have a string:
char *s = "asdf:jhgf";
I need to split this into two tokens:
token[0] = "asdf";
token[1] = "jhgf";
I'm having problems with strtok().
You can use a simple sscanf():
char token[2][80];
if(sscanf(s, "%[^:]:%s", token[0], token[1]) == 2)
{
printf("token 0='%s'\ntoken 1='%s'\n", token[0], token[1]);
}
Note that the first conversion is done using %[^:] to scan up until (but not including) the colon. Then we skip the colon, and scan an ordinary string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *s = "asdf:jhgf";
char *token[2];
char *p = strchr(s, ':');
size_t len1 = p-s, len2 = strlen(p+1);
token[0] = malloc(len1+1);
token[1] = malloc(len2+1);
memcpy(token[0], s, len1);
token[0][len1]=0;
memcpy(token[1], p+1, len2+1);
puts(token[0]);
puts(token[1]);
free(token[0]);free(token[1]);
return 0;
}
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.)