Strtok outputting just a part of the string - c

#include <stdio.h>
#include <string.h>
int main(){
char name[] = "eseumdesconhecidolheoferecerflores.issoeimpulse.cities";
char *str;
printf("%s\n", name)
str = strtok(name, ".cities");
printf("%s\n", str);
return 0;
}
This is the output:
eseumdesconhecidolheoferecerflores.issoeimpulse.cities
umd
I have no idea what is happening at all. What I want is for the output of strtok to be a pointer to "eseumdesconhecidolheoferecerflores.issoeimpulse"

The delimiter argument to strtok is a string containing individual characters used to separate the string.
You specified delimiters ., c, i, t, e, and s.
So it's no surprise the output is umd for the first token, since it is surrounded by characters in your delimiter string.
If you want to find a whole string, you should use strstr instead.
For example:
char name[] = "eseumdesconhecidolheoferecerflores.issoeimpulse.cities";
char *pos;
pos = strstr(name, ".cities");
if (pos)
{
*pos = '\0';
printf("%s\n", name);
}

Related

sscanf get string until second symbol (include one)

How to get string until second symbol through sscanf?
for example:
char *str = "struct1.struct2.struct3.int";
char buf[256] = {0};
sscanf(str, "", buf); //have any format string could get string until second dot?
sscanf get string until second symbol (include one)
How to get string until second symbol through sscanf?
Not generally possible with a single use of sscanf().
Certainly, without a lot of work, a more involved use of sscanf() will work for many input strings, yet fail for select ones1. sscanf() is not the best fit here for this task.
strchr(), strcspn() better suited.
#include <string.h>
#include<stdlib.h>
// Return offset to 2nd needle occurrence
// or end of string, if not found.
size_t foo(const char *haystack, const char *needle) {
size_t offset = strcspn(haystack, needle);
if (haystack[offset]) {
offset++;
offset += strcspn(haystack + offset, needle);
}
return offset;
}
#include <stdio.h>
int main() {
const char *haystack = "struct1.struct2.struct3.int";
printf("<%.*s>\n", (int) foo(haystack, "."), haystack);
}
Output
<struct1.struct2>
1 Consider: "struct1.struct2", "struct1..", "..struct2", ".struct2.", "..", ".", "".
You can use a * to tell scanf to ignore an element:
const char *str = "struct1.struct2.struct3.int";
int main() {
char buf[256];
int i = sscanf(str, "%*[^.].%[^.]", buf);
printf("%d >%s<\n", i, buf);
return 0;
}
This outputs as expected:
1 >struct2<
because exactly 1 element was assigned even if another one was parsed.

srtok is not working in c

here is my code,
#include <string.h>
#include <stdio.h>
main ()
{
explode (" ", "this is a text");
}
explode (char *delimiter, char string[])
{
char *pch;
printf ("Splitting string \"%s\" into tokens:\n",string);
pch = strtok (string,delimiter);
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, delimiter);
}
return 0;
}
I compile this code using gcc -o 1.exe 1.c and shows no error. But when i execute 1.exe it shows Splitting string "this is a text" into tokens: and at that moment 1.exe stops working (a dialogue box of windows shows). can anybody tell the problem and solve the problem? I am using windows 10.
While you can't do this with strtok because the literal can't be modified, it can be done with strcspn.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void explode (char *delimiter, char *string);
int main()
{
explode (" ", "this is a text");
return 0;
}
void explode (char *delimiter, char *string)
{
int span = 0;
int offset = 0;
int length = 0;
if ( delimiter && string) {
length = strlen ( string);
printf ("Splitting string \"%s\" into tokens:\n",string);
while (offset < length) {
span = strcspn ( &string[offset],delimiter);//work from offset to find next delimiter
printf ("%.*s\n",span, &string[offset]);//print span number of characters
offset += span + 1;// increment offset by span and one characters
}
}
}
In your explode() function, you're passing a string liteal ("this is a text") and using the same as the input to strtok().
As strtok() modifies the input string, here, it will invoke invokes undefined behavior. As mentioned in th C11 standard, chapter ยง6.4.5, String literals
[...] If the program attempts to modify such an array, the behavior is
undefined.
You can either
Define an array and initalize it with the string literal and the use the array as input to strtok().
take a pointer, use strdup() to copy the initializer and then supply that pointer to strtok().
The bottom line is, the input string to strtok() should be modifiable.

read the characters between special characters in C

I'm new to C language and I need a help on String functions.
I have a string variable called mcname upon which I would like to compare the characters between special characters.
For example:
*mcname="G2-99-77"
I expect the output to be 99 as this is between the - characters.
How can I do this in C please?
Travel the string (walking pointer) till u hit a special character.
Then start copying the characters into seperate array untill u hit the next special character (Place a null character when u encounter the special character second time)
You can do this by using strtok or sscanf
using sscanf:
#include <stdio.h>
int main()
{
char str[64];
int out;
char mcname[] = "G2-99-77";
sscanf(mcname, "%[^-]-%d", str, &out);
printf("%d\n", out);
return 0;
}
Using strtok:
#include <stdio.h>
#include <string.h>
int main()
{
char *str;
int out;
char mcname[] = "G2-99-77";
str = strtok(mcname, "-");
str = strtok (NULL, "-");
out = atoi(str);
printf("%d\n", out);
return 0;
}
sscanf() has great flexibility. Used correctly, code may readily parse a string.
Be sure to test the sscanf() return value.
%2[A-Z0-9] means to scan up to 2 characters from the set 'A' to 'Z' and '0' to '9'.
Use %2[^-] if code goal is any 2 char other than '-'.
char *mcname = "G2-99-77";
char prefix[3];
char middle[3];
char suffix[3];
int cnt = sscanf(mcname, "%2[A-Z0-9]-%2[A-Z0-9]-%2[A-Z0-9]", prefix, middle,
suffix);
if (cnt != 3) {
puts("Parse Error\n");
}
else {
printf("Prefix:<%s> Middle:<%s> Suffix:<%s>\n", prefix, middle, suffix);
}

Using Pointers and strtok()

I'm building a linked list and need your assistance please as I'm new to C.
I need to input a string that looks like this: (word)_#_(year)_#_(DEFINITION(UPPER CASE))
Ex: Enter a string
Input: invest_#_1945_#_TRADE
Basically I'm looking to build a function that scans the DEFINITION and give's me back the word it relates to.
Enter a word to search in the dictionary
Input: TRADE
Output: Found "TREADE" in the word "invest"
So far I managed to come up using the strtok() function but right now I'm not sure what to do about printing the first word then.
Here's what I could come up with:
char split(char words[99],char *p)
{
p=strtok(words, "_#_");
while (p!=NULL)
{
printf("%s\n",p);
p = strtok(NULL, "_#_");
}
return 0;
}
int main()
{
char hello[99];
char *s = NULL;
printf("Enter a string you want to split\n");
scanf("%s", hello);
split(hello,s);
return 0;
}
Any ideas on what should I do?
I reckon that your problem is how to extract the three bits of information from your formatted string.
The function strtok does not work as you think it does: The second argument is not a literal delimiting string, but a string that serves as a set of characters that are delimiters.
In your case, sscanf seems to be the better choice:
#include <stdlib.h>
#include <stdio.h>
int main()
{
const char *line = "invest_#_1945 _#_TRADE ";
char word[40];
int year;
char def[40];
int n;
n = sscanf(line, "%40[^_]_#_%d_#_%40s", word, &year, def);
if (n == 3) {
printf("word: %s\n", word);
printf("year: %d\n", year);
printf("def'n: %s\n", def);
} else {
printf("Unrecognized line.\n");
}
return 0;
}
The function sscanf examines a given string according to a given pattern. Roughly, that pattern consists of format specifiers that begin with a percent sign, of spaces which denote any amount of white-space characters (including none) and of other characters that have to be matched varbatim. The format specifiers yield a result, which has to be stored. Therefore, for each specifier, a result variable must be given after the format string.
In this case, there are several chunks:
%40[^_] reads up to 40 characters that are not the underscore into a char array. This is a special case of reading a string. Strings in sscanf are really words and may not contain white space. The underscore, however, would be part of a string, so in order not to eat up the underscore of the first delimiter, you have to use the notation [^(chars)], which means: Any sequence of chars that do not contain the given chars. (The caret does the negation here, [(chars)] would mean any sequence of the given chars.)
_#_ matches the first delimiter literally, i.e. only if the next chars are underscore hash mark, underscore.
%d reads a decimal number into an integer. Note that the adress of the integer has to be given here with &.
_#_ matches the second delimiter.
%40s reads a string of up to 40 non-whitespace characters into a char array.
The function returns the number of matched results, which should be three if the line is valid. The function sscanf can be cumbersome, but is probably your best bet here for quick and dirty input.
#include <stdio.h>
#include <string.h>
char *strtokByWord_r(char *str, const char *word, char **store){
char *p, *ret;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
p = strstr(ret=*store, word);
if(p){
*p='\0';
*store = p + strlen(word);
} else {
*store = NULL;
}
return ret;
}
char *strtokByWord(char *str, const char *word){
static char *store = NULL;
return strtokByWord_r(str, word, &store);
}
int main(){
char input[]="invest_#_1945_#_TRADE";
char *array[3];
char *p;
int i, size = sizeof(array)/sizeof(char*);
for(i=0, p=input;i<size;++i){
if(NULL!=(p=strtokByWord(p, "_#_"))){
array[i]=p;//strdup(p);
p=NULL;
} else {
array[i]=NULL;
break;
}
}
for(i = 0;i<size;++i)
printf("array[%d]=\"%s\"\n", i, array[i]);
/* result
array[0]="invest"
array[1]="1945"
array[2]="TRADE"
*/
return 0;
}

How to use strtok to parse string at whitespace?

I am trying to use strtok() to parse a string deliminated by spaces. From what I can tell, I am using it correctly, but it won't run on ideone.com. Is there anything wrong with the following code? I just get Runtime error time: 0 memory: 2288 signal:11
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void test(char *command)
{
char* output = strtok(command, " ");
printf("%s\n", output);
}
int main(void) {
test("set_rate 200");
return 0;
}
Here it is on ideone.com if you want to try it.
Always consult the man pages first.
strtok(3) says:
Be cautious when using these functions. If you do use them, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
strtok will modify the string passed as the first parameter, so you can't pass a string literal, change your main like this:
int main(void) {
char str[] = "set_rate 200";
test(str);
return 0;
}
str here is an char array, but not a string literal.
As strtok modifies the string, it requires that the string is not in read-only memory. So when you pass a string literal to your test function, it crashes.
This is better:
char s[] = "set_rate 200";
test(s);
When you pass hard coded string that was stored in read-only memory.
strtok() does not work with string which is read-only memory.
You need to use string variable rather than string literal .
you can first store string in some variable and then you can pass it to the function.
char[]="set_rate 200";
test(str);
See example:
char *str = malloc(20);
char *tok = NULL;
int len = 0;
strcpy(str, "This is a string");
len = strlen(str);
printf("string before strtok(): %s\n", str);
tok = strtok(str, " ");
while (tok) {
printf("Token: %s\n", tok);
tok = strtok(NULL, " ");
}
Edit
From #Yu Hao comment i am adding this
char *str = "set_rate 200";
test(str); // This won't work. here str is pointer to the string literal.

Resources