String in C: replace characters with each other - c

For example, I choose a string "sdoeoeeoasd". I should replace all the 'o' with 'e' and vice versa: "sdeoeooeasd". I intend to do this with the string lib.
I found a pretty similar question (Standard function to replace character or substring in a char array?), but I don't get how to make the code work according to my condition. It happens that the first occurence of the character is replaced, and then the only one character replaces:
char* replace_char(char* str, char find, char replace){
char temp = find;
char *current_pos = strchr(str,find);
char *current_posc2 = strchr(str,replace);
while (current_pos) {
*current_pos = replace;
current_pos = strchr(current_pos,find);
}
while (current_posc2) {
*current_posc2 = find;
current_posc2 = strchr(current_posc2, replace);
}
return str;
}
With c1='e' and c2='o' I get:
I have a thought about adding the third temp variable, but my suggestions of its implementation were wrong and didn't work.

Another solution:
int i=0;
while(ch[i])
{
if(ch[i] == 'e')
ch[i]='o';
else if(ch[i] == 'o')
ch[i]='e';
i++;
}

Do one loop:
char *replace_char(char *str, char find, char replace) {
char *str2 = str; // save str for return value
while (*str2) {
if (*str2 == find) *str2 = replace;
else if (*str2 == replace) *str2 = find;
str2++;
}
return str;
}

Your code doesn't work because it replaces all of the first character with the second character, then replaces all of the second character with the first character. It completely undoes the work of the first step in the second step. It's much simpler to just iterate through the string one character at a time, like in Bouraoui Al-Moez L.A's code.

there is no need to use two loops
char *replace_char(char *str, char find, char replace) {
char *ptr = str;
while (*ptr) {
if (*ptr == find) *ptr = replace;
else if (*ptr == replace) *ptr = find;
ptr++;
}
return str;
}
also you can use syntax array
int j=0;
while(str[j] !='\0') // will loop on your string till the end of it
{
if(str[j] == 'e') // if char=e will be o
str[j]='o';
else if(str[j] == 'o') // if char=o will be e
str[j]='e';
j++;
}
```````````````````````

Related

finding substring from a main string

My assignment is to find a substring from main string and return the pointer to the first character of the substring that is in mainstring and it needs to stop searching after "?" and the code has to be done without string.h . My code to me is working perfectly but the automatic checker says otherwise, checker says this
test_source.c:195:F:test_es_strstr:test_es_strstr:0: [07_altstring.d] Wrong return value with string "Foobarbaz?asd:w" and substring "baz?": Got 0x72, expected 0x7ffeb8b8a306
So the checker says that my pointer isn't in the right place.. but for me it is, need help.
My code =
const char *es_strstr(const char *str1, const char *str2) {
int i = 0;
int j = 0;
while (str1[j] != '?') ///function has to stop the search to
/// a question mark
{
if (*str1 == str2[i]) ///comparing main string first character
/// to substring first character
{
i++;
++str1;
if (*str1 == str2[i]) ///if first ones are match then look
/// for the next character matching
{
i++;
++str1;
if (*str1 == str2[i]) /// finally if 2nd is match then 3rd
{
--str1;
--str1;
printf("%c\n", *str1);
return *str1;
}
}
}
j++;
i = 0;
++str1;
}
return NULL; ///if nothing matches need to return NULL
int main(void) {
char *main = "Foobarbaz?asd:w";
char *sub = "baz?";
es_strstr(main, sub);
}
I think you should return pointer, i.e.
return str1;
instead of
return *str1;
*str means character pointed by str1

How to write your own strchr in c using pointers?

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.

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);
}

Substrings in the middle of a String in C

I need to extract substrings that are between Strings I know.
I have something like char string = "abcdefg";
I know what I need is between "c" and "f", then my return should be "de".
I know the strncpy() function but do not know how to apply it in the middle of a string.
Thank you.
Here's a full, working example:
#include <stdio.h>
#include <string.h>
int main(void) {
char string[] = "abcdefg";
char from[] = "c";
char to[] = "f";
char *first = strstr(string, from);
if (first == NULL) {
first = &string[0];
} else {
first += strlen(from);
}
char *last = strstr(first, to);
if (last == NULL) {
last = &string[strlen(string)];
}
char *sub = calloc(strlen(string) + 1, sizeof(char));
strncpy(sub, first, last - first);
printf("%s\n", sub);
free(sub);
return 0;
}
You can check it at this ideone.
Now, the explanation:
1.
char string[] = "abcdefg";
char from[] = "c";
char to[] = "f";
Declarations of strings: main string to be checked, beginning delimiter, ending delimiter. Note these are arrays as well, so from and to could be, for example, cd and fg, respectively.
2.
char *first = strstr(string, from);
Find occurence of the beginning delimiter in the main string. Note that it finds the first occurence - if you need to find the last one (for example, if you had the string abcabc, and you wanted a substring from the second a), it might need to be different.
3.
if (first == NULL) {
first = &string[0];
} else {
first += strlen(from);
}
Handle situation, in which the first delimiter doesn't appear in the string. In such a case, we will make a substring from the beginning of the entire string. If it does appear, however, we move the pointer by length of from string, as we need to extract the substring beginning after the first delimiter (correction thanks to #dau_sama).
Depending on your specifications, this may or may not be needed, or another result might be expected.
4.
char *last = strstr(first, to);
Find occurence of the ending delimiter in the main string. Note that it finds the first occurence.
As noted by #dau_sama, it's better to search for ending delimiter from the first, not from beginning of the entire string. This prevents situations, in which to would appear earlier than from.
5.
if (last == NULL) {
last = &string[strlen(string)];
}
Handle situation, in which the second delimiter doesn't appear in the string. In such a case, we will make a substring until end of the string, so we get a pointer to the last character.
Again, depending on your specifications, this may or may not be needed, or another result might be expected.
6.
char *sub = calloc(last - first + 1, sizeof(char));
strncpy(sub, first, last - first);
Allocate sufficient memory and extract substring based on pointers found earlier. We copy last - first (length of the substring) characters beginning from first character.
7.
printf("%s\n", sub);
Here's the result.
I hope it does present the problem with enough details. Depending on your exact specifications, you may need to alter this somehow. For example, if you needed to find all substrings, and not just the first one, you may want to make a loop for finding first and last.
TY guys, worked using the form below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *between_substring(char *str, char from, char to){
while(*str && *str != from)
++str;//skip
if(*str == '\0')
return NULL;
else
++str;
char *ret = malloc(strlen(str)+1);
char *p = ret;
while(*str && *str != to){
*p++ = *str++;//To the end if `to` do not exist
}
*p = 0;
return ret;
}
int main (void){
char source[] = "abcdefg";
char *target;
target = between(source, 'c', 'f');
printf("%s", source);
printf("%s", target);
return 0;
}
Since people seemed to not understand my approach in the comments, here's a quick hacked together stub.
const char* string = "abcdefg";
const char* b = "c";
const char* e = "f";
//look for the first pattern
const char* begin = strstr(string, b);
if(!begin)
return NULL;
//look for the end pattern
const char* end = strstr(begin, e);
if(!end)
return NULL;
end -= strlen(e);
char result[MAXLENGTH];
strncpy(result, begin, end-begin);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *between(const char *str, char from, char to){
while(*str && *str != from)
++str;//skip
if(*str == '\0')
return NULL;
else
++str;
char *ret = malloc(strlen(str)+1);
char *p = ret;
while(*str && *str != to){
*p++ = *str++;//To the end if `to` do not exist
}
*p = 0;
return ret;
}
int main(void){
const char* string = "abcdefg";
char *substr = between(string, 'c', 'f');
if(substr!=NULL){
puts(substr);
free(substr);
}
return 0;
}

Resources