How to write your own strchr in c using pointers? - c

Ok, so I have an assignment here from my professor. Here it is:
Write a function called strchr406. It is passed 2 parameters: a string and a char Here is the prototype for the function:
char *strchr406(char str[], char ch);
The function should return a pointer to the first instance of ch in str. For example:
char s[ ] = "abcbc";
strchr406(s, 'b'); // returns s + 1 (i.e., a pointer to the first 'b' in s)
strchr406(s, 'c'); // returns s + 2
strchr406(s, 'd'); // returns 0
He is asking us to write our own version of strchr using pointers. I looked up online for resources but none of it matches what he is asking us to do. I'm working with a group of other students, and none of us could figure this out.
How do we RETURN "s + 1"?
So far, I have this:
(I also put it online if that's easier: https://repl.it/FVK8)
#include <stdio.h>
#include "string_problems.h"
int main() {
char s[ ] = "abcbc";
strchr406(s, 'b'); // returns s + 1 (i.e., a pointer to the first 'b' in s)
strchr406(s, 'c'); // returns s + 2
strchr406(s, 'd'); // returns 0
printf("this should return %s\n", strchr406(s, 'c'));
return 0;
}
char *strchr406(char str[], char ch) {
char *p = str;
int index = 0;
while (*str != ch) {
++str;
++index;
}
if (*str == ch) {
return p + index;
} else {
return 0;
}
}
I'm getting weird outputs. Any help is appreciated.

From the manual:
char *strchr(const char *s, int c); --> the 2nd argument is an int
The strchr() and strrchr() functions return a pointer to the matched character or NULL if the character is not found.
The terminating null byte is considered part of the string,
so that if c is specified as '\0', these functions return a pointer to the terminator.
[there is no defined behaviour if the first argument happens to be NULL]
char *strchr42(char *str, int ch)
{
for (;; str++) {
if (*str == ch) return str;
if (!*str) return NULL;
}
return NULL;
}
or even shorter:
char *strchr42a(char *str, int ch)
{
do {
if (*str == ch) return str;
} while (*str++) ;
return NULL;
}

Here you are
#include <stdio.h>
char * strchr406( const char str[], char ch )
{
while ( *str && *str != ch ) ++str;
return ( char * )( ch == *str ? str : NULL );
}
int main(void)
{
char s[ ] = "abcbc";
printf( "strchr406(s, 'b') == s + 1 is %d\n", strchr406(s, 'b') == s + 1 );
printf( "strchr406(s, 'c') == s + 2 is %d\n", strchr406(s, 'c') == s + 2 );
printf( "strchr406(s, 'd') == 0 is %d\n", strchr406(s, 'd') == 0 );
printf( "this should return %s\n", strchr406(s, 'c'));
return 0;
}
The program output is
strchr406(s, 'b') == s + 1 is 1
strchr406(s, 'c') == s + 2 is 1
strchr406(s, 'd') == 0 is 1
this should return cbc
Say your professor that it will be correct to declare the function like
char * strchr406( const char str[], char ch );
^^^^^
Moreover the standard function has the following declaration
char *strchr(const char *s, int c);
because character literals in C have the type int.
So you could write the function even the following way
char * strchr406( const char str[], int ch )
{
unsigned char c = ch;
while ( *str && ( unsigned char )*str != c ) ++str;
return ( char * )( c == ( unsigned char )*str ? str : NULL );
}
As for your function then there is no sense to use the variable index because the pointer str is increased itself.

There are a couple of small things you should add or re-organize in your code to make it work.
First, this piece of code
while (*str != ch) {
++str;
++index;
}
will not stop at the end of your string and will continue looping until it finds your char somewhere after the string in the virtual memory of the process.
So you should probably have a condition for stopping that checks for the end of the string (strings in C ends with the char \0, ASCII code = 0):
while (*str != '\0')
Second thing, you are comparing ch with the current char of the string after the loop. You should probably move this code inside the loop: you need to check every character of the string against ch. Also, you don't need to use both an index and increment the pointer str. So you can get rid of the index variable. If at anytime in your loop you find the correct ch then you can directly return the pointer to it using str. If you get out of your loop, it means that you did not find the ch inside str and then you can return NULL (cf man strchr for more on return values).
char *strchr406(char str[], char ch)
{
while (*str != '\0')
{
if (*str == ch)
{
return (str);
}
str++;
}
return (NULL);
}
Note that in this context, even though NULL is 0, it's better to use NULL since you are supposed to return a pointer.
Last thing, if you want to do exactly like strchr, then if ch is '\0' you should return the pointer to the '\0' at the end of the string str. From the man: The terminating null byte is considered part of the string, so that if c is specified as '\0', these functions return a pointer to the terminator. So your code becomes:
char *strchr406(char str[], char ch)
{
while (*str != '\0')
{
if (*str == ch)
{
return (str);
}
str++;
}
/**
* if ch is '\0', you should return
* the pointer to the `\0` of the string str
*/
if (*str == ch)
{
return (str);
}
return (NULL);
}
Note: Thanks to #chux for pointing this last thing out.
Note 2: You don't need to check if str is NULL in this context.
Note 3: The "official" prototype for strchr is char *strchr(const char *s, int c); so depending on your project requirements you might want to update your prototype to match to this one.

Related

How do I return a char from a char pointer function in C?

i recently made a function that finds the smallest character in a string. I am not sure how to return the smallest character in a char pointer function.
#include <stdio.h>
#include <string.h>
char * smallest(char s[])
{
char small = 'z';
int i = 0;
while (s[i] != '\0')
{
if (s[i] < small)
{
small = s[i];
}
i++;
}
return small;
}
int main(void)
{
char s[4] = "dog";
printf("%c",smallest(s));
}
The variable small has the type char according to its declaration
char small = 'z';
//...
return small;
and this variable is returned from the function while the function return type is the pointer type char *.
char * smallest(char s[])
Also if the user will pass an empty string to the function then you will try to return the character 'z' as a smallest character though this character is absent in the empty string.
I think in this case you should return a pointer to the terminating zero character '\0'.
The function can be defined the following way
char * smallest( char s[] )
{
char *small = s;
if ( *s )
{
while ( *++s )
{
if ( *s < *small ) small = s;
}
}
return small;
}
Or as in C there is no function overloading then the function should be declared and defined like
char * smallest( const char s[] )
{
const char *small = s;
if ( *s )
{
while ( *++s )
{
if ( *s < *small ) small = s;
}
}
return ( char * )small;
}
Pay attention to that this assert
assert(smallest(s[4] == 'd'));
is incorrect, It seems you mean
assert( *smallest( s ) == 'd');
Or after you updated your program you need to write
printf("%c\n",*smallest(s));
instead of
printf("%c",smallest(s));
Using this function you can not only to find the smallest character but also to determine its position in the source string.
For example
char *small = smallest( s );
printf( "The smallest character is '%c' at the position %tu\n",
*small, small - s );
or
char *small = smallest( s );
if ( *small == '\0' )
{
puts( "The source string is empty" );
}
else
{
printf( "The smallest character is '%c' at the position %tu\n",
*small, small - s );
}
There are two problems with your program.
1. Wrong parameters
The function smallest(char[] s)expects to be given an character array but what you are passing in as an argument is s[4] == 'd' which is not a character array.
This has nothing to do with the assert() itself.
What you want to do is assert(smallest(s) == 'd').
2. Wrong return type
Your function is declares that it would return *char (= a pointer to a char) but you are trying to return a char. So you should adjust the return type of your function to be char.
The correct program:
#include <stdio.h>
#include <assert.h>
#include <string.h>
char smallest(char s[]) {
char small = 'z';
int i = 0;
while(s[i] != '\0') {
if (s[i] < small) {
small = s[i];
}
i++;
}
return small;
}
int main(void) {
char s[4] = "dog";
assert(smallest(s) == 'd');
printf("Passed\n");
}

Finding an index of array in C

i wanted to write a code which would allow me to find a position of a fist occurence of a letter, this is what i have come up so far. As you can see, what the function returns is actually a value and not the index. Is there a way to find it without simply giving the initial value of index as in the code no.2?
char *recFirstPosition(char * source, int letter)
{
if(*source == letter)
return *source;
if (*source =='\0')
return 0;
recFirstPosition(++source, letter);
}
char *recFirstPosition(char * source, int letter, int index)
{
if(*(source+index) == letter)
return index;
if (*(source+index) =='\0')
return 0;
recFirstPosition(source, letter, ++index);
}
Simply detach * from the first return and add return for the recursive call of your first version.
char *recFirstPosition(char * source, int letter)
{
if(*source == letter)
return source;
if (*source =='\0')
return 0;
return recFirstPosition(++source, letter);
}
It will make the code work. Your first version causes a type error.
The following is more readable version than the above:
char *recFirstPosition(char *source, char letter)
{
if (*source == '\0')
return NULL;
else if (*source == letter)
return source;
else
return recFirstPosition(++source, letter);
}
The above code also changed the type of the second parameter, but is written mostly inspired by several comments (Special thanks to Yuli and Dmitri).
And you may use the function as follows:
int main()
{
char *s = "Hello";
char *p = recFirstPosition(s, 'l');
if (p != NULL) {
int index = p - s;
printf("%s[%d] = %c\n", s, index, *p);
}
return 0;
}
Here is what I think could work. Please test it more since I did not have enough time to work with it
Edit: This return the position of the last occurrence but should give you enough to work with.
Edit2: Updated the function so now it works for
#include <stdio.h>
char *recFirstPosition(const char *s, int c, char *find){
if(s==NULL) return NULL;
if(*s == '\0') return (c == '\0') ? (char*)s : find;
if(*s == c) return (char*) s;
return recFirstPosition(s + 1, c, *s == c ? (char*)s : find);
}
int main ()
{
char str[] = "This is a sample string";
char * pch;
printf ("Looking for the 's' character in \"%s\"...\n",str);
pch=recFirstPosition(str,'s', NULL);
// Uncomment the while loop to get all instances positions
//while (pch!=NULL)
//{
printf ("found at %d\n",pch-str+1);
// pch=recFirstPosition(pch+1,'s',NULL);
//}
return 0;
}
output
Looking for the 's' character in "This is a sample string"...
found at 4

strchr implementation in c is it possible to make this work?

please help me out , I'm trying to implement strchr and I still get Null when I run this code... what is it wrong with it?
char *ft_strchr(const char *str, int c)
{
int i;
char *temp;
i = 0;
while (str[i])
{
if (str[i] == c)
{
*temp = str[i];
return (temp);
}
else
return (NULL);
i++;
}
return (str);
}
char* ft_strchr(const char *str, int c){
size_t i;
char *temp;
i = 0;
while (str[i])
{
if (str[i] == c)
{
temp = &str[i];
return temp;
}
i++;
}
if(str[i]==c)
{
return &str[i];
}
return NULL;
// You need to return NULL after scanning whole line..
// Or it will send NULL checking after 1st character
}
strchr is supposed to return a pointer to the matching character in the string. You're returning a pointer, but it doesn't point into the string. You never initialized it, so it doesn't point anywhere.
Change
*temp = str[i];
to:
temp = &str[i];
the following code:
makes use of the fact the C passes by value rather than by reference
eliminates the code clutter,
uses a for() statement so the compiler handles all the loop details,
eliminates all the code clutter
Note: this kind of expression: *str evaluates to true, except when the char pointed at is '\0'.
So the below code walks through the passed in char string, terminating on either of two conditions.
1) a matching char is found in the string or
2) end of string is encountered.
The return statement returns NULL if end of string is encountered, else returns the address of where the matching char is first found in the string.
char *ft_strchr(const char *str, int c)
{
for( ; *str && (*str != c); str++ ) ;
return ( *str? str : NULL);
}

Why string termination not happening at null character

Why it prints null character in second string?
Declaring character array should automatically add null character at end. Is this dependent on compiler?
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool ChckStrng(char *str);
void main()
{
char a[] = "hello";
char b[] = "abc";
printf("a:%d\n", ChckStrng(a));
printf("b:%d\n", ChckStrng(b));
}
bool ChckStrng(char *str)
{
int count[26];
while(str != NULL)
{
printf(":%d:\n", *str - 'a');
if(++count[*str - 'a'] > 1)
return false;
str = str + 1;
}
printf("end\n");
return true;
}
Output1:
:7:
:4:
:11:
:11:
a:0
:0:
:1:
:2:
:-97:
:-97:
b:0
You are comparing pointers here, in other words, if str is set to NULL:
while(str != NULL) /* str holds the address of a char */
You need to compare characters to the null-terminator, in other words, check whether the character str points to is the null-terminator:
while(*str != '\0')
str is a pointer which holds the address *str holds the value
bool ChckStrng(char *str)
{
int count[26];
while(*str != '\0')
{
printf(":%d:\n", *str - 'a');
if(++count[*str - 'a'] > 1)
return false;
str = str + 1;
}
printf("end\n");
return true;
}
You are comparing the value of the pointer itself instead of the value pointer points to.
while( *str != '\0' )
{
Not the difference: *str, and \0 which is a null character.
NULL is a null pointer not a null character.
Pointers are different than characters. In 'C' null termination of character array is signified by ascii value 0 or NUL

How can I check if an element of an array is the terminating element and return a new line?

I need to check an array like 'Hello' and check when the terminating element is and then return a new line due to it. I've been trying code like this:
char * my_strchr(const char * string, int ch)
{
int count;
int length = strlen(string);
for(count = 0; count < length; count++)
{
if(string[count] == '\0')
{
return '\n' ;
}
}
My compiler does not like when I use these for some reason. In the function declaration for string it reads const char * string
The strlen function returns the string length without the NULL terminator. What this means is that your function does not return a char pointer, because your code will never get to the condition string[count] == '\0'.
Further, even if you did reach that condition, you are returning a char, not a char *, which is an error. Your function agreed to return a char * so some kind of char * needs to be returned, even if it points to NULL.
It also isn't clear from your function code, because it lacks a terminating bracket, but your function may never return anything.
Kind of guessing from your description, but perhaps something like this?
char * my_strchr(const char * string, int ch) {
int i;
int c;
for (i = 0; (c = string[i]) != '\0'; ++i) {
if (c == ch) return string + i; /* aka &string[i] */
}
return "\n"; /* got to the end w/o finding ch in string */
}
char *my_strchr(const char *string, int ch){
if(*string == '\0')
putchar('\n');//side effect
while(*string){
if(*string == ch)
return (char*)string;
++string;
}
return *string == ch ? (char*)string : NULL;
}

Resources