string function

D

dimitris67

How can I replace an occurence of p(a string) in an other string(s) with
np(new string)..
char* replace _pattern(char *s,char *p,char *np)
PLEASE HELP ME!!!!!
 
S

SM Ryan

# How can I replace an occurence of p(a string) in an other string(s) with
# np(new string)..
# char* replace _pattern(char *s,char *p,char *np)
# PLEASE HELP ME!!!!!

Nothing in the C library. One way to implement it is to build up a new string.
Use ststr to search for p in s. Copy characters from s to where strstr found
a match to the new string, copy np to the new string, and then advance p
past the found substring. Continue searching with strstr through the rest of
s. When strstr finds nothing, copy the remaining, unmatched portion of s to
the new string.
 
C

C.E.P.A.

dimitris67 said:
How can I replace an occurence of p(a string) in an other string(s) with
np(new string)..
char* replace _pattern(char *s,char *p,char *np)
PLEASE HELP ME!!!!!

its is quite easy, use fast kmp (knuth-morris-pratt) algorithm for searching
all occurrences of pattern1 in string and next create new string with
pattern2 (kmp returns offsets to pat1 in string so you can replace pat1
with pat2).
 
S

sridhar

use strstr so that it gives the first occurence of the string s2 in
string s1 and then copy the replacing string .

as every body knows

while(*s2++=*s1++);

do the operation of strcpy

check it out
 
W

websnarf

dimitris67 said:
How can I replace an occurence of p(a string) in an other string(s) with
np(new string)..
char* replace _pattern (char *s, const char *p, const char *np)

There are three distinct cases. |p| < |np|, |p| == |np|, |p| > |np|.

So your first step is to determine which of those three cases you are
in, and then perform the operation with custom code for each.

The |p| == |np| is trivial. Just search for occurrences of p, and
directly overwrite it with |np|.

The case where |p| > |np| is also fairly straightfoward. You have a
read pointer and write pointer, both of which are initialized to each
other. You copy and increment step by step, except when you notice an
occurrence of p. Then you copy over np in its place, then increment
the write pointer by |np|, and the read pointer by |p| and continue in
a loop.

The case where |p| < |np| is the really tricky one because you have to
perform an insert as you go, but you can't tell the amount of total
inserting you will need to do until you have completely scanned the
string. So the easiest way to do it, is to do it in two passes. In
the first pass you simply count up the number of occurrences of p, and
compute len, the length of p. You then compute the amount that the
string grows (len * (|np| - |p|)) and in a second pass going backwards
from the end you copy the string in segment chunks until you encounter
p, then you overwrite it with np, etc.

If you want to see an example of a very similar look at the function
bFindAndReplace() in "The Better String Library":

http://bstring.sf.net/
 
W

Walter Roberson

There are three distinct cases. |p| < |np|, |p| == |np|, |p| > |np|.

Travelling Salesmen worldwide are still arguing about whether
|p| == |np|


(Sorry, a little mathematics humour there...)
 
S

Stan Milam

There are three distinct cases. |p| < |np|, |p| == |np|, |p| > |np|.

So your first step is to determine which of those three cases you are
in, and then perform the operation with custom code for each.

The |p| == |np| is trivial. Just search for occurrences of p, and
directly overwrite it with |np|.

The case where |p| > |np| is also fairly straightfoward. You have a
read pointer and write pointer, both of which are initialized to each
other. You copy and increment step by step, except when you notice an
occurrence of p. Then you copy over np in its place, then increment
the write pointer by |np|, and the read pointer by |p| and continue in
a loop.

The case where |p| < |np| is the really tricky one because you have to
perform an insert as you go, but you can't tell the amount of total
inserting you will need to do until you have completely scanned the
string. So the easiest way to do it, is to do it in two passes. In
the first pass you simply count up the number of occurrences of p, and
compute len, the length of p. You then compute the amount that the
string grows (len * (|np| - |p|)) and in a second pass going backwards
from the end you copy the string in segment chunks until you encounter
p, then you overwrite it with np, etc.

If you want to see an example of a very similar look at the function
bFindAndReplace() in "The Better String Library":

http://bstring.sf.net/


You make things too complicated.

/**********************************************************************/
/* File Name: replace.c. */
/* Author: Stan Milam. */
/* Date Written: 13-Jan-2003. */
/* Description: */
/* Implement a function replace all occurances of a pattern. */
/* */
/* (c) Copyright 2005 by Stan Milam. */
/* All rights reserved. */
/* */
/**********************************************************************/

#include <errno.h>
#include <string.h>
#include <stddef.h>

**********************************************************************/
/* Name: */
/* replace(). */
/* */
/* Synopsis: */
/* #include "strtools.h" */
/* char *replace(char *target, const char *from, char *to */
/* */
/* Description: */
/* The replace function will replace all instances of the from */
/* pattern with that of the to pattern. If the to pattern is */
/* an empty string or NULL all instances of the from pattern will */
/* be removed from the target string. */
/* */
/* Note: */
/* Since a replacement pattern can be longer the the original */
/* pattern the programmer must allow for enough memory to */
/* accomodate a larger target string to allow successful */
/* completion of the operation. */
/* */
/* Arguments: */
/* char *target - The string in which patterns will be */
/* replaced. Cannot be NULL */
/* */
/* const char *from - The pattern to be replaced. Cannot be NULL */
/* or an empty string (i.e. ""). */
/* */
/* const char *to - The replacement pattern. Using a NULL */
/* pointer will be interpreted the same as an */
/* empty string (i.e. ""). */
/* */
/* Return Value: */
/* In all cases the address of the target string. Should either */
/* the target string or the from pattern be NULL the global errno */
/* variable will be set to EINVAL. */
/* */
/**********************************************************************/

char *
replace ( char *p_target, const char *p_from, const char *p_to )
{
size_t to_len, from_len;
char *l_to, *ptr, *rv = p_target;

/******************************************************************/
/* Check for excrement passed in as arguments! */
/******************************************************************/

if ( p_target == NULL || p_from == NULL || *p_from == '\0' )
errno = EINVAL;
else {

/**************************************************************/
/* I should not have to do this but some compilers complain */
/* when I try to assign the empty pointer to p_to. p_to */
/* points to a string of const characters. I should be able */
/* to change the pointer! */
/**************************************************************/

l_to = p_to == NULL ? "" : (char *) p_to;

/**************************************************************/
/* Get the lengths before we enter the loop. */
/**************************************************************/

to_len = strlen( l_to );
from_len = strlen( p_from );

for(ptr = strstr(p_target,p_from); ptr; ptr = strstr(ptr,
p_from)) {

/**********************************************************/
/* We must either shrink out the replaced pattern or make */
/* room for the new pattern. If the two patterns are of */
/* equal length we don't care. */
/**********************************************************/

if ( to_len != from_len )
memmove(ptr + to_len,ptr + from_len,strlen(ptr +
from_len)+1);

/**********************************************************/
/* Once everthing is adjusted all we have to do is */
/* replace :). */
/**********************************************************/

memmove( ptr, l_to, to_len );

/**********************************************************/
/* Bump the pointer by the length of the replacement */
/* pattern just to be safe. */
/**********************************************************/

ptr += to_len;
}
}
return rv;
}

Regards,
Stan Milam.
 
R

Richard Bos

Travelling Salesmen worldwide are still arguing about whether
|p| == |np|

(Sorry, a little mathematics humour there...)

That's not just mathematics, that's perfectly good computing science.

Richard
 
M

Malcolm

dimitris67 said:
How can I replace an occurence of p(a string) in an other string(s) with
np(new string)..
char* replace _pattern(char *s,char *p,char *np)
PLEASE HELP ME!!!!!

char *replace_pattern(char *s, char *p, char *np)
{
char *sub;

/* find pattern */
sub = strstr(s, p);
if(!sub)
{
/* pattern not found */
return 0;
}
answer = malloc( strlen(s) - strlen(p) + strlen(np) + 1);
/* out of memory. */
if(!answer)
return 0;

/* copy the leading characters */
strncpy(answer, s, sub - s);
/* evil strncpy appends no null */
answer[sub-s] = 0;
/* add the repalcement pattern */
strcat(answer, np);
/* add the trailing characters */
strcat(answer, sub + strlen(p));

return answer;
}

If you want to replace all the occurences, call iteratively until the
function returns a null. This is not very efficient and will fail if the
replacement contains the search pattern, but removing these restrictions
makes the whole thing a lot more complex.
 
C

CBFalconer

dimitris67 said:
How can I replace an occurence of p(a string) in an other string(s)
with np(new string)..
char* replace _pattern(char *s,char *p,char *np)

sed (in the unix, DJGPP, cygwin, mingw worlds) will do it nicely.
If he wants C source code to do it for multiple identifiers in one
pass, see:

<http://cbfalconer.home.att.net/download/id2id-20.zip>

no patterns there, just exact identifiers.

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
G

Gregory Pietsch

The following is an untested quick hack. There's something like this
in FreeDOS edlin 2.5 (available on ibiblio or alt.sources):

#include <string.h>

char *replace_pattern(char *s, char *p, char *np)
{
char *x;
size_t plen, nplen;

if (s == NULL || p == NULL || np == NULL)
return NULL;
x = strstr(s, p);
if (x == NULL)
return NULL;
plen = strlen(p);
nplen = strlen(np);
if (plen != nplen)
memmove(x + nplen, x + plen, strlen(x + plen) + 1);
memmove(x + plen, np, nplen);
return s;
}

/* Gregory Pietsch */
 
K

Keith Thompson

Gregory Pietsch said:
The following is an untested quick hack. There's something like this
in FreeDOS edlin 2.5 (available on ibiblio or alt.sources):

#include <string.h>

char *replace_pattern(char *s, char *p, char *np)
{
char *x;
size_t plen, nplen;

if (s == NULL || p == NULL || np == NULL)
return NULL;
x = strstr(s, p);
if (x == NULL)
return NULL;
plen = strlen(p);
nplen = strlen(np);
if (plen != nplen)
memmove(x + nplen, x + plen, strlen(x + plen) + 1);
memmove(x + plen, np, nplen);
return s;
}

You didn't quote the original question, which was:

] How can I replace an occurence of p(a string) in an other string(s) with
] np(new string)..

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

I haven't studied the code carefully, but one thing that jumps out is
that it returns NULL if p does not occur in s.

It's not clear from the orginal problem statement whether the
replacement is supposed to be done in place (writing over the previous
contents of s) or in a newly allocated string. Given that the
function returns a char* result, I assume the latter; otherwise it
might as well be a void function. In this case, surely replacing all
occurences of "foo" by "bar" in "hello" should return "hello", not
NULL.

Also, your function overwrites the original contents of s; as I
mentioned, it's not clear whether this violates the requirements.

Finally, you don't allocate any memory. That's ok if you want to
overwrite s *and* if np is no longer than p. Otherwise, you need to
allocate some extra space, and if you don't want to overwrite s you
need to allocate space for the entire result (and document that the
caller is responsible for deallocating it).
 
G

Gregory Pietsch

Keith said:
Gregory Pietsch said:
The following is an untested quick hack. There's something like this
in FreeDOS edlin 2.5 (available on ibiblio or alt.sources):

#include <string.h>

char *replace_pattern(char *s, char *p, char *np)
{
char *x;
size_t plen, nplen;

if (s == NULL || p == NULL || np == NULL)
return NULL;
x = strstr(s, p);
if (x == NULL)
return NULL;
plen = strlen(p);
nplen = strlen(np);
if (plen != nplen)
memmove(x + nplen, x + plen, strlen(x + plen) + 1);
memmove(x + plen, np, nplen);
return s;
}

You didn't quote the original question, which was:

] How can I replace an occurence of p(a string) in an other string(s) with
] np(new string)..

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

I haven't studied the code carefully, but one thing that jumps out is
that it returns NULL if p does not occur in s.

It's not clear from the orginal problem statement whether the
replacement is supposed to be done in place (writing over the previous
contents of s) or in a newly allocated string. Given that the
function returns a char* result, I assume the latter; otherwise it
might as well be a void function. In this case, surely replacing all
occurences of "foo" by "bar" in "hello" should return "hello", not
NULL.

Also, your function overwrites the original contents of s; as I
mentioned, it's not clear whether this violates the requirements.

Finally, you don't allocate any memory. That's ok if you want to
overwrite s *and* if np is no longer than p. Otherwise, you need to
allocate some extra space, and if you don't want to overwrite s you
need to allocate space for the entire result (and document that the
caller is responsible for deallocating it).

As I said, it was a quick hack. Here's one that has a lot of fixes
suggested above.

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

char *replace_pattern(char *s, char *p, char *np)
{
char *x, *r;
size_t slen, plen, nplen;

if (s == NULL || p == NULL || np == NULL)
return NULL;
x = strstr(s, p);
if (x == NULL)
return s;
plen = strlen(p);
nplen = strlen(np);
slen = strlen(s);
r = malloc(slen - plen + nplen + 1);
if (r == 0)
abort(); /* Not worried about error conditions */
strcpy(r, s);
if (plen != nplen)
memmove((r + (x - s)) + nplen, x + plen, strlen(x + plen) + 1);
memmove((r + (x - s)) + plen, np, nplen);
return r;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top