Warning to newbies

S

spinoza1111

spinoza1111wrote:

<snip>














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

$ gcc -ospinoza1111spinoza1111.cspinoza1111.c:27:16: error: invalid suffix "D" on integer constantspinoza1111.c: In function ‘replace’:spinoza1111.c:27: error: expected ‘;’ before ‘strMaster’spinoza1111.c:28:27: error: invalid suffix "D" on integer constantspinoza1111.c:28: error: expected ‘;’ before numeric constantspinoza1111.c:29:19: error: invalid suffix "D" on integer constantspinoza1111.c:29: error: expected ‘;’ before numeric constantspinoza1111.c:32:20: error: invalid suffix "D" on integer constantspinoza1111.c:32: error: expected ‘;’ before ‘ptrIndex1’spinoza1111.c:34:40: error: invalid suffix "D" on integer constantspinoza1111.c:36:24: error: invalid suffix "D" on integer constantspinoza1111.c:36: error: expected ‘;’ before ‘strTarget’spinoza1111.c:36:49: error: invalid suffix "D" on integer constantspinoza1111.c:37:53: error: invalid suffix "D" on integer constantspinoza1111.c:37:56: error: invalid suffix "D" on integer constantspinoza1111.c:41:37: error: invalid suffix "D" on integer constantspinoza1111.c:42: error: expected ‘)’ before ‘malloc’spinoza1111.c:44:43: error: invalid suffix "D" on integer constantspinoza1111.c:44: error: expected ‘;’ before ‘ptrIndex0’spinoza1111.c:45:49: error: invalid suffix "D" on integer constantspinoza1111.c:46: error: expected ‘;’ before ‘ptrIndex1’spinoza1111.c:47:48: error: invalid suffix "D" on integer constantspinoza1111.c:48: error: expected ‘;’ before ‘!’ tokenspinoza1111.c:49:28: error: invalid suffix "D" on integer constantspinoza1111.c:49: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:55:40: error: invalid suffix "D" on integer constantspinoza1111.c:55: error: expected ‘;’ before numeric constantspinoza1111.c:56:40: error: invalid suffix "D" on integer constantspinoza1111.c:56: error: expected ‘)’ before numeric constantspinoza1111.c:57:48: error: invalid suffix "D" on integer constantspinoza1111.c:57: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:59:41: error: invalid suffix "D" on integer constantspinoza1111.c:59: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:60:35: error: invalid suffix "D" on integer constantspinoza1111.c:60: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:62:20: error: invalid suffix "D" on integer constantspinoza1111.c:62: error: expected ‘;’ before ‘ptrIndex3’spinoza1111.c:64:24: error: invalid suffix "D" on integer constantspinoza1111.c:64: error: expected ‘)’ before ‘malloc’spinoza1111.c:65:13: error: invalid suffix "D" on integer constantspinoza1111.c:65: error: expected ‘;’ before ‘strNewStart’spinoza1111.c:66:23: error: invalid suffix "D" on integer constantspinoza1111.c:66: error: expected ‘;’ before ‘ptrSegmentStructStarts’spinoza1111.c:69:25: error: invalid suffix "D" on integer constantspinoza1111.c:69: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:70:24: error: invalid suffix "D" on integer constantspinoza1111.c:73:23: error: invalid suffix "D" on integer constantspinoza1111.c:75:29: error: invalid suffix "D" on integer constantspinoza1111.c:75: error: expected ‘;’ before ‘strReplacement’spinoza1111.c:78:27: error: invalid suffix "D" on integer constantspinoza1111.c:79:27: error: invalid suffix "D" on integer constantspinoza1111.c:79: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:81:14: error: invalid suffix "D" on integer constantspinoza1111.c:81: error: expected ‘;’ before '\x0'

How did it compile for you? Which compiler and what options did you
use?

Microsoft C++ (and C) .Net express, with a blank project and a
filetype of C to enforce C.

I really should get GCC...although some of the regs diss it.

I will take a look at your error list.
 
S

spinoza1111

spinoza1111wrote:

<snip>














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

$ gcc -ospinoza1111spinoza1111.cspinoza1111.c:27:16: error: invalid suffix "D" on integer constantspinoza1111.c: In function ‘replace’:spinoza1111.c:27: error: expected ‘;’ before ‘strMaster’spinoza1111.c:28:27: error: invalid suffix "D" on integer constantspinoza1111.c:28: error: expected ‘;’ before numeric constantspinoza1111.c:29:19: error: invalid suffix "D" on integer constantspinoza1111.c:29: error: expected ‘;’ before numeric constantspinoza1111.c:32:20: error: invalid suffix "D" on integer constantspinoza1111.c:32: error: expected ‘;’ before ‘ptrIndex1’spinoza1111.c:34:40: error: invalid suffix "D" on integer constantspinoza1111.c:36:24: error: invalid suffix "D" on integer constantspinoza1111.c:36: error: expected ‘;’ before ‘strTarget’spinoza1111.c:36:49: error: invalid suffix "D" on integer constantspinoza1111.c:37:53: error: invalid suffix "D" on integer constantspinoza1111.c:37:56: error: invalid suffix "D" on integer constantspinoza1111.c:41:37: error: invalid suffix "D" on integer constantspinoza1111.c:42: error: expected ‘)’ before ‘malloc’spinoza1111.c:44:43: error: invalid suffix "D" on integer constantspinoza1111.c:44: error: expected ‘;’ before ‘ptrIndex0’spinoza1111.c:45:49: error: invalid suffix "D" on integer constantspinoza1111.c:46: error: expected ‘;’ before ‘ptrIndex1’spinoza1111.c:47:48: error: invalid suffix "D" on integer constantspinoza1111.c:48: error: expected ‘;’ before ‘!’ tokenspinoza1111.c:49:28: error: invalid suffix "D" on integer constantspinoza1111.c:49: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:55:40: error: invalid suffix "D" on integer constantspinoza1111.c:55: error: expected ‘;’ before numeric constantspinoza1111.c:56:40: error: invalid suffix "D" on integer constantspinoza1111.c:56: error: expected ‘)’ before numeric constantspinoza1111.c:57:48: error: invalid suffix "D" on integer constantspinoza1111.c:57: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:59:41: error: invalid suffix "D" on integer constantspinoza1111.c:59: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:60:35: error: invalid suffix "D" on integer constantspinoza1111.c:60: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:62:20: error: invalid suffix "D" on integer constantspinoza1111.c:62: error: expected ‘;’ before ‘ptrIndex3’spinoza1111.c:64:24: error: invalid suffix "D" on integer constantspinoza1111.c:64: error: expected ‘)’ before ‘malloc’spinoza1111.c:65:13: error: invalid suffix "D" on integer constantspinoza1111.c:65: error: expected ‘;’ before ‘strNewStart’spinoza1111.c:66:23: error: invalid suffix "D" on integer constantspinoza1111.c:66: error: expected ‘;’ before ‘ptrSegmentStructStarts’spinoza1111.c:69:25: error: invalid suffix "D" on integer constantspinoza1111.c:69: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:70:24: error: invalid suffix "D" on integer constantspinoza1111.c:73:23: error: invalid suffix "D" on integer constantspinoza1111.c:75:29: error: invalid suffix "D" on integer constantspinoza1111.c:75: error: expected ‘;’ before ‘strReplacement’spinoza1111.c:78:27: error: invalid suffix "D" on integer constantspinoza1111.c:79:27: error: invalid suffix "D" on integer constantspinoza1111.c:79: error: expected ‘;’ before ‘ptrSegmentStruct’spinoza1111.c:81:14: error: invalid suffix "D" on integer constantspinoza1111.c:81: error: expected ‘;’ before '\x0'

How did it compile for you? Which compiler and what options did you
use?

It looks like something your browser did, perhaps prepending or
suffixing every line with D.
 
S

santosh

spinoza1111 wrote:

<snip>

Apologies for my previous post. A cut and paste of your code from
Google Groups resulted in numerous strange sequences within your code,
which stymied the compiler obviously. I notice that it's not in your
code, but it does appear in the 'show original' link of your post on
Groups.

After a proper cut and past, I got your program to compile and
seemingly produce the expected output, as you've indicated in main().
Haven't walked through the code though.
 
S

santosh

spinoza1111 said:
santosh wrote:
[ ... ]
It looks like something your browser did, perhaps prepending or
suffixing every line with D.

Yes. It's either the browser or Google Groups, probably the latter.

Quite apart from the merits or demerits of GCC, it's useful to compile
a program under more than one compiler. It's one way of eliminating
unnecessary compiler-specific constructs and improving the portability
of the code, to an extent.

I used to compile under MSVC, Borland and GCC, but I've lost access to
a Windows system these days. Been meaning to install another copy, but
haven't got around to doing it yet.
 
S

spinoza1111

spinoza1111wrote:


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.

 > We want to hear it again, because we


It wasn't the angle brackets that were the problem. The problem was that
<malloc.h> is not a standard header, and therefore you have no
guarantees that the code will compile on implementations other than the
one you use; nor do you have any guarantees that, even on
implementations that do provide such a header, that header has the same
semantics as the header on your implementation.

OK, got this. I recall the issue being discussed here. But note that
you're still not competent enough as a discussant here to give a
straight answer. Why not write "quote malloc(), Mr. Fabulous, since it
might not be available on other implementations, and your code is so
great that all sorts of people would want to use it." And why do I
have to beat answers out of you? Chop chop dickie.

Also, you FAILED to point out a SERIOUS bug, for shame. I did not
free. Schildt says I should and at least he (1) knows what he's
talking about most of the time and (2) is enough of a man to say what
should be done. I suggest you emulate him in future.

Stop grandstanding and get to work.
 
F

Flash Gordon

Richard said:
I'm pretty sure I've explained the above to you in nauseous detail on at
least one previous occasion. Go look it up in the archives.

You have been trolled.

Please try and avoid rising to such obvious bait.
 
S

spinoza1111

spinoza1111wrote:
santosh wrote:

[ ... ]
It looks like something your browser did, perhaps prepending or
suffixing every line with D.

Yes. It's either the browser or Google Groups, probably the latter.

Quite apart from the merits or demerits of GCC, it's useful to compile
a program under more than one compiler. It's one way of eliminating
unnecessary compiler-specific constructs and improving the portability
of the code, to an extent.

I used to compile under MSVC, Borland and GCC, but I've lost access to
a Windows system these days. Been meaning to install another copy, but
haven't got around to doing it yet.

By the way, as I test the code I realize that it doesn't at all
recover from false positives where there's a partial keyword match,
and should probably not allow a null string to be the first argument
of replace since replace("", "snirpKamunkle") is undefined.
 
S

santosh

spinoza1111 wrote:

By the way, as I test the code I realize that it doesn't at all
recover from false positives where there's a partial keyword match,
and should probably not allow a null string to be the first argument
of replace since replace("", "snirpKamunkle") is undefined.

Yes.

I noticed that it fails for many cases of bad input.

replace("a stupid errord", "stupid error", "miracle") gives:

miracled

but,

replace("a stupid errod", "stupid error", "miracle") gives:

d

also:

replace("a sstupid error", "stupid error", "miracle") gives:

miracle

and not

smiracle

as the first case above would lead one to expect. Also:

replace("a stupid errorstupid error", "stupid error", "miracle")
gives:

a miraclemiracle

but

replace("a stupid error stupiderror", "stupid error", "miracle")
gives:

a miracleerror

Not what one might expect.

Anyway, I didn't follow the previous discussions in the thread
closely, but for what it appears to do, your code appears to be an
overkill. What about a solution involving strstr(), malloc()/realloc()
and strcat()?
 
W

Willem

santosh wrote:
) Anyway, I didn't follow the previous discussions in the thread
) closely, but for what it appears to do, your code appears to be an
) overkill. What about a solution involving strstr(), malloc()/realloc()
) and strcat()?

I've never liked strcat(), and I'm not sure about the performance of
realloc(), so this is roughly what I would do:

#include <string.h>

char *replace(char *string, char *replace, char *with)
{
size_t replace_len = strlen(replace);
size_t with_len = strlen(with);
size_t result_len;
char *string_ptr, *search_ptr, *result_ptr;
char *result;

/* Determine result length */
result_len = 0;
string_ptr = string;
while (search_ptr = strstr(string_ptr, replace)) {
result_len += (search_ptr - string_ptr);
result_len += with_len;
string_ptr = search_ptr + replace_len;
}
result_len += strlen(string_ptr) + 1;

if (result = malloc(result_len)) {
/* Do the replacement */
string_ptr = string;
result_ptr = result;
while (search_ptr = strstr(string_ptr, replace)) {
memcpy(result_ptr, string_ptr, search_ptr - string_ptr);
result_ptr += (search_ptr - string_ptr);
memcpy(result_ptr, with, with_len);
result_ptr += with_len;
string_ptr = search_ptr + replace_len;
}
*result_ptr = 0;
}
return result;
}


Of course, this does the loop twice. I have no idea if this would
outperform the realloc() method, basically you either have to do 1
additional strstr() per match, or one additional realloc() per match.

For the realloc() version, you'd obviously have to lose the result_ptr
and work with result+result_len instead.


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
 
R

Richard Tobin

Just asking out of interest, would a post-increment enable any
significant optimisations by the compiler that wouldn't be possible
with a pre-increment?
[/QUOTE]
I doubt it. Many assemblers have an INC instruction, which would
make things probably a little harder for a post-increment.

When ++i or i++ are used as complete statements, as in the for-loop
example, they are exactly equivalent and there is no reason for them
to generate different code on any but the most naive compiler.

And when they aren't equivalent, there's no reason to suppose that the
programmer is going to make a better job of re-arranging the expression
than the compiler.

-- Richard
 
R

Richard Tobin

spinoza1111 said:
Why not write "quote malloc(), Mr. Fabulous, since it
might not be available on other implementations, and your code is so
great that all sorts of people would want to use it."

You have still not grasped the problem. malloc() is perfectly
portable. But it is standardly declared in <stdlb.h>, not <malloc.h>.

-- Richard
 
S

spinoza1111

spinoza1111wrote:

<snip>

Apologies for my previous post. A cut and paste of your code from
Google Groups resulted in numerous strange sequences within your code,
which stymied the compiler obviously. I notice that it's not in your
code, but it does appear in the 'show original' link of your post on
Groups.

After a proper cut and past, I got your program to compile and
seemingly produce the expected output, as you've indicated in main().
Haven't walked through the code though.

A new version with a major bug fix and more tests:

(1) Fixes the major bug that in the case of a partial match we must
iterate the search for a full match

(2) Checks for a null target: this is not permitted

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

struct TYPsegmentstruct
{ char * strSegment;
long lngSegmentLength;
int intReplaceAtEnd;
struct TYPsegmentstruct * ptrNext; };

char * replace(char * strMaster,
char * strTarget,
char * strReplacement)
{
char * ptrIndex0;
char * ptrIndex1;
char * ptrIndex2;
char * ptrIndex3;
char * strNew;
char * strNewStart;
long lngNewLength;
long lngCount;
struct TYPsegmentstruct * ptrSegmentStructStarts;
struct TYPsegmentstruct * ptrSegmentStruct;
struct TYPsegmentstruct * ptrSegmentStructPrev;
if (!*strTarget)
{
printf("Error in calling replace(): target can't be null");
abort();
}
ptrIndex1 = strMaster;
ptrSegmentStructPrev = 0;
lngNewLength = 0;
while(*ptrIndex1)
{
ptrIndex0 = ptrIndex1;
while (-1)
{
for(;
*ptrIndex1 && *ptrIndex1 != *strTarget;
ptrIndex1++);
for(ptrIndex2 = strTarget, ptrIndex3 = ptrIndex1;
*ptrIndex3
&&
*ptrIndex2
&&
*ptrIndex3 == *ptrIndex2;
ptrIndex3++, ptrIndex2++);
if (!*ptrIndex3 || !*ptrIndex2) break;
ptrIndex1 = ptrIndex3;
}
if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->intReplaceAtEnd = *ptrIndex2 ? 0 : -1;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;
lngNewLength += ptrSegmentStruct->lngSegmentLength +
(*ptrIndex3
?
strlen(strReplacement)
:
0);
ptrSegmentStruct->ptrNext = 0;
if (ptrSegmentStructPrev != 0)
ptrSegmentStructPrev->ptrNext = ptrSegmentStruct;
else
ptrSegmentStructStarts = ptrSegmentStruct;
ptrSegmentStructPrev = ptrSegmentStruct;
ptrIndex1 = ptrIndex3;
}
if (!(strNewStart = malloc(lngNewLength + 1))) abort();
strNew = strNewStart;
ptrSegmentStruct = ptrSegmentStructStarts;
while (ptrSegmentStruct)
{
for (ptrIndex1 = ptrSegmentStruct->strSegment, lngCount = 0;
lngCount < ptrSegmentStruct->lngSegmentLength;
ptrIndex1++, lngCount++, strNew++)
*strNew = *ptrIndex1;
if (ptrSegmentStruct->intReplaceAtEnd)
for (ptrIndex1 = strReplacement;
*ptrIndex1;
ptrIndex1++, ++strNew)
*strNew = *ptrIndex1;
ptrSegmentStruct = ptrSegmentStruct->ptrNext;
}
*strNew = '\0';
return strNewStart;
}

int main()
{
printf("\nReplace\n\n\n");
printf("Expect a miracle:\n\"%s\"\n\n",
replace("a stupid error", "stupid error", "miracle"));
printf("Expect a miracle error:\n\"%s\"\n\n",
replace("a stupid error", "stupid", "miracle"));
printf("Expect a miracle:\n\"%s\"\n\n",
replace("the stupid error", "the stupid error", "a
miracle"));
printf("Expect a miracle:\n\"%s\"\n\n",
replace("the miracle", "the", "a"));
printf("Expect a miracle:\n\"%s\"\n\n",
replace("a miraclsnirpKamunkle", "snirpKamunkle", "e"));
printf("Expect snirpKamunkle:\n\"%s\"\n\n",
replace("a miraclesnirpKamunkle", "a miracle", ""));
printf("Expect snirpKamunkle (preceded by a space):\n\"%s\"\n\n",
replace(" a miraclesnirpKamunkle", "a miracle", ""));
printf("Expect snirpKamunkle (preceded by a space):\n\"%s\"\n\n",
replace(" a miraclesnirpKamunklea miraclea miracle", "a
miracle", ""));
printf("Expect snirpKamunkle a Miracle (preceded by a space):\n\"%s
\"\n\n",
replace("a miracle a miraclesnirpKamunkle a Miraclea
miraclea miracle", "a miracle", ""));
return 0;
}
 
S

spinoza1111

spinoza1111wrote:



Yes.

I noticed that it fails for many cases of bad input.

Doesn't look bad to me below, will try out the new cases on my lastest
vrsion
replace("a stupid errord", "stupid error", "miracle") gives:

miracled

This is correct, as you understand.
but,

replace("a stupid errod", "stupid error", "miracle") gives:

d

This was the "failure to handle false positives" bug which has been
fixed in the latest version (the one with the while(-1) loop. This now
gives "a stupid errod"
also:

replace("a sstupid error", "stupid error", "miracle") gives:

miracle

and not

smiracle

This also was fixed by the fix to "failure to handle false positives".
as the first case above would lead one to expect. Also:

replace("a stupid errorstupid error", "stupid error", "miracle")
gives:

a miraclemiracle

That is what we get.
but

replace("a stupid error stupiderror", "stupid error", "miracle")
gives:

a miracleerror

Not what one might expect.

Again, fixed. The false positive handling was incorrect.
Anyway, I didn't follow the previous discussions in the thread
closely, but for what it appears to do, your code appears to be an
overkill. What about a solution involving strstr(), malloc()/realloc()
and strcat()?

Try the new version and I will try all your tests.

A solution could of course use the string library more intensively.
However, the basic approach is proven. Don't, as Seebach did, redefine
a string problem as a character problem.

Thank you for a most enjoyable work session. Here is the latest code
(a copy is elsethread) with more consistent quoting of expected
results, and all the test cases that you have proposed.

#include <stdio.h>
#include "malloc.h" // per Richard Heathfield we must quote this so I
did
#include <stdlib.h>
#include <string.h>

struct TYPsegmentstruct
{ char * strSegment;
long lngSegmentLength;
int intReplaceAtEnd;
struct TYPsegmentstruct * ptrNext; };

char * replace(char * strMaster,
char * strTarget,
char * strReplacement)
{
char * ptrIndex0;
char * ptrIndex1;
char * ptrIndex2;
char * ptrIndex3;
char * strNew;
char * strNewStart;
long lngNewLength;
long lngCount;
struct TYPsegmentstruct * ptrSegmentStructStarts;
struct TYPsegmentstruct * ptrSegmentStruct;
struct TYPsegmentstruct * ptrSegmentStructPrev;
if (!*strTarget)
{
printf("Error in calling replace(): target can't be null");
abort();
}
ptrIndex1 = strMaster;
ptrSegmentStructPrev = 0;
lngNewLength = 0;
while(*ptrIndex1)
{
ptrIndex0 = ptrIndex1;
while (-1)
{
for(;
*ptrIndex1 && *ptrIndex1 != *strTarget;
ptrIndex1++);
for(ptrIndex2 = strTarget, ptrIndex3 = ptrIndex1;
*ptrIndex3
&&
*ptrIndex2
&&
*ptrIndex3 == *ptrIndex2;
ptrIndex3++, ptrIndex2++);
if (!*ptrIndex3 || !*ptrIndex2) break;
ptrIndex1 = ptrIndex3;
}
if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->intReplaceAtEnd = *ptrIndex2 ? 0 : -1;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;
lngNewLength += ptrSegmentStruct->lngSegmentLength +
(*ptrIndex3
?
strlen(strReplacement)
:
0);
ptrSegmentStruct->ptrNext = 0;
if (ptrSegmentStructPrev != 0)
ptrSegmentStructPrev->ptrNext = ptrSegmentStruct;
else
ptrSegmentStructStarts = ptrSegmentStruct;
ptrSegmentStructPrev = ptrSegmentStruct;
ptrIndex1 = ptrIndex3;
}
if (!(strNewStart = malloc(lngNewLength + 1))) abort();
strNew = strNewStart;
ptrSegmentStruct = ptrSegmentStructStarts;
while (ptrSegmentStruct)
{
for (ptrIndex1 = ptrSegmentStruct->strSegment, lngCount = 0;
lngCount < ptrSegmentStruct->lngSegmentLength;
ptrIndex1++, lngCount++, strNew++)
*strNew = *ptrIndex1;
if (ptrSegmentStruct->intReplaceAtEnd)
for (ptrIndex1 = strReplacement;
*ptrIndex1;
ptrIndex1++, ++strNew)
*strNew = *ptrIndex1;
ptrSegmentStruct = ptrSegmentStruct->ptrNext;
}
*strNew = '\0';
return strNewStart;
}

int main()
{
printf("\nReplace\n\n\n");
printf("Expect \"a miracle\":\n\"%s\"\n\n",
replace("a stupid error", "stupid error", "miracle"));
printf("Expect \"a miracle error\":\n\"%s\"\n\n",
replace("a stupid error", "stupid", "miracle"));
printf("Expect \"a miracle\":\n\"%s\"\n\n",
replace("the stupid error", "the stupid error", "a
miracle"));
printf("Expect \"a miracle\":\n\"%s\"\n\n",
replace("the miracle", "the", "a"));
printf("Expect \"a miracle\":\n\"%s\"\n\n",
replace("a miraclsnirpKamunkle", "snirpKamunkle", "e"));
printf("Expect \"snirpKamunkle\":\n\"%s\"\n\n",
replace("a miraclesnirpKamunkle", "a miracle", ""));
printf("Expect \" snirpKamunkle\":\n\"%s\"\n\n",
replace(" a miraclesnirpKamunkle", "a miracle", ""));
printf("Expect \" snirpKamunkle\":\n\"%s\"\n\n",
replace(" a miraclesnirpKamunklea miraclea miracle", "a
miracle", ""));
printf("Expect \" snirpKamunkle a Miracle\":\n\"%s\"\n\n",
replace("a miracle a miraclesnirpKamunkle a Miraclea
miraclea miracle", "a miracle", ""));
printf("Expect \"a miracled\"):\n\"%s\"\n\n",
replace("a stupid errord", "stupid error", "miracle") );
printf("Expect \"a stupid errod\"):\n\"%s\"\n\n",
replace("a stupid errod", "stupid error", "miracle") );
printf("Expect \"a smiracle\"):\n\"%s\"\n\n",
replace("a sstupid error", "stupid error", "miracle") );
printf("Expect \"a miraclemiracle\"):\n\"%s\"\n\n",
replace("a stupid errorstupid error", "stupid error",
"miracle") );
printf("Expect \"a miracle stupiderror\"):\n\"%s\"\n\n",
replace("a stupid error stupiderror", "stupid error",
"miracle") );
printf("\n\nTesting complete: check output carefully!\n\n");
return 0;
}
 
S

spinoza1111

santosh wrote:

) Anyway, I didn't follow the previous discussions in the thread
) closely, but for what it appears to do, your code appears to be an
) overkill. What about a solution involving strstr(), malloc()/realloc()
) and strcat()?

I've never liked strcat(), and I'm not sure about the performance of
realloc(), so this is roughly what I would do:

 #include <string.h>

 char *replace(char *string, char *replace, char *with)
 {
   size_t replace_len = strlen(replace);
   size_t with_len = strlen(with);
   size_t result_len;
   char *string_ptr, *search_ptr, *result_ptr;
   char *result;

   /* Determine result length */
   result_len = 0;
   string_ptr = string;
   while (search_ptr = strstr(string_ptr, replace)) {
     result_len += (search_ptr - string_ptr);
     result_len += with_len;
     string_ptr = search_ptr + replace_len;
   }
   result_len += strlen(string_ptr) + 1;

   if (result = malloc(result_len)) {
     /* Do the replacement */
     string_ptr = string;
     result_ptr = result;
     while (search_ptr = strstr(string_ptr, replace)) {
       memcpy(result_ptr, string_ptr, search_ptr - string_ptr);
       result_ptr += (search_ptr - string_ptr);
       memcpy(result_ptr, with, with_len);
       result_ptr += with_len;
       string_ptr = search_ptr + replace_len;
     }
     *result_ptr = 0;
   }
   return result;
 }

Of course, this does the loop twice.  I have no idea if this would
outperform the realloc() method, basically you either have to do 1
additional strstr() per match, or one additional realloc() per match.

For the realloc() version, you'd obviously have to lose the result_ptr
and work with result+result_len instead.

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

I like to minimize all use of the string library. I do use it but only
at one place: to obtain strlen(strReplacement). This can and shall be
easily precalculated at the beginning of the code.

The purpose is to escape string.h, since its use blinds the soul. The
C programmer who expects all strings to have a nice \0 at the end is
mentally crippled ontologically, for he won't see, as in the case of
Seebach's code, a string inside a string, and will create character-
based solutions.

So overkill? You ain't seen nothing yet. The point is an "immanent"
criticism of C, tunneling from within, to use C to create something
quite unlike C.
 
B

Ben Bacarisse

Willem said:
santosh wrote:
) Anyway, I didn't follow the previous discussions in the thread
) closely, but for what it appears to do, your code appears to be an
) overkill. What about a solution involving strstr(), malloc()/realloc()
) and strcat()?

I've never liked strcat(), and I'm not sure about the performance of
realloc(), so this is roughly what I would do:
<snip code>

Snap! Here is what I'd do. I think it is structurally the same:

char *replace(const char *src, const char *match, const char *replacement)
{
size_t mlen = strlen(match), matches = 0;
for (const char *t, *s = src; t = strstr(s, match); s = t + mlen)
++matches;
size_t rlen = strlen(replacement);
char *result = malloc(strlen(src) + matches*rlen - matches*mlen + 1);
if (result) {
char *dst = result;
const char *s = src;
for (const char *t; t = strstr(s, match); s = t + mlen) {
memcpy(dst, s, t - s);
memcpy(dst += t - s, replacement, rlen);
dst += rlen;
}
strcpy(dst, s);
}
return result;
}
Of course, this does the loop twice. I have no idea if this would
outperform the realloc() method, basically you either have to do 1
additional strstr() per match, or one additional realloc() per
match.

There is another strategy that would involve guessing the likely
number of matches combined with increasing the size by some multiple
that would avoid a lot of reallocs. The cost would be wasted space
and/or fragmentation.
For the realloc() version, you'd obviously have to lose the result_ptr
and work with result+result_len instead.

I can't image that the repeated strstr calls would, in typical
situations, be a significant cost (though one could construct examples
that would favour avoiding them). In any case, it is clearly wise to
get something working so that benefit (in terms of speed) of working
on the code can be assessed.

<snip>
 
I

Ike Naar

A new version with a major bug fix and more tests:

In the old version, replace("banana","ana","oat") gives "boat".
In the new version it gives "boatn".

Both outputs are not what one would expect.
 
J

James

Ben Bacarisse said:
<snip code>

Snap! Here is what I'd do. I think it is structurally the same:

char *replace(const char *src, const char *match, const char
*replacement)
{
size_t mlen = strlen(match), matches = 0;
for (const char *t, *s = src; t = strstr(s, match); s = t + mlen)
++matches;
size_t rlen = strlen(replacement);


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


/* allocate space for new string. */
char* dest_string = malloc(new_size + 1);

if (dest_string)
{
/* mutate and display the string. */
puts(replace(src_string, dest_string, "A", "XXXX"));


/* free it. */
free(dest_string);
}




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.
 
N

Nick Keighley

Just asking out of interest, would a post-increment enable any
significant optimisations by the compiler that wouldn't be possible
with a pre-increment?

I believe the C++ people might give you a slightly different answer.
For classes a preincrement might be a bit more effecient than a
postincrement. For builtins like int it makes no difference. For more
(and more correct) info ask on comp.lang.c++.
That's about the only reason I can think of for using a post-
increment, other than that it's more idiomatic, in such typical loops.

post inc seems to be the more idiomatic
 
S

spinoza1111

On Feb 7, 6:02 pm, santosh <[email protected]> wrote:

Hopefully a final version, with free storage calls for both the
replaced strings and the linked list created inside replace(). I found
a major memory leak in the previous version owing to the use of an
incorrect index in a test, and this has been fixed. The leak didn't
occur in debug mode until I added code to free strings returned by
replace(), and I'd propose some sort of macro interface to malloc()
and free() is needed in test. It's nuts in Microsoft C++/C that debug
mode would conceal leakages.

The code is followed by the expected output.



// ***************************************************************
// * *
// * replace() demo *
// * *
// * Demonstrates how to replace non-NUL-defined strings in C *
// * using a simple function, and bypassing string.h. *
// * *
// * C H A N G E R E C O R D --------------------------------- *
// * DATE PROGRAMMER DESCRIPTION OF CHANGE *
// * -------- ---------- --------------------------------- *
// * 02 07 10 Nilges Version 1.0 *
// * *
// * 02 07 10 Nilges Bug: partial matches not handled *
// * correctly: need to iterate search *
// * for match. *
// * *
// * 02 07 10 Nilges 1. Santosh suggested tests *
// * 2. Heathfield put the boot in re *
// * including malloc *
// * *
// * 02 07 10 Nilges 1. Remove string.h use and code *
// * strlen by hand *
// * 2. Add comment block and comments*
// * inline. *
// * 3. free() storage *
// * 4. Use macro for testing *
// * 5. Bug: calculation of *
// * lngNewLength used incorrect *
// * index (intIndex3 instead of 2)*
// * which caused a memory leak. *
// * *
// * ----------------------------------------------------------- *
// * *
// * "In the near future we shall have to live with the *
// * superstition that programming is 'so easy that even a *
// * Republican can do it!'" *
// * *
// * - E. W. Dijkstra *
// * *
// * *
// ***************************************************************

#include <stdio.h>
#include "malloc.h" // Per RH ess muss sein
#include <stdlib.h>

// ***** Segmentation *****
struct TYPsegmentstruct
{ char * strSegment;
long lngSegmentLength;
int intReplaceAtEnd;
struct TYPsegmentstruct * ptrNext; };

// ---------------------------------------------------------------
// Calculate string length
//
//
long strLen(char *strInstring)
{
char *ptrInstring;
for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
return ptrInstring - strInstring;
}

// ---------------------------------------------------------------
// Replace target by replacement string in master string
//
//
// Caution: the string returned by this function should be freed.
//
//
char * replace(char * strMaster,
char * strTarget,
char * strReplacement)
{
char * ptrIndex0;
char * ptrIndex1;
char * ptrIndex2;
char * ptrIndex3;
char * strNew;
char * strNewStart;
long lngNewLength;
long lngCount;
long lngReplacementLength;
struct TYPsegmentstruct * ptrSegmentStructStarts;
struct TYPsegmentstruct * ptrSegmentStruct;
struct TYPsegmentstruct * ptrSegmentStructPrev;
lngReplacementLength = strlen(strReplacement);
if (!*strTarget)
{
printf("Error in calling replace(): target can't be null");
abort();
}
ptrIndex1 = strMaster;
ptrSegmentStructPrev = 0;
lngNewLength = 0;
while(*ptrIndex1)
{
ptrIndex0 = ptrIndex1;
while (-1)
{
for(;
*ptrIndex1 && *ptrIndex1 != *strTarget;
ptrIndex1++);
for(ptrIndex2 = strTarget, ptrIndex3 = ptrIndex1;
*ptrIndex3
&&
*ptrIndex2
&&
*ptrIndex3 == *ptrIndex2;
ptrIndex3++, ptrIndex2++);
if (!*ptrIndex3 || !*ptrIndex2) break;
ptrIndex1 = ptrIndex3;
}
if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->intReplaceAtEnd = *ptrIndex2 ? 0 : -1;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;
lngNewLength += ptrSegmentStruct->lngSegmentLength +
(!*ptrIndex2
?
lngReplacementLength
:
0);
ptrSegmentStruct->ptrNext = 0;
if (ptrSegmentStructPrev != 0)
ptrSegmentStructPrev->ptrNext = ptrSegmentStruct;
else
ptrSegmentStructStarts = ptrSegmentStruct;
ptrSegmentStructPrev = ptrSegmentStruct;
ptrIndex1 = ptrIndex3;
}
if (!(strNewStart = malloc(lngNewLength + 1))) abort();
strNew = strNewStart;
ptrSegmentStruct = ptrSegmentStructStarts;
while (ptrSegmentStruct)
{
for (ptrIndex1 = ptrSegmentStruct->strSegment, lngCount = 0;
lngCount < ptrSegmentStruct->lngSegmentLength;
ptrIndex1++, lngCount++, strNew++)
*strNew = *ptrIndex1;
if (ptrSegmentStruct->intReplaceAtEnd)
for (ptrIndex1 = strReplacement;
*ptrIndex1;
ptrIndex1++, ++strNew)
*strNew = *ptrIndex1;
ptrSegmentStructPrev = ptrSegmentStruct;
ptrSegmentStruct = ptrSegmentStruct->ptrNext;
free(ptrSegmentStructPrev);
}
*strNew = '\0';
return strNewStart;
}

// ---------------------------------------------------------------
// Statement-format test macro
//
//
#define TESTER(resultPtr, master, target, replacement, expected) \
{ \
printf("Expect \"%s\":\n\"%s\"\n\n", \
(expected), \
resultPtr = replace((master), \
(target), \
(replacement))); \
free(resultPtr); \
}

// ---------------------------------------------------------------
// Main procedure
//
//
int main()
{
char *ptrResult;
printf("\nReplace\n\n\n");
TESTER(ptrResult,
"a stupid error",
"stupid error",
"miracle",
"a miracle")
TESTER(ptrResult,
"a stupid error",
"stupid",
"miracle",
"a miracle error")
TESTER(ptrResult,
"the stupid error",
"the stupid error",
"a miracle",
"a miracle")
TESTER(ptrResult,
"the miracle",
"the",
"a",
"a miracle")
TESTER(ptrResult,
"a miraclsnirpKamunkle",
"snirpKamunkle",
"e",
"a miracle")
TESTER(ptrResult,
"a miraclesnirpKamunkle",
"a miracle",
"",
"snirpKamunkle")
TESTER(ptrResult,
" a miraclesnirpKamunkle",
"a miracle",
"",
" snirpKamunkle")
TESTER(ptrResult,
" a miraclesnirpKamunklea miraclea miracle",
"a miracle",
"",
" snirpKamunkle")
TESTER(ptrResult,
"a miracle a miraclesnirpKamunkle a Miraclea miraclea
miracle",
"a miracle",
"",
" snirpKamunkle a Miracle")
TESTER(ptrResult,
"a stupid errord",
"stupid error",
"miracle",
"a miracled")
TESTER(ptrResult,
"a stupid errod",
"stupid error",
"miracle",
"a stupid errod")
TESTER(ptrResult,
"a sstupid error",
"stupid error",
"miracle",
"a smiracle")
TESTER(ptrResult,
"a stupid errorstupid error",
"stupid error",
"miracle",
"a miraclemiracle")
TESTER(ptrResult,
"a stupid error stupiderror",
"stupid error",
"miracle",
"a miracle stupiderror")
TESTER(ptrResult,
"bbbbbbbbbb",
"b",
"a",
"aaaaaaaaaa")
TESTER(ptrResult,
"In the halls of R'yleh great %s lies dreaming",
"%s",
"Cthulu",
"In the halls of R'yleh great Cthulu lies dreaming")
TESTER(ptrResult,
"%s%s%s%s%s%s",
"%s",
"Cthulu",
"CthuluCthuluCthuluCthuluCthuluCthulu")
printf("\n\nTesting complete: check output carefully!\n\n");
return 0;
}



Replace


Expect "a miracle":
"a miracle"

Expect "a miracle error":
"a miracle error"

Expect "a miracle":
"a miracle"

Expect "a miracle":
"a miracle"

Expect "a miracle":
"a miracle"

Expect "snirpKamunkle":
"snirpKamunkle"

Expect " snirpKamunkle":
" snirpKamunkle"

Expect " snirpKamunkle":
" snirpKamunkle"

Expect " snirpKamunkle a Miracle":
" snirpKamunkle a Miracle"

Expect "a miracled":
"a miracled"

Expect "a stupid errod":
"a stupid errod"

Expect "a smiracle":
"a smiracle"

Expect "a miraclemiracle":
"a miraclemiracle"

Expect "a miracle stupiderror":
"a miracle stupiderror"

Expect "aaaaaaaaaa":
"aaaaaaaaaa"

Expect "In the halls of R'yleh great Cthulu lies dreaming":
"In the halls of R'yleh great Cthulu lies dreaming"

Expect "CthuluCthuluCthuluCthuluCthuluCthulu":
"CthuluCthuluCthuluCthuluCthuluCthulu"



Testing complete: check output carefully!
 
S

spinoza1111

spinoza1111wrote:


Good. Now please *learn*, so that we don't have to tell you yet again.

I'm coding, writing and thinking rings around you. You focus on
trivialities because you're an incompetent programmer. Do not EVER
presume to be my teacher. You're a gangster and a thug, and useful at
best for trivialities. You're going to end up in a court of law.
Because it's stupid to say that, that's why. The malloc function is
available in all hosted implementations, and "quoting" it is in any case
meaningless.



If I took the time to point out all your serious bugs, I wouldn't have
time to do anything else.

Fool. Get the **** out of this newsgroup.
 

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,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top