2

How does one check the read in string for a substring in C?

If I have the following

char name[21];
fgets(name, 21, stdin);

How do I check the string for a series of substrings?

How does one check for a substring before a character? For example, how would one check for a substring before an = sign?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
some_id
  • 29,466
  • 62
  • 182
  • 304
  • Post a sample input string. If strtok cannot tokenise it, then you may have to just scan char by char and pick out the substrings. – Michael Dillon Feb 13 '11 at 02:57

3 Answers3

2

Be wary of strtok(); it is not re-entrant. Amongst other things, it means that if you need to call it in one function, and then call another function, and if that other function also uses strtok(), your first function is messed up. It also writes NUL ('\0') bytes over the separators, so it modifies the input string as it goes. If you are looking for more than one terminator character, you can't tell which one was found. Further, if you write a library function for others to use, yet your function uses strtok(), you must document the fact so that callers of your function are not bemused by the failures of their own code that uses strtok() after calling your function. In other words, it is poisonous; if your function calls strtok(), it makes your function unreusable, in general; similarly, your code that uses strtok() cannot call other people's functions that also use it.

If you still like the idea of the functionality - some people do (but I almost invariably avoid it) - then look for strtok_r() on your system. It is re-entrant; it takes an extra parameter which means that other functions can use strtok_r() (or strtok()) without affecting your function.

There are a variety of alternatives that might be appropriate. The obvious ones to consider are strchr(), strrchr(), strpbrk(), strspn(), strcspn(): none of these modify the strings they analyze. All are part of Standard C (as is strtok()), so they are essentially available everywhere. Looking for the material before a single character suggests that you should use strchr().

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I would like an equivalent to the Objective C componentsSeparatedByString: which returns an array of the elements so that you can access what you want. – some_id Feb 13 '11 at 03:04
  • +1 for beating me and using more words at the same time. The third `strtok` issue is one I'd never thought of before. – Chris Lutz Feb 13 '11 at 03:05
  • 1
    @alJaree - You'll have to roll your own. Should it return a C array (with a `size_t *` out-parameter)? Or should it take the buffer and lengh as parameters and try to fill them? Or should it return a user-defined structure that serves the purpose of an array? Similarly, how should it allocate the strings? – Chris Lutz Feb 13 '11 at 03:09
  • What I am going for is having a collection of structs. In these structs I have variables and one of the variables is an array of strings. So I need to grab user input, handle it by assigning it to the tempStruct fields. I want to check user input and match the first "token" (before the ':') and then take the rest, store it in the array of strings. repeat until inputs first token doesnt match what I want and then add this struct to the collection struct. – some_id Feb 13 '11 at 03:13
  • @alJaree: How is the memory going to be allocated? How do you know how long the input lines are going to be? What happens if the input line is longer than you thought it would be? How can you tell when the first toekn doesn't match what you want? When you say 'array of strings', are you splitting what follows the colon? Do you need to deal with blanks before the colon? Before the first word? After the colon? Do you match multiple lines with the same prefix to the same temporary structure, or do you process each line in isolation? What happens if there is no colon in the input line? – Jonathan Leffler Feb 13 '11 at 03:34
1

Use strtok() to split the string into tokens.

char *pch;
pch = strtok (name,"=");
if (pch != NULL)
{
  printf ("Substring: %s\n",pch);
}

You can keep calling strtok() to find more strings after the =.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
  • Thanks. what will this return or print out? The substring before the = ? How does one compare this to another string in C? – some_id Feb 13 '11 at 02:00
  • It's the string before `=`. All string comparison with done with `strcmp()` (or a variant like `strncmp()`) in C, so just use `pch` as one of the parameters. – chrisaycock Feb 13 '11 at 02:11
1

You can use strtok but it's not reentrant and it destroys the original string. Other (perhaps safer) functions to look into would be strchr, strstr, strspn, and perhaps the mem* variations. In general, I avoid strn* variants because, while they do "boinds checking," they still rely on the nul terminator. They can fail on a valid string that just happens to be longer than you expected to deal with, and they won't actually prevent a buffer overrun unless you know the buffer size. Better (IMHO) to ignore the terminator and know exactly how much data you're working with every time the way the mem* functions work.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • C seems so primitive. I just want to learn it for university course. Such a struggle to do things dynamically. I wish obj c was more common. :/ So what if I dont know how much data I will receive every time. I am splitting user input. e.g. Language:English I want to check the Language and then grab the English and store it. – some_id Feb 13 '11 at 03:09
  • @alJaree - It is, very deliberately. It allows you to do things faster and more precisely. If you want easy dynamic control (which is also a good thing and has it's own merits) you shouldn't use C. But learning how to do it "the C way" is important too. – Chris Lutz Feb 13 '11 at 03:12
  • Sure. I know it is great for knowing how things work. What will happen in the future when computers have virtually unlimited memory and processing power? Anyway, this is another discussion ;) So I should manually scan through the char array(user input) and check for the delimiter, storing each part into an array myself or is there a library function which can be used to split a string and store the parts into an array? – some_id Feb 13 '11 at 03:18
  • @alJaree: It depends on which libraries you have that you can use. There is no such function in the Standard C library, but there are probably such functions in other libraries built atop the Standard C library. – Jonathan Leffler Feb 13 '11 at 03:21
  • @alJaree - Well, it's not really manually scanning when you can use `strchr` and `strspn`, but the array storage is something you'll have to do yourself. C doesn't have a built-in dynamic array type like most other languages do. – Chris Lutz Feb 13 '11 at 03:22