Warning to newbies

W

Willem

spinoza1111 wrote:
) The point being that a professional, whether or not he uses string.H,

Oh so you're wanting a solution that doesn't use string.h ?

I've seen some iterations of your code. No offense, but it looks
needlessly complex. I think even if we were to replicate strstr()
and memcpy() with our own versions, it would still be simpler.

But sticking it all in one function, off the top of my head:

#include <stdlib.h> /* for malloc() */

size_t replace_string(char *string, char *replace, char *with, char *target)
{
char *string_ptr = string;
size_t target_len = 0;

while (*string_ptr) {
size_t replace_len = 0;
while (string_ptr[replace_len] == replace[replace_len]) {
replace_len++;
}
if (replace[replace_len] == 0) {
size_t with_len;
for (with_len = 0; with[with_len]; with_len++) {
if (target) { target[target_len] = with[with_len]; }
target_len++;
}
string_ptr += replace_len;
} else {
if (target) { target[target_len] = *string_ptr; }
target_len++;
string_ptr++;
}
}
if (target) { target[target_len] = 0 }
target_len++;
return target_len;
}

char *replace(char *string, char *replace, char *with)
{
char *result;
if (result = malloc(replace_string(string, replace, with, 0) + 1)) {
replace_string(string, replace, with, result);
}
return result;
}


Of course, this will get horridly bad performance for some nasty inputs,
especially when the 'replace' string has repeats.

To fix that you need Boyer-Moore, IIRC (which I think strstr uses ?)


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
S

santosh

Joe said:
spinoza1111 said:
On Feb 7, 7:50 pm, spinoza1111 <[email protected]> wrote:
[ all snipped ]
I suggest you spend overlong on a relatively simple task. Regard..

/*
Program: stuff.c
Author: Joe Wright
Date: 05/24/1999

The dBASE stuff() function
*/

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

#define LEN 256

void usage(void) {
printf("Usage: stuff 'cString' nStart nDelete 'cInsert'\n"
"Example: stuff 'Now is the time.' 7 0 'NOT '\n"
"Note: nStart is rel-0 in C\n"), exit(0);
}

char *stuff(char *string, int start, int delete, char *insert) {
static char str1[LEN]; /* Return buffer */
char str2[LEN]; /* Temporary buffer */
strncpy(str1, string, start);
str1[start] = 0;
strcpy( str2, string+start+delete);
strcat( str1, insert);
return strcat(str1, str2);
}

int main(int argc, char **argv) {
if (argc < 5) usage();
printf("%s\n", stuff(argv[1], atoi(argv[2]), atoi(argv[3]), argv[4]));
return 0;
}
/* End of stuff.c */

Note stuff() is eight lines, not eighty. You are a fraud.

This doesn't exactly do what spinoza1111 set out to do, and what the
subsequent examples from others like Ben and Willem did. That combined
with the fact that you're using static buffers means that a line count
comparison of this program with the others is not very meaningful.
 
S

Seebs

To fix that you need Boyer-Moore, IIRC (which I think strstr uses ?)

It may or may not. I'd guess most don't bother; it's more expensive for
the most common cases, and requires additional storage.

I got curious, and implemented one of these. Mine's using the same
spec as the Nilges one, I think (I have no idea what he means by not
NUL terminated, all the strings are, although substrings aren't necessarily),
and passes common input cases.

FWIW, this took me about ten minutes total. Errors:
* Missing quote in one of the strings (caught by compiler)
* const poisoning required me to redeclare s as a const char *
* missed a quote in the Makefile for my test cases, which caused
surprising (but correct for the input) results
* initially wrote "u = resultlen" rather than "u = result" (caught
by compiler)

The actual algorithm worked the first time. :)

I'm not trying especially hard to optimize stuff away here, on the grounds
that for most real inputs, the cost of the string functions is probably
dwarfed by the cost of a single malloc/free. I lack Nilges' strange fear
of <string.h>, but all I use is strlen, strstr, strcpy, and memcpy, all
of which are trivial to implement in a few lines of code.

I am genuinely amazed that the Nilges version is on its fourth or so iteration
and doesn't yet work. I won't be surprised if someone finds a boundary
condition I missed... well, actually, I'll be a little surprised, because this
is a pretty simple algorithm. In my preemptive defense, I just woke up less
than half an hour ago and haven't had breakfast yet.

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

#define DEBUG

char *
rep(const char *in, const char *out, const char *target) {
char *result = 0;
const char *s;
char *t, *u;
size_t inlen, outlen, targetlen, resultlen;
int count;

if (!in || !out || !target)
return 0;
inlen = strlen(in);
outlen = strlen(out);
targetlen = strlen(target);

for (count = 0, t = strstr(target, in); t; t = strstr(t, in)) {
++count;
t += inlen;
}
resultlen = targetlen + (outlen * count) - (inlen * count);
result = malloc(resultlen + 1);
if (!result)
return result;
u = result;
*u = '\0';
s = target;
for (t = strstr(target, in); t; t = strstr(t, in)) {
memcpy(u, s, (t - s));
u += (t - s);
memcpy(u, out, outlen + 1);
u += outlen;
t += inlen;
s = t;
}
strcpy(u, s);
#ifdef DEBUG
fprintf(stderr, "replaced %d occurrences, new length %d, actual %d\n",
count, (int) resultlen, (int) strlen(result));
#endif

return result;
}

int
main(int argc, char **argv) {
int i;
if (argc < 4) {
fprintf(stderr, "usage: rep in out test ...\n");
exit(EXIT_FAILURE);
}
for (i = 3; i < argc; ++i) {
char *result = rep(argv[1], argv[2], argv);
printf("%s => %s\n", argv, result ? result : "<null>");
free(result);
}
return 0;
}

-s
 
S

Seebs

I made no such suggestion.

There's a physics debate on a forum I participate in (on the brainteaser
"can you make a completely wind-powered vehicle which can, steady state,
go directly downwind faster than the wind" -- the answer is obviously "no"
and actually "yes"). I bring it up because it has a participant who reminds
me a great deal of Nilges. He has a genuinely awe-inspiring ability to
get ANYTHING wrong. He refers to kilowatt-hours as "kilowatts per hour",
then argues at length that this must be correct because a Google search on
"kW/hr" turns up pages about kilowatt hours. Someone described wind speed
as "30 to 40 miles per hour, with a peak recorded gust of 47"; our hero
pointed out that 47 is 16 miles per hour faster than the average of 35.

This is sort of like that. It's practically hypnotic trying to say something
so simple that he can't misunderstand it. It was, to nearly everyone, obvious
what the objection was. I mean, come on. It's even *in the FAQ*.

"The situation is more complicated in the case of nonstandard
headers. Some are completely system- or compiler-specific.
Some are completely unnecessary, and should be replaced by their
Standard equivalents. (For example, instead of <malloc.h>, use
<stdlib.h>.)"

(clc FAQ 10.11)

For that matter... "replace substring with other string" would be a
typical first year problem. I liked my snprintf solution because it
was relatively terse and streamlined the inner loop, and because it's
pretty easy to get things like that off by one with fencepost errors.
I didn't mention it because I thought it would offer a genuine challenge
to a programmer who was not in his first semester of classes.

-s
 
S

santosh

Willem said:
spinoza1111 wrote:
) The point being that a professional, whether or not he uses string.H,

Oh so you're wanting a solution that doesn't use string.h ?

I've seen some iterations of your code. No offense, but it looks
needlessly complex. I think even if we were to replicate strstr()
and memcpy() with our own versions, it would still be simpler.

But sticking it all in one function, off the top of my head:

#include <stdlib.h> /* for malloc() */

size_t replace_string(char *string, char *replace, char *with, char *target)
{
char *string_ptr = string;
size_t target_len = 0;

while (*string_ptr) {
size_t replace_len = 0;
while (string_ptr[replace_len] == replace[replace_len]) {
replace_len++;
}
if (replace[replace_len] == 0) {
size_t with_len;
for (with_len = 0; with[with_len]; with_len++) {
if (target) { target[target_len] = with[with_len]; }
target_len++;
}
string_ptr += replace_len;
} else {
if (target) { target[target_len] = *string_ptr; }
target_len++;
string_ptr++;
}
}
if (target) { target[target_len] = 0 }
target_len++;
return target_len;
}

char *replace(char *string, char *replace, char *with)
{
char *result;
if (result = malloc(replace_string(string, replace, with, 0) + 1)) {
replace_string(string, replace, with, result);
}
return result;
}


Of course, this will get horridly bad performance for some nasty inputs,
especially when the 'replace' string has repeats.

To fix that you need Boyer-Moore, IIRC (which I think strstr uses ?)

$ ./willem "aaa" "aaa" "t"

aaa

$ ./willem "aaa" "a" "t"

tta

So a bug somewhere.
 
S

santosh

To fix that you need Boyer-Moore, IIRC (which I think strstr uses ?)

It may or may not.  I'd guess most don't bother; it's more expensive for
the most common cases, and requires additional storage.

I got curious, and implemented one of these.  Mine's using the same
spec as the Nilges one, I think (I have no idea what he means by not
NUL terminated, all the strings are, although substrings aren't necessarily),
and passes common input cases.

FWIW, this took me about ten minutes total.  Errors:
        * Missing quote in one of the strings (caught by compiler)
        * const poisoning required me to redeclare s as a const char *
        * missed a quote in the Makefile for my test cases, which caused
          surprising (but correct for the input) results
        * initially wrote "u = resultlen" rather than "u = result" (caught
          by compiler)

The actual algorithm worked the first time.  :)

I'm not trying especially hard to optimize stuff away here, on the grounds
that for most real inputs, the cost of the string functions is probably
dwarfed by the cost of a single malloc/free.  I lack Nilges' strange fear
of <string.h>, but all I use is strlen, strstr, strcpy, and memcpy, all
of which are trivial to implement in a few lines of code.

I am genuinely amazed that the Nilges version is on its fourth or so iteration
and doesn't yet work.  I won't be surprised if someone finds a boundary
condition I missed... well, actually, I'll be a little surprised, because this
is a pretty simple algorithm.  In my preemptive defense, I just woke up less
than half an hour ago and haven't had breakfast yet.

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

        #define DEBUG

        char *
        rep(const char *in, const char *out, const char *target) {
                char *result = 0;
                const char *s;
                char *t, *u;
                size_t inlen, outlen, targetlen, resultlen;
                int count;

                if (!in || !out || !target)
                        return 0;
                inlen = strlen(in);
                outlen = strlen(out);
                targetlen = strlen(target);

                for (count = 0, t = strstr(target, in); t; t = strstr(t, in)) {
                        ++count;
                        t += inlen;
                }
                resultlen = targetlen + (outlen * count) - (inlen * count);
                result = malloc(resultlen + 1);
                if (!result)
                        return result;
                u = result;
                *u = '\0';
                s = target;
                for (t = strstr(target, in); t; t = strstr(t, in)) {
                        memcpy(u, s, (t - s));
                        u += (t - s);
                        memcpy(u, out, outlen + 1);
                        u += outlen;
                        t += inlen;
                        s = t;
                }
                strcpy(u, s);
        #ifdef DEBUG
                fprintf(stderr, "replaced %d occurrences, new length %d, actual %d\n",
                        count, (int) resultlen, (int) strlen(result));
        #endif

                return result;
        }

        int
        main(int argc, char **argv) {
                int i;
                if (argc < 4) {
                        fprintf(stderr, "usage: rep in out test ...\n");
                        exit(EXIT_FAILURE);
                }
                for (i = 3; i < argc; ++i) {
                        char *result = rep(argv[1], argv[2], argv);
                        printf("%s => %s\n", argv, result ? result : "<null>");
                        free(result);
                }
                return 0;
        }


Can you give an example of how to use this program? I tried some
values, but it seems to always replace zero occurences. I guess I'm
not feeding it the strings in the right sequence.
 
B

Ben Bacarisse

James said:
[...]
Do you think it could be beneficial to be able to do something like:

char const* src_string = "ABAB";


/* get's size minus null terminator. */
size_t new_size = replace_get_size(string, "A", "XXXX");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OOPS! That should be:

size_t new_size = replace_get_size(src_string, "A", "XXXX");

[...]
That would allow the caller of the function to handle all the memory
allocation. This might be good if the user wanted to employ a custom
allocation scheme.

Yes, that is a good idea (I was just copying seebs interface).
Another way to do this is to pass a pointer and a size:

size_t replace(const char *src, const char *what, const char *with,
char *dst, size_t dsize);

The returned size is the size needed, but no more that dsize bytes of
dst will ever be written to (including the terminating null). If dst
is a null pointer, the function just returns the size needed. A
simple wrapper then makes the interface currently being used, if that
is needed.

(There should probably be a couple of restrict qualifications in there.)
 
S

Seebs

Can you give an example of how to use this program? I tried some
values, but it seems to always replace zero occurences. I guess I'm
not feeding it the strings in the right sequence.

$ ./rep a b banana
replaced 3 occurrences, new length 6, actual 6
banana => bbnbnb

-s
 
S

santosh

Seebs said:
$ ./rep a b banana
replaced 3 occurrences, new length 6, actual 6
banana => bbnbnb

Thanks! Your versions seems to work expect that an empty string for
the 'in' parameter sends it into an infinite loop.
 
S

santosh

Seebs wrote:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEBUG

char *
rep(const char *in, const char *out, const char *target) {
char *result = 0;
const char *s;
char *t, *u;
size_t inlen, outlen, targetlen, resultlen;
int count;

if (!in || !out || !target)
return 0;
inlen = strlen(in);
outlen = strlen(out);
targetlen = strlen(target);

for (count = 0, t = strstr(target, in); t; t = strstr(t, in)) {
++count;
t += inlen;
}
resultlen = targetlen + (outlen * count) - (inlen * count);
result = malloc(resultlen + 1);
if (!result)
return result;
u = result;
*u = '\0';
s = target;
for (t = strstr(target, in); t; t = strstr(t, in)) {
memcpy(u, s, (t - s));
u += (t - s);
memcpy(u, out, outlen + 1);
u += outlen;
t += inlen;
s = t;
}
strcpy(u, s);
#ifdef DEBUG
fprintf(stderr, "replaced %d occurrences, new length %d, actual %d\n",
count, (int) resultlen, (int) strlen(result));

You probably meant strlen(target) for the fifth argument above?

<snip>
 
K

Keith Thompson

santosh said:
spinoza1111 wrote: [32 lines of text deleted] [93 lines of C deleted]

It doesn't compile here. I'm using gcc 4.3.3 on Ubuntu 9.04.

$ gcc -o spinoza1111 spinoza1111.c
[54 lines of error messages deleted]
How did it compile for you? Which compiler and what options did you
use?

It compiled without error for me (using gcc 4.3.3 on Ubuntu 9.04,
command "gcc -c c.c"). It must have been messed up somehow by your
news software.

This is not a comment on the quality of the code, which I haven't
taken the time to study.
 
J

James

Ben Bacarisse said:
James said:
[...]
Do you think it could be beneficial to be able to do something like:

char const* src_string = "ABAB";


/* get's size minus null terminator. */
size_t new_size = replace_get_size(string, "A", "XXXX");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OOPS! That should be:

size_t new_size = replace_get_size(src_string, "A", "XXXX");

[...]
That would allow the caller of the function to handle all the memory
allocation. This might be good if the user wanted to employ a custom
allocation scheme.

Yes, that is a good idea (I was just copying seebs interface).

Thanks Ben! :^)


I was also thinking that if the user knows that the exchange string is
smaller than or equal to the comparand string then everything can be done
in-place. Luckily, the interface I posted could possibly handle that as-is:


char src_string[] = "ABAB";

puts(replace(src_string, src_string, "AB", "X"));



What do you think?
 
S

Seebs

Thanks! Your versions seems to work expect that an empty string for
the 'in' parameter sends it into an infinite loop.

D'oh!

I'm not sure what the right behavior there is. I experimentally modified
it to simply append <out> after each character, but that is both uglier
and non-obvious.

So.

if (!in || !out || !target || !*in)
return 0;

I think that's the right fix.

-s
 
S

Seebs

You probably meant strlen(target) for the fifth argument above?

No. I was verifying that the calculated result length was the same as
the actual number of characters written into the result. (Note that the
malloc is for N+1 to allow for the terminating NUL.)

-s
 
S

Seebs

I was also thinking that if the user knows that the exchange string is
smaller than or equal to the comparand string then everything can be done
in-place.

This sounds error-prone, because I know that if I were using such a function,
I'd end up forgetting whether I was getting a new pointer back or not.

-s
 
J

James

Seebs said:
This sounds error-prone, because I know that if I were using such a
function,
I'd end up forgetting whether I was getting a new pointer back or not.

It's probably best to create a wrapper function; perhaps something like:


char*
replace_in_place(char* src,
char const* cmp,
char const* xchg)
{
return replace(src, src, cmp, xchg);
}


Is that any better?
 
P

Phil Carmody

Richard Heathfield said:
No, I've indicated a problem with my code. My mistake was in crediting
you with enough basic common sense to be able to work out the problem
from the information I provided.


It wasn't the angle brackets that were the problem.

Indeed. He should have had

#INCLUDE <malloc.h>

instead. Now please follow my example, and do your research before
posting nonsense to usenet.

Phil
(Is '-) necessary?)
 
J

James

[...]
I am genuinely amazed that the Nilges version is on its fourth or so
iteration
and doesn't yet work. I won't be surprised if someone finds a boundary
condition I missed... well, actually, I'll be a little surprised, because
this
is a pretty simple algorithm. In my preemptive defense, I just woke up
less
than half an hour ago and haven't had breakfast yet.
[...]


Here is what I came up with so far:
__________________________________________________________________
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>




size_t
count_sub_strings(char const* src,
char const* cmp,
size_t size)
{
char const* head = src;
size_t count = 0;

while ((head = strstr(head, cmp)))
{
++count;
head += size;
}

return count;
}




struct replace_ex
{
char* src;
char* dest;
char const* cmp;
char const* xchg;
size_t dest_size;
size_t src_size;
size_t cmp_size;
size_t xchg_size;
};




static int
replace_get_size_ex(struct replace_ex* t,
char* src,
char const* cmp,
char const* xchg);


static char*
replace_in_place_ex(struct replace_ex* t);


static char*
replace_copy_ex(struct replace_ex* t);


static char*
replace_copy(char* src,
char const* cmp,
char const* xchg);




size_t
replace_get_count_and_size_ex(struct replace_ex* t,
char* src,
char const* cmp,
char const* xchg)
{
size_t xchg_size;
size_t cmp_size = strlen(cmp);
size_t count = count_sub_strings(src, cmp, cmp_size);

t->src = src;
t->cmp = cmp;
t->xchg = xchg;
t->dest = NULL;
t->src_size = strlen(src);
t->cmp_size = cmp_size;
t->xchg_size = strlen(xchg);

cmp_size = count * t->cmp_size;
xchg_size = count * t->xchg_size;

t->dest_size = t->src_size - cmp_size + xchg_size;

return count;
}


char*
replace_in_place_ex(struct replace_ex* t)
{
char* head = t->src;
char* const tail = t->src + t->src_size;

assert(t && t->xchg_size <= t->cmp_size);

if (t->cmp_size)
{
while ((head = strstr(head, t->cmp)))
{
char* remain_tail = head + t->cmp_size;
char* remain_head = head + t->xchg_size;
size_t size = tail - remain_tail;

memcpy(head, t->xchg, t->xchg_size);
memmove(remain_head, remain_tail, size + 1);
head = remain_head;
}
}

return t->src;
}


char* replace_in_place(char* src,
char const* cmp,
char const* xchg)
{
struct replace_ex t = { NULL };

t.src = src;
t.cmp = cmp;
t.xchg = xchg;
t.src_size = strlen(src);
t.cmp_size = strlen(cmp);
t.xchg_size = strlen(xchg);

return replace_in_place_ex(&t);
}


char*
replace_copy_ex(struct replace_ex* t)
{
char* head = t->src;
char* origin_head = t->src;
char* dest_head = t->dest;

dest_head[t->dest_size] = '\0';

memset(dest_head, 'Z', t->dest_size);

while ((head = strstr(head, t->cmp)))
{
size_t size = head - origin_head;
memcpy(dest_head, origin_head, size);
dest_head += size;
memcpy(dest_head, t->xchg, t->xchg_size);
dest_head += t->xchg_size;
head += t->cmp_size;
origin_head = head;
}

if (origin_head < t->src + t->src_size)
{
size_t size = ((t->src + t->src_size) - origin_head) - 1;
assert(size);
memcpy(dest_head, origin_head,
(t->src + t->src_size) - origin_head);
}

return t->dest;
}


char*
replace_copy(char* src,
char const* cmp,
char const* xchg)
{
struct replace_ex t = { NULL };

replace_get_count_and_size_ex(&t, src, cmp, xchg);

if ((t.dest = malloc(t.dest_size + 1)))
{
replace_copy_ex(&t);
}

return t.dest;
}








char*
test_replace_and_display(char* src,
char const* cmp,
char const* xchg)
{
struct replace_ex t = { NULL };

printf("original: %s\n"
"comparand: %s\n"
"exchange: %s\n",
src,
cmp,
xchg);

if (replace_get_count_and_size_ex(&t, src, cmp, xchg))
{
if (t.dest_size <= t.src_size)
{
printf("result: %s\n"
"_______________________________________________\n",
replace_in_place_ex(&t));

t.dest = src;
}

else if ((t.dest = malloc(t.dest_size + 1)))
{
printf("allocated: %p\n"
"result: %s\n"
"_______________________________________________\n",
(void*)t.dest,
replace_copy_ex(&t));
}
}

else
{
puts("result: not found!\n"
"_______________________________________________");

t.dest = src;
}

return t.dest;
}


int
main(void)
{
char* dest1;
char* dest2;
char src[] = "XYXYX--XYXYXY--XYXYXY";


dest1 = test_replace_and_display(src, "XY", "AB");


dest2 = test_replace_and_display(dest1, "--", "<-->");
if (dest1 != src && dest1 != dest2) free(dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "--", "<-->");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "<<", "|");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, ">>", "|");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "ABABAB", "1234");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "ABABX", "ABCDEFG");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "-", "");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "||", "<<XXX>>");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "<X", "-");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, ">X", "--->");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "X>", "X--->");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "1234", "!");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "<-XX--->>!", "!");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;

dest2 = test_replace_and_display(dest1, "ABCD", "Hello");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "EFG", " World");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "!@#", "123456789");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "!!", "!");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "Hello", "Goodbye");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


dest2 = test_replace_and_display(dest1, "!", "! We are going to miss
you!");
if (dest1 != src && dest1 != dest2)
free(dest1), printf("freed: %p\n", (void*)dest1);
dest1 = dest2;


if (dest1 != src)
free(dest1), printf("freed: %p\n", (void*)dest1);


return 0;
}
__________________________________________________________________
 
J

James

James said:
[...]
I am genuinely amazed that the Nilges version is on its fourth or so
iteration
and doesn't yet work. I won't be surprised if someone finds a boundary
condition I missed... well, actually, I'll be a little surprised, because
this
is a pretty simple algorithm. In my preemptive defense, I just woke up
less
than half an hour ago and haven't had breakfast yet.
[...]


Here is what I came up with so far:
__________________________________________________________________ [...]

OOPS!


static int
replace_get_size_ex(struct replace_ex* t,
char* src,
char const* cmp,
char const* xchg);


should read as:



static size_t
replace_get_count_and_size_ex(struct replace_ex* t,
char* src,
char const* cmp,
char const* xchg);



It does not show up as an error, but as an warning for an unused declaration
in Comeau.



Sorry about that.
 
B

Ben Bacarisse

Joe Wright said:
santosh said:
Joe said:
spinoza1111 wrote:
[ all snipped ]
I suggest you spend overlong on a relatively simple task. Regard..

/*
Program: stuff.c
Author: Joe Wright
Date: 05/24/1999

The dBASE stuff() function
*/

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

#define LEN 256

void usage(void) {
printf("Usage: stuff 'cString' nStart nDelete 'cInsert'\n"
"Example: stuff 'Now is the time.' 7 0 'NOT '\n"
"Note: nStart is rel-0 in C\n"), exit(0);
}

char *stuff(char *string, int start, int delete, char *insert) {
static char str1[LEN]; /* Return buffer */
char str2[LEN]; /* Temporary buffer */
strncpy(str1, string, start);
str1[start] = 0;
strcpy( str2, string+start+delete);
strcat( str1, insert);
return strcat(str1, str2);
}

int main(int argc, char **argv) {
if (argc < 5) usage();
printf("%s\n", stuff(argv[1], atoi(argv[2]), atoi(argv[3]), argv[4]));
return 0;
}
/* End of stuff.c */

Note stuff() is eight lines, not eighty. You are a fraud.

This doesn't exactly do what spinoza1111 set out to do, and what the
subsequent examples from others like Ben and Willem did. That combined
with the fact that you're using static buffers means that a line count
comparison of this program with the others is not very meaningful.

Gimme a break. One malloc() and one free() add two lines.

How does that give you a function like the one being discussed
elsewhere in the thread?
 

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

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top