Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > how to replace a substring in a string using C?

Reply
Thread Tools

how to replace a substring in a string using C?

 
 
Paul
Guest
Posts: n/a
 
      10-30-2005
hi, there,

for example,

char *mystr="##this is##a examp#le";

I want to replace all the "##" in mystr with "****". How can I do this?

I checked all the string functions in C, but did not find one.

thanks.

 
Reply With Quote
 
 
 
 
wormpattern@gmail.com
Guest
Posts: n/a
 
      10-30-2005
I think the best choice is to write your own function. It is easy task.

 
Reply With Quote
 
 
 
 
Mike Wahler
Guest
Posts: n/a
 
      10-30-2005

"Paul" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
> hi, there,
>
> for example,
>
> char *mystr="##this is##a examp#le";
>
> I want to replace all the "##" in mystr with "****". How can I do this?


With the above construct, you can't. It's not
allowed to modify a string literal (more specifically,
an attempt to do so produces 'undefined behavior'.

However, if you change the code to store your string
in an array, it can be modified.

>
> I checked all the string functions in C, but did not find one.
>
> thanks.


#include <stdio.h>
#include <string.h>

char *replace(char *s, char old, char new)
{
char *p = s;

while(*p)
{
if(*p == old)
*p = new;

++p;
}

return s;
}

int main()
{
char mystr[] = "##this is##a examp#le";
puts(mystr);
puts(replace(mystr, '#', '*'));
return 0;
}

-Mike



 
Reply With Quote
 
Netocrat
Guest
Posts: n/a
 
      10-30-2005
On Sun, 30 Oct 2005 19:45:30 +0000, Mike Wahler wrote:
> "Paul" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed) ups.com...
>> hi, there,
>>
>> for example,
>>
>> char *mystr="##this is##a examp#le";
>>
>> I want to replace all the "##" in mystr with "****". How can I do this?


Your code looked fine Mike but I gathered the OP wanted to deal more
generally with string rather than character replacement, so here's an
extended version.

Output:

##this is##a examp#le
****this is****a examp#le

Code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *replace(const char *s, const char *old, const char *new)
{
char *ret;
int i, count = 0;
size_t newlen = strlen(new);
size_t oldlen = strlen(old);

for (i = 0; s[i] != '\0'; i++) {
if (strstr(&s[i], old) == &s[i]) {
count++;
i += oldlen - 1;
}
}

ret = malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);

i = 0;
while (*s) {
if (strstr(s, old) == s) {
strcpy(&ret[i], new);
i += newlen;
s += oldlen;
} else
ret[i++] = *s++;
}
ret[i] = '\0';

return ret;
}

int main(void)
{
char mystr[] = "##this is##a examp#le";
char *newstr = NULL;

puts(mystr);
newstr = replace(mystr, "##", "****");
printf("%s\n", newstr);

free(newstr);
return 0;
}

--
http://members.dodo.com.au/~netocrat
 
Reply With Quote
 
Skarmander
Guest
Posts: n/a
 
      10-30-2005
Netocrat wrote:
<snip>
> char *replace(const char *s, const char *old, const char *new)
> {

<snip>
> ret = malloc(i + count * (newlen - oldlen));
> if (ret == NULL)
> exit(EXIT_FAILURE);
>


Whoa, what's this? Just return NULL. It's massively rude to terminate
the program in a function like this. It's *likely* the caller can't
respond to out-of-memory either (and won't check for it if they're
sloppy), but making the decision here is silly.

S.
 
Reply With Quote
 
Netocrat
Guest
Posts: n/a
 
      10-30-2005
On Sun, 30 Oct 2005 20:40:58 +0000, Netocrat wrote:
[...]
> ret = malloc(i + count * (newlen - oldlen));


Off-by-one; should be:
ret = malloc(i + 1 + count * (newlen - oldlen));

--
http://members.dodo.com.au/~netocrat

 
Reply With Quote
 
Netocrat
Guest
Posts: n/a
 
      10-30-2005
On Sun, 30 Oct 2005 21:46:46 +0100, Skarmander wrote:

> Netocrat wrote:
> <snip>
>> char *replace(const char *s, const char *old, const char *new)
>> {

> <snip>
>> ret = malloc(i + count * (newlen - oldlen));
>> if (ret == NULL)
>> exit(EXIT_FAILURE);

>
> Whoa, what's this? Just return NULL. It's massively rude to terminate
> the program in a function like this. It's *likely* the caller can't
> respond to out-of-memory either (and won't check for it if they're
> sloppy), but making the decision here is silly.


In a generic library function I agree 100%. When it's part of a specific
simple application, a policy to abort on memory failure isn't
unreasonable. The possibility did occur to me, and the reason I didn't
take it up is that it would have added extra lines to the (demonstration)
code. OTOH, this is intended to be a portable function, so your objection
is sound.

--
http://members.dodo.com.au/~netocrat
 
Reply With Quote
 
Skarmander
Guest
Posts: n/a
 
      10-30-2005
Netocrat wrote:
> On Sun, 30 Oct 2005 21:46:46 +0100, Skarmander wrote:
>
>
>>Netocrat wrote:
>><snip>
>>
>>>char *replace(const char *s, const char *old, const char *new)
>>>{

>>
>><snip>
>>
>>> ret = malloc(i + count * (newlen - oldlen));
>>> if (ret == NULL)
>>> exit(EXIT_FAILURE);

>>
>>Whoa, what's this? Just return NULL. It's massively rude to terminate
>>the program in a function like this. It's *likely* the caller can't
>>respond to out-of-memory either (and won't check for it if they're
>>sloppy), but making the decision here is silly.

>
>
> In a generic library function I agree 100%. When it's part of a specific
> simple application, a policy to abort on memory failure isn't
> unreasonable. The possibility did occur to me, and the reason I didn't
> take it up is that it would have added extra lines to the (demonstration)
> code. OTOH, this is intended to be a portable function, so your objection
> is sound.
>


The portability (that is, portability of a function across applications)
wasn't actually my primary concern; my primary concern was separation of
concerns. Side effects of a function should be minimized to those
that are documented. A function like `replace' has no business
terminating the program, unless it's clearly stated to do just that if
it can't allocate memory.

A "policy to abort on memory failure" is reasonable only if it really is
a policy, not something the function happens to do because it's
acceptable in the (implicit, unstated) context. You shouldn't have to be
required to know this. Doing this in `main' or a major subroutine
without drawing attention to it is fine, but not a string replacement
function, no matter what program or library it occurs in.

I'm not pretending I'm telling you something new, but especially since
this is demonstration code, I'm spelling it out for the innocent.
Encouraging good habits does pay off even if things become a little more
complicated to understand. Better that than writing code that's easy,
but contains a trap. We should at least point out the trap, then. As
we've just done.

S.
 
Reply With Quote
 
websnarf@gmail.com
Guest
Posts: n/a
 
      10-30-2005
Paul wrote:
> char *mystr="##this is##a examp#le";
>
> I want to replace all the "##" in mystr with "****". How can I do this?
>
> I checked all the string functions in C, but did not find one.


That is because the C library doesn't have one. (BTW, The Better
String Library, http://bstring.sf.net/ does contain a function
"bfindreplace()" that does this.) You are also pointing mystr to a
constant string, which you cannot modify at all. So you would either
have to change the storage or allow the creation of new storage for
your desired result.

Ok, there is a big difference in general between the three cases of
expanding, shrinking, or having the same sized before and after
strings. The first may require additional storage, while the other two
never do. In this case you are expanding, so you have to solve the
problem of requiring additional storage for your result.

Also you have to define what you mean by "replace all". For example,
if you want to replace "##" with "***#", then what happens when you
apply it to "foo###bar"? Does it become "foo***##bar" or does it
become "foo******#bar"?

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

 
Reply With Quote
 
Jordan Abel
Guest
Posts: n/a
 
      10-31-2005
On 2005-10-30, Netocrat <(E-Mail Removed)> wrote:
> On Sun, 30 Oct 2005 21:46:46 +0100, Skarmander wrote:
>
>> Netocrat wrote:
>> <snip>
>>> char *replace(const char *s, const char *old, const char *new)
>>> {

>> <snip>
>>> ret = malloc(i + count * (newlen - oldlen));
>>> if (ret == NULL)
>>> exit(EXIT_FAILURE);

>>
>> Whoa, what's this? Just return NULL. It's massively rude to
>> terminate the program in a function like this. It's *likely* the
>> caller can't respond to out-of-memory either (and won't check for
>> it if they're sloppy), but making the decision here is silly.

>
> In a generic library function I agree 100%. When it's part of a
> specific simple application, a policy to abort on memory failure
> isn't unreasonable.


Then I'd do it in a malloc wrapper so that it'd be done everywhere.

> The possibility did occur to me, and the reason I didn't take it
> up is that it would have added extra lines to the (demonstration)
> code. OTOH, this is intended to be a portable function, so your
> objection is sound.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
how can I replace a substring in a string silverburgh.meryl@gmail.com C++ 7 05-31-2007 02:50 AM
A simple 'Replace' and 'Substring' question: How to add a string to another string SM Javascript 4 04-27-2007 07:22 AM
RegEx search for a substring within a substring colinhumber@gmail.com Perl Misc 3 08-03-2005 04:29 PM
Function to replace multiple occurence of substring in a string Dominique Deleris C Programming 4 02-27-2005 10:19 PM



Advertisments