To summarize, if the function is given arguments char *str1 = "Watch out the streets?";
char *str2 = "street?";, it should return a pointer in str1 to the first instance of "street", starting from s.
I am completely stuck and appreciate any help. I have a feeling my problem is with pointers. I'm a beginner as you might imagine.
I just edited the code to my latest attempt. I am very close, but cannot still find the idea to modify the first string.
Output image:
const char *qstr_strstr(const char *str1, const char *str2) {
int j = 0;
char newstr2[256];
while (str2[j]) {
if (str2[j] == '?') {
break;
} else {
newstr2[j] = str2[j];
}
j++;
}
newstr2[j] = '\0';
size_t n = strlen(newstr2);
while(*str1) {
if (!memcmp(str1++, newstr2, n)) {
return (str1 - 1);
}
}
return NULL;
}
You are heading in the right direction, and you are starting to think about stepping through stings correctly, but you are getting wrapped up in your use of any additional string -- there is no need for that.
When you are analyzing stings and substrings, all you care about is:
the index (position) within the original string (to iterate);
whether you have found the beginning of the substring yet (if so set flag indicating in word matching chars); and
whether you make it all the way to the end of the substring while your flag is set (if you do, you have found your substring). Otherwise, if there is a mismatch in characters before reaching the end, unset your flag and keep going. Repeat until you run out of str1.
Complicating your case here is the Red-Herring '?' character. You can either use it as a test for end-of-substring, or ignore it altogether. Your goal is to locate str2 "street" within str1 "... streets?". You would generally use ispunct() from ctype.h to identify '?' as a non-word character and not part of the string anyway. Here, you can simply check for '?' in a similar way that you would check for '\0' to mark end-of-string.
Putting it altogether and not using any of the string.h or ctype.h functions, you could do:
#include <stdio.h>
const char *qstr_strstr (const char *str1, const char *str2)
{
int i = 0, instr2 = 0, ndx = 0; /* str1 index, in-str2 flag, str2 index */
if (str1 == NULL || str2 == NULL) /* validte both str1 and str2 not NULL */
return NULL;
do { /* loop over each char in str1 */
/* if in str2 and (at end or at '?') */
if (instr2 && (!str2[ndx] || str2[ndx] == '?'))
return &str1[i-ndx]; /* return address in str1 to start of str2 */
/* if char in str1 and str2 equal */
if (str1[i] == str2[ndx]) {
ndx += 1; /* increment str2 index */
instr2 = 1; /* set in-str2 flag true (done each time) */
}
else /* otherwise chars not equal */
ndx = instr2 = 0; /* reset str2 index, set in-str2 flag false */
} while (str1[i++]); /* includes \0, allows match at end of both */
return NULL;
}
int main (void) {
const char *str1 = "Watch of the streets?",
*str2 = "street?",
*ptr = qstr_strstr (str1, str2);
if (ptr) {
size_t i = ptr - str1;
printf ("ptr : %s\nptr addr : %p\n---\n"
"&str1[%zu] : %s\n&str1[%zu] : %p\n",
ptr, (void*)ptr, i, str1 + i, i, (void*)(str1 + i));
}
}
Example Use/Output
Outputting the string and adderss retuned by qstr_strstr() as well as the address of that string and address located within the original str1 you would have:
$ ./bin/strstrawk
ptr : streets?
ptr addr : 0x4006c1
---
&str1[13] : streets?
&str1[13] : 0x4006c1
You can further copy just the substring street from the address in str1 or whatever else you need to do. Look things over and let me know if you have further questions.
Edit Based On Picture Added
If you want to output just the characters before the '?' from the pointer returned by qstr_strstr(), then you can do that trivially by using the precision modifier with the "%s" output conversion specifier in your printf format string and limit the number of characters output to just the number before the '?' in str2. Your format conversion specifier would look like "%.*s" where it expects 2 arguments, the first of type int being the number of characters, and the second the string.
In the case above the arguments would be:
(int)strcspn (str2, "?"), ptr
Where strcspn() returns the number of characters before the '?' in str2 (cast to int) and ptr the return from qstr_strstr(). Changing the code above you would have:
...
#include <string.h>
...
printf ("ptr : %.*s\nptr addr : %p\n---\n"
"&str1[%zu] : %s\n&str1[%zu] : %p\n",
(int)strcspn (str2, "?"), ptr, (void*)ptr,
i, str1 + i, i, (void*)(str1 + i));
(the remaining code is unchanged)
$ ./bin/strstrawk
ptr : street
ptr addr : 0x4006c1
---
&str1[13] : streets?
&str1[13] : 0x4006c1
Where the output using ptr as the string and the length from str2 is not "street".
Let me know if you have further questions.
Related
Why does the below code give Seg. Fault at last line?
char* m=ReadName();
printf("\nRead String %s\n",m); // Writes OK
char* token;
token=strtok(m,'-');
As said, read string prints w/o problem, but why cannot split to tokens?
strtok modifies its first argument, hence it should be modifiable.
Maybe ReadName() returns a pointer to a read-only char array.Can you show us your ReadName() function.
If that is the reason for seg-faullt, you can create a copy of the char array before you pass it to strtok using the strdup function like:
char *copy = strdup(m);
token = strtok(copy,'-');
....
....
free(copy); // free the copy once you are done using it.
token=strtok(m,'-'); should generate a compiler warning because the second parameter of strtok() is a const char * pointing to multiple delimiters, not a single char delimiter:
char *strtok(char *str, const char *delim);
The ASCII code of '-' is 0x2D, so passing it as the second parameter of strtok() will cause strtok() to dereference the address 0x0000002D, which will cause a segfault or access violation on most modern operating systems. To fix this, use a string literal instead of a character literal: token=strtok(m,"-");
There's also the issue of how the return value of ReadName() is allocated, which others have addressed in their answers.
It's impossible to know for sure without knowing what m points to. But the most likely reason is that m is pointing to readonly memory. So you can print it out, but you can't write to it.
strtok writes to the string, so it's faulting, but printf only reads from it, so it isn't.
Try this
char* m=ReadName();
printf("\nRead String %s\n",m); // Writes OK
char temp = m[0];
m[0] = temp; // I'll bet you segfault here.
Its probably because ReadName() return string. So, the assignment makes m const char* and hence, you cannot alter any of its values (modify the string). So, when 'strtok' tries to modify 'm', Segmentation Fault is there
Remedy:
char *m = malloc(sizeof(char)*MAX);
strcpy(m, ReadName());
OR
char *m = strdup(ReadName());
Code below is taken from a BSD licensed string processing library for C, called zString.
https://github.com/fnoyanisi/zString
Looking at the implementation of the function, you can see that strtok() (or in this case zstring_strtok()) relies on a static *char to preserve the last location of the delimiter and actually modifies the original string.
char *zstring_strtok(char *str, const char *delim) {
static char *static_str=0; /* var to store last address */
int index=0, strlength=0; /* integers for indexes */
int found = 0; /* check if delim is found */
/* delimiter cannot be NULL
* if no more char left, return NULL as well
*/
if (delim==0 || (str == 0 && static_str == 0))
return 0;
if (str == 0)
str = static_str;
/* get length of string */
while(str[strlength])
strlength++;
/* find the first occurance of delim */
for (index=0;index<strlength;index++)
if (str[index]==delim[0]) {
found=1;
break;
}
/* if delim is not contained in str, return str */
if (!found) {
static_str = 0;
return str;
}
/* check for consecutive delimiters
*if first char is delim, return delim
*/
if (str[0]==delim[0]) {
static_str = (str + 1);
return (char *)delim;
}
/* terminate the string
* this assignmetn requires char[], so str has to
* be char[] rather than *char
*/
str[index] = '\0';
/* save the rest of the string */
if ((str + index + 1)!=0)
static_str = (str + index + 1);
else
static_str = 0;
return str;
}
This post explains the deifference between char s[] and char *s quite well. So,
char s[]="Test to pass strtok()"; /* this can be passed to strtok() */
char *m="Test to pass strtok()"; /* passing this will result in SIGSEGV */
I am writing my own trim() in C. There is a structure which contains all string values, the structure is getting populated from the data coming from a file which contains spaces before and after the beginning of a word.
char *trim(char *string)
{
int stPos,endPos;
int len=strlen(string);
for(stPos=0;stPos<len && string[stPos]==' ';++stPos);
for(endPos=len-1;endPos>=0 && string[endPos]==' ';--endPos);
char *trimmedStr = (char*)malloc(len*sizeof(char));
strncpy(trimmedStr,string+stPos,endPos+1);
return trimmedStr;
}
int main()
{
char string1[]=" a sdf ie ";
char *string =trim(string1);
printf("%s",string);
return 0;
}
Above code is working fine, but i don't want to declare new variable that stores the trimmed word. As the structure contains around 100 variables.
Is there any way to do somthing like below where I dont need any second variable to print the trimmed string.
printf("%s",trim(string1));
I believe above print can create dangling pointer situation.
Also, is there any way where I don't have to charge original string as well, like if I print trim(string) it will print trimmed string and when i print only string, it will print original string
elcuco was faster. but it's done so here we go:
char *trim(char *string)
{
char *ptr = NULL;
while (*string == ' ') string++; // chomp away space at the start
ptr = string + strlen(string) - 1; // jump to the last char (-1 because '\0')
while (*ptr == ' '){ *ptr = '\0' ; ptr--; } ; // overwrite with end of string
return string; // return pointer to the modified start
}
If you don't want to alter the original string I'd write a special print instead:
void trim_print(char *string)
{
char *ptr = NULL;
while (*string == ' ') string++; // chomp away space at the start
ptr = string + strlen(string) - 1; // jump to the last char (-1 because '\0')
while (*ptr == ' '){ ptr--; } ; // find end of string
while (string <= ptr) { putchar(*string++); } // you get the picture
}
something like that.
You could the original string in order to do this. For trimming the prefix I just advance the pointer, and for the suffix, I actually add \0. If you want to keep the original starting as is, you will have to move memory (which makes this an O(n^2) time complexity solution, from an O(n) I provided).
#include <stdio.h>
char *trim(char *string)
{
// trim prefix
while ((*string) == ' ' ) {
string ++;
}
// find end of original string
char *c = string;
while (*c) {
c ++;
}
c--;
// trim suffix
while ((*c) == ' ' ) {
*c = '\0';
c--;
}
return string;
}
int main()
{
char string1[] = " abcdefg abcdf ";
char *string = trim(string1);
printf("String is [%s]\n",string);
return 0;
}
(re-thinking... is it really O(n^2)? Or is it O(2n) which is a higher O(n)...? I guess depending on implementation)
You can modify the function by giving the output in the same input string
void trim(char *string)
{
int i;
int stPos,endPos;
int len=strlen(string);
for(stPos=0;stPos<len && string[stPos]==' ';++stPos);
for(endPos=len-1;endPos>=0 && string[endPos]==' ';--endPos);
for (i=0; i<=(endPos-stPos); i++)
{
string[i] = string[i+stPos];
}
string[i] = '\0'; // terminate the string and discard the remaining spaces.
}
...is there any way where i don't have to charge original string as well, like if i do trim(string) it will print trimmed string and when i print only string, it will print original string – avinashse 8 mins ago
Yes, though it gets silly.
You could modify the original string.
trim(string);
printf("trimmed: %s\n", string);
The advantage is you have the option of duplicating the string if you want to retain the original.
char *original = strdup(string);
trim(string);
printf("trimmed: %s\n", string);
If you don't want to modify the original string, that means you need to allocate memory for the modified string. That memory then must be freed. That means a new variable to hold the pointer so you can free it.
char *trimmed = trim(original);
printf("trimmed: %s\n", trimmed);
free(trimmed);
You can get around this by passing a function pointer into trim and having trim manage all the memory for you.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void trim(char *string, void(*func)(char *) )
{
// Advance the pointer to the first non-space char
while( *string == ' ' ) {
string++;
}
// Shrink the length to the last non-space char.
size_t len = strlen(string);
while(string[len-1]==' ') {
len--;
}
// Copy the string to stack memory
char trimmedStr[len + 1];
strncpy(trimmedStr,string, len);
// strncpy does not add a null byte, add it ourselves.
trimmedStr[len] = '\0';
// pass the trimmed string into the user function.
func(trimmedStr);
}
void print_string(char *str) {
printf("'%s'\n", str);
}
int main()
{
char string[]=" a sdf ie ";
trim(string, print_string);
printf("original: '%s'\n", string);
return 0;
}
Ta da! One variable, the original is left unmodified, no memory leaks.
While function pointers have their uses, this is a bit silly.
It's C. Get used to managing memory. ¯\_(ツ)_/¯
Also, is there any way where I don't have to charge original string as
well, like if I print trim(string) it will print trimmed string and
when i print only string, it will print original string
Yes you can, but you cannot allocate new memory in the trim function as you will not be holding the return memory.
You can have a static char buffer in the trim function and operate on it.
Updated version of #elcuco answer.
#include <stdio.h>
char *trim(char *string)
{
static char buff[some max length];
// trim prefix
while ((*string) == ' ' ) {
string++;
}
// find end of original string
int i = 0;
while (*string) {
buff[i++] = *string;
string++;
}
// trim suffix
while ((buff[i]) == ' ' ) {
buff[i] = '\0';
i--;
}
return buff;
}
int main()
{
char string1[] = " abcdefg abcdf ";
char *string = trim(string1);
printf("String is [%s]\n",string);
return 0;
}
With this you don't need to worry about holding reference to trim function return.
Note: Previous values of buff will be overwritten with new call to trim function.
If you don't want to change the original, then you will need to make a copy, or pass a second array of sufficient size as a parameter to your function for filling. Otherwise a simple in-place trmming is fine -- so long as the original string is mutable.
An easy way to approach trimming on leading and trailing whitespace is to determine the number of leading whitespace characters to remove. Then simply use memmove to move from the first non-whitespace character back to the beginning of the string (don't forget to move the nul-character with the right portion of the string).
That leaves only removing trailing whitespace. An easy approach there is to loop from the end of the string toward the beginning, overwriting each character of trailing whitespace with a nul-character until your first non-whitespace character denoting the new end of string is found.
A simple implementation for that could be:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define DELIM " \t\n" /* whitespace constant delimiters for strspn */
/** trim leading and trailing whitespace from s, (s must be mutable) */
char *trim (char *s)
{
size_t beg = strspn (s, DELIM), /* no of chars of leading whitespace */
len = strlen (s); /* length of s */
if (beg == len) { /* string is all whitespace */
*s = 0; /* make s the empty-string */
return s;
}
memmove (s, s + beg, len - beg + 1); /* shift string to beginning */
for (int i = (int)(len - beg - 1); i >= 0; i--) { /* loop from end */
if (isspace(s[i])) /* checking if char is whitespace */
s[i] = 0; /* overwrite with nul-character */
else
break; /* otherwise - done */
}
return s; /* Return s */
}
int main (void) {
char string1[] = " a sdf ie ";
printf ("original: '%s'\n", string1);
printf ("trimmed : '%s'\n", trim(string1));
}
(note: additional intervening whitespace was added to your initial string to show that multiple intervening whitespace is left unchanged, the output is single-quoted to show the remaining text boundaries)
Example Use/Output
$ ./bin/strtrim
original: ' a sdf ie '
trimmed : 'a sdf ie'
Look things over and let me know if you have further questions.
I want to save part of a string into a new char array while including the period. For example, the string is:
My name is John. I have 1 dog.
I want to copy each char up to and including the first period, so the new char array will contain:
My name is John.
The code I have written below copies only "My name is John" but omits the period.
ptrBeg and ptrEnd point to the char at the beginning and end, respectively, of the portion I want to copy. My intention was to copy ptrBeg into array newBuf through a pointer to newBuf and then increment both ptrBeg and the pointer to the array until ptrBeg and ptrEnd point to the same char, which should always be a period.
At this point, the text of the string should be copied, so I increment the pointer to char array once more and copy the period to the new space using
++ptrnewBuf;
*ptrnewBuf = *ptrEnd";
Finally, I print the contents of newBuf.
Here's the total code:
int main()
{
char buf[] = "My name is John. I have 1 dog.";
char * ptrBuf;
char * ptrBeg;
char * ptrEnd;
ptrBeg = buf;
ptrBuf = ptrBeg;
while (*ptrBuf != '.'){
ptrBuf++;
}
ptrEnd = ptrBuf;
char newBuf[100];
char * ptrnewBuf = newBuf;
while(*ptrBeg != *ptrEnd){
*ptrnewBuf = *ptrBeg;
ptrnewBuf++;
ptrBeg++;
}
++ptrnewBuf;
*ptrnewBuf = *ptrEnd;
printf("%s", newBuf);
}
How would I modify this code to include a period?
You are on the right track, but you may be making things a bit more complicated than needed and overlooking a few critical checks. The key to iterating by pointers or using pointer arithmetic is to always validate and protect your array or memory bounds during each iteration or arithmetic operation.
Another tip is to always map out your pointer positions on a piece of paper before coding everything up so you have a clear picture of what your iteration limits and any adjustments need to be. (you don't have to use full long strings and many boxes, just use a representation of what needs to be done with a handful of characters) In your case where you wish to copy the substing up through the first '.', something simple like the following will do, e.g.
+---+---+---+---+---+---+
| A | . | | B | . |\0 |
+---+---+---+---+---+---+
^ ^
| pointer (when *p == '.')
buf
So to copy "A." from buf to a new buffer you can't simply iterate while (*p != '.') or you will not copy '.'. By drawing it out, you can clearly see you need to also copy the character when p == '.', e.g.
+---+---+---+---+---+---+
| A | . | | B | . |\0 |
+---+---+---+---+---+---+
^ ^
| |-->| pointer (p + 1)
buf
Now regardless of the actual length of the string before '.', you now know you need p + 1 as the final address to include the last character in the copy.
You also know how many characters your new buffer can store. Say the size of new is MAXC characters (maximum number of characters). So you can store a string of at most MAXC-1 characters (plus the nul-character). When you are filling new you need to always validate you are within MAXC-1 characters.
You also need to insure you new string is nul-terminated (or it isn't a string, it's simply an array of characters). One effective way to insure nul-termination is by initializing all characters in new to 0 when it is declared, e.g.
char new[MAXC] = "";
which initializes the 1st character to 0 (e.g. '\0' empty-string) and all remaining characters 0 by default. Now if you fill no more than MAXC-1 characters, you are guaranteed the array will be a nul-terminated string.
Putting it altogether, you could do something like the following:
#include <stdio.h>
#define MAXC 128 /* if you need a constant, #define one (or more) */
int main (void) {
char buf[] = "My name is John. I have 1 dog.",
*p = buf, /* pointer to buf */
new[MAXC] = "", /* buffer for substring */
*n = new; /* pointer to new */
size_t ndx = 0; /* index for new */
/* loop copying each char until new full, '.' copied, or end of buf */
for (; ndx + 1 < MAXC && *p; p++, n++, ndx++) {
*n = *p; /* copy char from buf to new */
if (*n == '.') /* if char was '.' break */
break;
}
printf ("buf: %s\nnew: %s\n", buf, new);
return 0;
}
(note: ndx is incremented as part of the for loop to track the number of characters copied with the pointers)
Example Use/Output
$ ./bin/str_cpy_substr
buf: My name is John. I have 1 dog.
new: My name is John.
If you do not have the luxury of initializing the string to insure nul-termination, you can always affirmatively nul-terminate after your copy is done. For example, you could add the following after the for loop exit to insure an array of unknown initialization is properly terminated:
*++n = 0; /* nul-terminate (if not already done by initialization) and
* note ++n applied before * due to C operator precedence.
*/
Look things over and let me know if you have further questions.
Just breaking it out into a helper function that "extracts" the first sentence from a line. Just copies the characters over one at a time until either an end of string condition is hit on the source, the period is found, or a max length of the destination buffer is encountered.
void ExtractFirstSentence(const char* line, char* dst, int size)
{
int count = 0;
char c ='\0';
if ((line == NULL) || (dst == NULL) || (size <= 0))
{
return;
}
while ((*line) && ((count+1) < size) && (c != '.'))
{
c = *line++;
*dst++ = c;
count++;
}
*dst = '\0';
}
int main()
{
char buf[] = "My name is John. I have 1 dog.";
char newBuf[100];
ExtractFirstSentence(buf, newBuf, 100);
printf("%s", newBuf);
}
if you want something a bit easier without dealing with all those pointers, try :
int main()
{
char buf[] = "My name is John. I have 1 dog.";
int i = 0;
int j = 0;
while(buf[i] != '.' && buf[i] != '\0') {
i++;
}
char newbuf[i+1];
while (j <= i) {
newbuf[j] = buf[j];
j++;
}
newbuf[j] = '\0';
printf("%s\n",newbuf);
return 0;
}
though the i+1 when making newbuf and the newbuff[j] = '\0' im not 100% certain need to be that way. my thoughts are the i+1 is needed to make room for the \0 ending which is then added after the while loop copying buf to newbuf. but i could be mistaken.
You can use strtok() to split string. Just type man strtok, You will see:
Program source
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr, "Usage: %s string delim subdelim\n",
argv[0]);
exit(EXIT_FAILURE);
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
break;
printf("%d: %s\n", j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
break;
printf(" --> %s\n", subtoken);
}
}
exit(EXIT_SUCCESS);
}
An example of the output produced by this program is the following:
$ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
1: a/bbb///cc
--> a
--> bbb
--> cc
2: xxx
--> xxx
3: yyy
--> yyy
I have a string (pathname) in C, and I need to remove the last /... from the string.
Ex: home/usr/bin/ls
Wanted result: home/usr/bin
I can't seem to think of a way to do this to be honest. I tried strtok() but this splits the string from the first occurence of the delimiter, I just need to remove the text after the last occurence of "/". If anyone has any pointers to a method in C that can help me to this, I would be very grateful.
Use strrchr.
Here max string length is 50 bytes.
int main()
{
char s1[50];
printf("enter your string\n");
fgets(s1, 50, stdin);
char *p;
p=strrchr(s1, '/');
if(p)
*p='\0';
printf("output is %s\n",s1);
return 0;
}
Loop strtok until no more / are found, then split at previously found /
Or, in this special case try using the dirname() function
There are many, many ways to do this. One of the simplest is to use strrchr to find last occurrence of '/' in the path and set it to null (i.e. make it the new end of string):
#include <stdio.h>
#include <string.h>
int main () {
char mypath[] = "home/usr/bin/ls";
char *p = strrchr (mypath, '/'); /* find last '/' in mypath */
*p = 0; /* set as null-termination */
printf ("\n mypath : %s\n\n", mypath); /* print it */
return 0;
}
output:
$ ./bin/trimpath
mypath : home/usr/bin
Another alternative is to find the length of mypath (i.e. size_t len = strlen (mypath);) and then using a pointer, decrement the pointer mypath + len -1 until / is found and set / to null:
char *p = (mypath + strlen (mypath) - 1);
while (p > mypath)
{
if (*p == '/') {
*p = 0;
break;
}
p--;
}
Say if I have :
unsigned char* str = "k0kg"
And 0 is the null element. When I loop through it using a for loop, how do I check if the array has a null?
I tried:
if (str[1]==0):
I also tried:
if (str[1]=="0"):
And they didn't work. :(
The loop:
for (i=0;i<num_bytes;i++){
if (str[i]!=0){
printf("null spotted\n");
}
In C, strings, by definition, are terminated by '\0', the NUL character. So all (valid) strings have a '\0' in them, at the end.
To find the position of the '\0', simply use strlen():
const char * const end = str + strlen(str);
It's odd that you are using "unsigned char" if you are dealing with normal, printable strings. If you mean that you have a memory block with bytes it in and you want to find the first 0x00 byte, then you'll need a pointer to the start of the memory and the size of the memory area, in bytes. Then, you'd use memchr():
// Where strSize is the number of bytes that str points to.
const unsigned char * const end = memchr(str, 0, strSize);
If you are actually looking for the null element then you should do the following condition :
if(str[i]=='\0')
Say if I have : unsigned char* str = "k0kg"
And 0 is the null element. When I loop through it using a for loop, how do I check if the array has a null?
You're terminology is going to confuse any C programmer. You're confusing character representations with values. You're not looking for a null character ("null element", which would be '\0'), you're looking for the character '0'. So...
int len = strlen(str);
for(int i = 0; i < len; ++i) {
if(str[i] == '0')
printf("found it");
}
use strchr
#include <stdio.h>
#include <string.h>
int main(){
char *str = "k0kg";
char *p = strchr(str, '0');
if(p){
printf("find at %d\n", (int)(p - str));//find at 1
}
if(p=strchr(str, 0)){
printf("find at %d\n", (int)(p - str));//find at 4
}
str = "k\0kg";
if(p=strchr(str, 0)){
printf("find at %d\n", (int)(p - str));//find at 1
}
return 0;
}