Warning to newbies

S

spinoza1111

Ben said:
santosh wrote:
Joe Wright wrote:
spinoza1111wrote:
[ 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 whatspinoza1111set 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?

I must be missing something.spinoza1111came up with almost 100 lines of
code to solve what I consider to be a simple problem solvable in 10 lines
or so. Maybe I didn't appreciate how hard a real programmer would work on
this sort of thing. Finding a substring and replacing it with another is
almost trivial.

While my refusal to use the string library contributed to the line
count, as did the documentation, I think the problem is in
subprofessional programmers like Seebach presenting "simple" code with
bugs that they refuse to fix, and which when one tries to fix them,
one finds that the whole architecture of the solution is flawed.

Also, no problem is "trivial" except to the trivial.

"Hey, Harv, are you into TRIVIA?" "I'm talking to you, ain't I?" -
Harvey Pekar, AMERICAN SPLENDOR

"In the near future we shall have to live with the superstition that
programming is 'so easy that even a Republican can do it!'"

Edsger Dijsktra
 
S

spinoza1111

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",

This is a lie. I never was in this discussion.

I'm going to write your employers and our publisher about your
behavior in this newsgroup on advice of counsel.
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.

How would you know? You majored in psychology. And your solution
didn't work. I'm not going to examine your new solution, but it's
probably full of bugs. Like the typical office asshole who ruined the
structured walkthrough, you use others' openness about bugs against
them.
 
S

spinoza1111

My code for this was written in about five minutes, I have not yet found a bug
in it (although it does have the documented limitation that, as of this
writing, it simply assumes that "%" will be the first character of "%s";
since it only has to run on two strings, and they're in the same module,
I was okay with that), and ran correctly on the first try.  (It would have
been the second try, except that I'd just done something sort of similar
half an hour earlier and made a fencepost error there, which kept the question
clearly in mind.)

I did analyze the problem carefully, and I concluded that it was simple enough
and easy enough to get right in this particular case that it would be better
to write a fairly simple loop which the reader could verify by inspection
than to try to solve the general problem.

* Your code didn't work and you didn't show how to fix it.

* You confused reports of bugs in the process of being fixed with
"thousands of bugs", and your interpretation of yesterday's
professional discussion amongst Naar, Santosh and myself concerning
bugs and their fixing makes it clear that you are unqualified and
disruptive. Terrified of your own impotence and weakness, you lash out
at others.

* You woke up, saw the discussion, and madly coded a new solution
which uses the string library. I won't waste my time on this
"solution".

* Code monkeys with psychology degrees who back-stabbed and lied their
way onto a job are terrified of "the inner contour of their
weakness".
 
S

spinoza1111

spinoza1111wrote:
On Feb 7, 7:50 pm,spinoza1111<[email protected]> wrote:

[ all snipped ]
I suggest you spend overlong on a relatively simple task. Regard..

The problem is of course that ignorant managers have only one way of
measuring programmers: this is to measure time taken to come up with a
solution that only seems to work. You can't even write a grammatical
sentence, and your solution is a joke (see below). But in many little
shops, you'll go far.
/*
    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 solution doesn't even work for length > 256. I suggest you're the
fraud.
 
S

spinoza1111

What Richard is getting at is that you shouldn't be including
malloc.h at all.  Instead you should be including stdlib.h.

Malloc is defined in stdlib.h.

Malloc.h is not a standard C system include file.  It is
definitely archaic and non-standard.  The fact that your code
compiles on your system is peculiar to your system.

I've taken it out, but I'd suggest that having to remember the
consequences of sloppy design is a task for apes and not men. Just my
opinion.
 
S

Seebs

I must be missing something. spinoza1111 came up with almost 100 lines of
code to solve what I consider to be a simple problem solvable in 10 lines
or so.

A classic example of massively overthinking a problem.

One of the most useful skills in programming is learning when you don't need
to build an entire infrastructure layer to support a straightforward
operation.

I just hope he never realizes that his implementation of a string length
counter is not particularly overth^H^H^H^H^Hrobustly engineered. If he does,
we'll get something like this:

#include <sys\types.h>
#include "curses.h"
#include <iso646.H>
#include <emmintrin.h>

/* C does not provide a value which is distinct from all possible
* char values, because the idiots who wrote the standard didn't
* realize that the "char" type which they stupidly left undefined
* could hold the value -1.
*/
#define EndOfFileValue -3

int isPointerNull(void *p) {
if ((void *) p == (void *) 0) {
return ~0;
} else {
return 0;
}
/* because the standard was written by autistic twerps who have
* never studied computer science, it is crucially important that
* there be an explicit return statement at the end of every
* function.
*/
return 0;
}

int characterAtPointer(const char *pointerToCharacter) {
if (isPointerNull((void *)pointerToCharacter) == ~0) {
return EndOfFileValue;
} else {
return pointerToCharacter[(int) 0];
}
return EndOfFileValue;
}

int lengthOfString(const char *stringToMeasure) {
int nextCharacter;
int nextCharacterIsEndOfFileValue;
const char *nextCharacterPointer;
int charactersSoFar;
if (isPointerNull((void *)stringToMeasure)) {
return ~0;
} else {
/* important not to modify the caller's string, which is on
* the STACK STACK STACK STACK STACK STACK STACK STACK you
* transvestite nazi motherfuckers
*/
nextCharacterPointer = stringToMeasure;
charactersSoFar = 0;
nextCharacterIsEndOfFileValue = 0;
/* the following monstrosity is necessary because C is
* intrinsically unsafe, providing no type-safe way to
* extract a value from a pointer without first verifying
* that the pointer is valid, as I proved in the 1980s.
*/
while(characterAtPointer((const char *)nextCharacterPointer) != '\0' && nextCharacterIsEndOfFileValue != ~0) {
if (characterAtPointer((const char *)nextCharacterPointer) == EndOfFileValue) {
nextCharacterIsEndOfFileValue = ~0;
}
if (nextCharacterIsEndOfFileValue != ~0) {
nextCharacter = characterAtPointer((const char *)nextCharacterPointer);
if (nextCharacter == '\0') {
/* when I was working with Ogden Nash,
* he told me to always phrase my tests in
* a positive way
*/
} else {
charactersSoFar = charactersSoFar + (int) 1;
}
}
nextCharacterPointer = (const char *) &nextCharacterPointer[1];
}
}
return (int) charactersSoFar;
}

-s
p.s.: Needless to say, I have not tried to compile the above fragment.
However, I consider it fairly representative.
 
S

Seebs

It may be a lie, or it may not be. But Seebs didn't claim that you were
in that discussion. He claimed that that discussion has a participant
who reminds him of you. Please learn to read.

Yes. "I bring it up because it has a participant *who reminds me a
great deal of Nilges*". Emphasis mine.
Now that sounds much, much more like a lie. But feel free to prove me
wrong. His employers sound like a reasonable bunch; if they take you
seriously (for example, if they've never heard from you before), then
they may investigate your claim, at which point they may be in danger of
dying from sheer laughter. Same applies to the publisher. And a court
would eat you for breakfast.

All I have to say is:

Please cc my attorney on all attempts at libel and/or slander. He could
use the laugh.

BTW, at least one of my coworkers is familiar with Nilges in particular,
and people up to the VP level are aware of my amazing talent for acquiring
angry kooks. I am, shall we say, not especially worried.

-s
 
S

Seebs

Sorry, but "all" is out of the question. There are too many, and I don't
have the time. But I could probably manage a representative sample.

Sorry, I was not adequately clear. I meant specifically that if Nilges wished
to make assertions intended to cause people to perceive me as being
unqualified to hold my job, for instance, he should cc my attorney, who could
use the laugh.

I don't think random insults posted to usenet rise to the level of "attempts
at libel and/or slander", except in the way that flailing your arms generally
in someone's direction rises to the level of attempted murder. Basically, if
it's not a *credible* attempt, it doesn't count.

-s
 
S

Seebs

No, I fixed that. Here is a version just for you, with this test
added.

I normally ignore your stuff, but since this is actual code, I figure it
deserves a bit of a look.

Your various statements about the original example are deeply confused.
There was no "spec" that I short-circuited; I wrote the data and the
code to fit each other. In any event, your code is fascinating.
// * Demonstrates how to replace non-NUL-defined strings in C *
// * using a simple function, and bypassing string.h. *

Congratulations! You're barely into the comments and you've already
made your first obvious mistake. "NUL-defined" isn't even meaningful,
but "NUL-terminated" is... And all three of the arguments to your function
are, in fact, NUL-terminated. You seem to be making much of the lack
of a NUL byte at the end of the substrings, but really, that's not
particularly unusual; strstr() has always handled that just fine.
#include <stdio.h>
#include "malloc.h" // Per RH ess muss sein

No, RH pointed out that "malloc.h" did not need to be included at all,
since it's not a standard header and malloc is adequately declared in
#include <stdlib.h>

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

This is an exceptionally elaborate structure definition. I am also
hugely amused by your decision to make your systems hungarian even LESS
usable out of spite.
// ---------------------------------------------------------------
// Calculate string length
//
//
long strLen(char *strInstring)
{
char *ptrInstring;
for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
return ptrInstring - strInstring;
}

While this does indeed appear to work, it's shoddy.

First, you should have written the loop as:

for (ptrInstring = strInstring; *ptrInstring; ptrInstring++)
;

Accidentally putting a semicolon on the end of a for loop is a common
typo. The reader is better served by an explicit "loop body" even if
it's just a semicolon.
// ---------------------------------------------------------------
// 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)
{

So far, this looks fine.
char * ptrIndex0;
char * ptrIndex1;
char * ptrIndex2;
char * ptrIndex3;

This, by contrast, is just plain stupid. How is the reader supposed to know
what these are used for? This is like a parody of variable naming
conventions. You're so busy telling us that these are "pointer indexes" that
you forget to suggest or even hint at what they'll be used for. It's like
reading a large chunk of numerical processing in which the variables are
all named "mathematicalValue0", "mathematicalValue1", and so on.
char * strNew;
char * strNewStart;
long lngNewLength;
long lngCount;
long lngReplacementLength;
struct TYPsegmentstruct * ptrSegmentStructStarts;
struct TYPsegmentstruct * ptrSegmentStruct;
struct TYPsegmentstruct * ptrSegmentStructPrev;
lngReplacementLength = strlen(strReplacement);

It seems suspiciously likely that you have more variables here than you
actually need to implement this, but of course, it's hard to guess what you
might have been thinking. The TYPsegmentstruct thing seems to be an
exceptionally poor design choice already, though.
if (!*strTarget)
{
printf("Error in calling replace(): target can't be null");
abort();
}

Error handling with a gun.
ptrIndex1 = strMaster;

So. You start with ptrIndex1. You haven't used ptrIndex0 yet. Also,
there is no future reference to strMaster in the code, suggesting that you
don't need the old value for anything -- so storing a copy of it seems
unnecessary. Just use strMaster.
ptrSegmentStructPrev = 0;
lngNewLength = 0;

It's not unheard of to put stuff like this in the variable declaration,
since that's usually easier to keep straight.
while(*ptrIndex1)
{
ptrIndex0 = ptrIndex1;
while (-1)

So you're telling us here that anything I say, no matter how universally
acknowledged it is, you're going to do the other way just out of spite. Okay.

Furthermore, why not actually specify the loop condition as the loop
condition? Oh, that's right. Because you're crazy.
{
for(;
*ptrIndex1 && *ptrIndex1 != *strTarget;
ptrIndex1++);
for(ptrIndex2 = strTarget, ptrIndex3 = ptrIndex1;
*ptrIndex3
&&
*ptrIndex2
&&
*ptrIndex3 == *ptrIndex2;
ptrIndex3++, ptrIndex2++);
if (!*ptrIndex2) break;
ptrIndex1 = ptrIndex3;
if (!*ptrIndex3) break;
}

Here's where you would have benefitted a lot from giving these variables
semantically indicative names.

To summarize this loop, for anyone following along at home and unable to make
sense of this godawful spaghetti code:

until something breaks us out of this loop
advance to the first instance of the first character
in the string to be replaced

point index2 at the string to be replaced, and index3
at the character which was the same as it

iterate as long as both of them are non-NUL and the same.

break if *index2 is NUL (this would mean that we matched
the entire string to be replaced)

point index1 (our location in the master string) at index3
otherwise.

if *index3 is NUL, break there too.

This is massively complicated by a refusal to use the provided tools, but
that alone isn't enough to cover it. This is a gratuitously complicated
and spaghetti-code way of going about doing this.

But whatever. We have gotten out of the loop. If *ptrIndex2 is a nul byte,
we found a thing to replace. Otherwise, we reached the end of the original
string. In either case, ptrIndex1 now points to either just past the thing
to replace, or to the end of the original string.

if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();

Wonderful error handling.
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->intReplaceAtEnd = *ptrIndex2 ? 0 : -1;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;

So, Segment is pointed to the point in the original string where
we started this block. ReplaceAtEnd is set to 0 or nilgesTrue to indicate
whether or not to include the replacement string. The segment length
is the difference between where we are now in the original string
and where we were.
lngNewLength += ptrSegmentStruct->lngSegmentLength +
(!*ptrIndex2
?
lngReplacementLength
:
0);

This really shows a great openness to bugs. An ordinary developer would
have started NewLength as the length of the original string, then maybe
added the difference between the replacement and target lengths every time
a target string was found. But not you! You carefully add the length
of the original string by bits and pieces.

Special credit for the gratuitously elaborate calculation based on *ptrIndex2.
You already determined whether to ReplaceAtEnd; you could have used that
value, rather than recalculating it. But that's okay, because you've inverted
the sense of the comparison; while previously, you had:
*ptrIndex2 ? <no> : <yes>
here you have
!*ptrIndex2 ? <yes> : <no>

That's a great way to keep readers on their toes!

Remember, *any sort of consistency at all* is the hobgoblin of little
minds. Ralph Waldo Emerson said that when I was helping him write poetry
in C.
ptrSegmentStruct->ptrNext = 0;
if (ptrSegmentStructPrev != 0)
ptrSegmentStructPrev->ptrNext = ptrSegmentStruct;
else
ptrSegmentStructStarts = ptrSegmentStruct;
ptrSegmentStructPrev = ptrSegmentStruct;

This is a technically correct way to handle a linked list, but it does
highlight the inappropriateness of the data structure. This is a gratuitously
complicated series of operations.
ptrIndex1 = ptrIndex3;
}

This is nicely opaque, because you chose completely meaningless names, but
it turns out that:
* if ptrIndex1 had reached the end of the original string, ptrIndex3
was set equal to it and then that loop exited before incrementing
anything, so ptrIndex3 is already the same as ptrIndex1.
* if ptrIndex1 was not at the end of the original string, and we
started the inner loop to see whether we'd found a complete match
for the target string...
* if the match was found, ptrIndex3 points to the end of the match.
* if the match was not found, the loop up at the top kept going.

So either ptrIndex1 already pointed at the end of the original string, and
this is a no-op, or ptrIndex3 pointed to just past the end of an instance
of the target string, and this does indeed move ptrIndex1 to the right
place.

Had you chosen clearer names and not written spaghetti code, this wouldn't
take explanation.
if (!(strNewStart = malloc(lngNewLength + 1))) abort();

Wonderful error handling.
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);
}

This is an extremely elaborate way to keep track of everything. It's
conceptually interesting. Rather than tracking the offsets in the
original string at which the target string occurred (which is the only
information you need to do this; the other information can be derived
from that trivially), you store a series of pointers, lengths, and
additional flags. This allows you to make a much more elaborate loop
here.
*strNew = '\0';
return strNewStart;
}

This part is, surprisingly, probably correct.

The test harness isn't interesting.

Overall... This is crap. It's massively overengineered, in a way that
carefully creates multiple brand new opportunities for brittleness. Your
inexplicable refusal to use any of the standard tools (such as strlen
or memcpy) hardly goes far enough to explain this.

If you really wanted a linked list structure, you could have done just fine
with:

struct replace_at { int offset; struct replace_at *next; };

If you know the offset, you can start at position zero, and:
* copy everything up to the first offset
* add the replacement string
* skip the target (whose length you already know)
* repeat
* copy whatever's left when you're done

It's a simpler loop which only requires a single data point rather than
three. Since the only way ReplaceAtEnd can be zero is when you've reached
the end of the string, it's obvious that you can use the next pointer as
a surrogate for it in this context.

So, long story short:
* Long
* Invites bugs
* Incredibly poor choice of names (and I'm ignoring your faux "Hungarian")
* Insanely inefficient
* Demonstrably very buggy, given how many iterations you've had.

So far, I'm only aware of one bug in the version I did in ten minutes; you
put hours into this, and more time into debugging it, and while I *think* it
probably works, I sure wouldn't want to bet on it. Were this an actual code
review, this would get a "NAK, please clean up and resubmit".

-s
 
N

Nick Keighley

On Feb 7, 8:43 pm, Richard Heathfield <[email protected]> wrote:
Although I initially accepted your [Richard Heathfield's] foolish
ideas about quoting rather
than angle-bracketing included files, I am beginning to change my
mind. Perhaps C code written for a specific compiler should have a
look and feel unique to that compiler, with let us say upper case type
suffixes on file names. This would inform the reader that we're using
Windows, and it would have the added benefit of driving you bat shit.

Richard Heathfield general advice on header files is that standard
headers should be enclosed in angle brackets <> and non-implementaion
ones should be enclosed in string quotes "". Certain platform
standards like Posix extend the "implementation" headers to included
their own headers.

/* implementaion headers */
#include <stdio.h>

/* non-implementation */
#include "my_header.h"


I'd strongly advise anyone that they followed the standard and put
standard headers (stdlib.h, stdio.h) in lower case as it reeduces
potential problems when attempting to port code. (Unix/Linux for
instance is case sensitive and wouldn't recognise STDIO.H as being the
same as stdio.h).

Check the C standard if you don't believe me!
 
S

santosh

Nick said:
On Feb 7, 8:43 pm, Richard Heathfield <[email protected]> wrote:
Although I initially accepted your [Richard Heathfield's] foolish
ideas about quoting rather
than angle-bracketing included files, I am beginning to change my
mind. Perhaps C code written for a specific compiler should have a
look and feel unique to that compiler, with let us say upper case type
suffixes on file names. This would inform the reader that we're using
Windows, and it would have the added benefit of driving you bat shit.

Richard Heathfield general advice on header files is that standard
headers should be enclosed in angle brackets <> and non-implementaion
ones should be enclosed in string quotes "". [ ... ]

Why Richard Heathfield's advice? That's the usual practice in C
programming isn't it?

<snip>
 
N

Nick Keighley

[...] I haven't had time to look at your code being busy with mine
but it looks like an effective use of the library.

The point being that a professional, whether or not he uses string.H,

that should be string.h
case matters!
is someone who fixes bugs and does not say "this is just a fast and
dirty solution". Nor is he one who gets [upset] about quoting malloc.h.

the problem is *using* malloc.h; it's a non-standard header. So when
using the function malloc() you should use the header stdlib.h rather
than malloc.h. And since stdlib.h is a standard header it should be
angle bracketed.

#include <stdlib.h>

If you aren't sure of the right header to use this is quite a nice
site
http://www.dinkumware.com/manuals/

though often just typeing the name of the function into google is good
enough (C functions are spelt so oddly there is hardly ever a
collision with some other meaning!).
 
N

Nick Keighley

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 ?)

no. The standard doesn't specify algorithms. I'd be slightly surprised
if strstr() used Boyer-Moore, I thought it was a bit over the top for
the simple cases.
 
S

santosh

Joe said:
Ben said:
Joe Wright said:
santosh wrote:
Joe Wright wrote:
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?
I must be missing something. spinoza1111 came up with almost 100 lines of
code to solve what I consider to be a simple problem solvable in 10 lines
or so. Maybe I didn't appreciate how hard a real programmer would work on
this sort of thing. Finding a substring and replacing it with another is
almost trivial.

Conceptually it is. But in the discussions elsewhere in the thread,
not only did one poster (spinoza1111) reimplement some of <string.h>
functionality, to my knowledge, all the examples avoided static
buffers and the simplistic but perhaps inefficient realloc() based
method, but chose to pre-calculate the size before allocating once.
That's the main reason for the (slight) complexity of most of the
examples.
 
S

Seebs

The point being that a professional, whether or not he uses string.H,
is someone who fixes bugs and does not say "this is just a fast and
dirty solution". Nor is he one who gets [upset] about quoting malloc.h.
the problem is *using* malloc.h; it's a non-standard header.

He's not talking about that, he's talking about my original post about the
string replace thing, which was done as a "quick path to having this work".
It didn't need to be a general solution, as we had an extremely narrowly
defined problem, but we did need one written soonish and easy to verify
the correctness of.

-s
 
N

Nick Keighley

[...] So I fixed these and compiled and ran it. It does produce
the expected output for the test cases you include in main(), but I
commented out both the TESTER macro and your main() definition and
supplied my own given below. This allows me to test your function from
the command-line without having to include each test case in the code
and go through the build process each time.

the argument for embedding the test cases in code (not necessarily the
actual delivered code) is that you have a permenant way of running all
the tests if any modifcation is ever made to the code. This tends to
improve the reliability and maintainability of your code and make you
less scared about making minor improvements to your code (re-
factoring)- testing the new code is easy.

A halfway house might be to invoke your code from a scripting
language.

<snip>
 
N

Nick Keighley

"spinoza1111" <[email protected]> ha scritto nel messaggionews:5cda5e37-e5c2-4ea4-b2f0-dca48d0289a7@x10g2000prk.googlegroups.com...

    char * ptrIndex1;
    char * ptrIndex2;
    char * ptrIndex3;
[...]

##the name for pointer should be p, p1, p2, ... pn
##the name for index i,j,k, i1, i2 ...j1, j2 ...k1, k2

almost certainly wrong. Names in programs are supposed to tell you
what a variable does. Embedding numbers in names often indicates you
need an array. There are exceptions where there are two argments with
identical semantics. But much beying two you should think again.

<snip>
 
P

Phil Carmody

Seebs said:
....
I just hope he never realizes that his implementation of a string length
counter is not particularly overth^H^H^H^H^Hrobustly engineered. If he does,
we'll get something like this:

[SNIP - aaaaaaaaaaaaaaaaaaaarrrrrrrrrrrrghhhhhhhhhhhhh!!!!!]

That was a work of art! You should print that out and frame it.
I think I'll submit it for code review later today at work ;-)

Phil
 
B

blmblm


[ snip ]
I have no respect it is true for Peter Seebach. Why? Because he's
bragged that he's never taken a computer science class in his life

Why do you keep claiming that Seebs "bragged" or boasted about not
having taken CS classes? as best I can tell, you made a guess about
various people's backgrounds, in message ID

Sounds to me that you guys AP'd out of CS 101

and he followed up to someone else's response, in message ID

<[email protected]>

as follows (slightly reformatted for readability):
There is some irony, which is that for reasons not adequately
explained (my brain is pretty weird), it *never occurred to me* to try
to take any CS classes. Programming was just stuff I did for fun. So
in fact, I've never taken ANY CS classes, of any level -- I just pick
stuff up as I go, which explains why I have a much more practical
"here's what works" attitude rather than an ivory-tower one... and
also why I have to look up basic algorithms, or be hinted towards
them.

He later wrote, in message ID

<[email protected]>




In
spinoza1111wrote:
"I have never taken any computer science classes" - Peter Seebach 26
Oct 2003 (with pride)
Lots of programmers have picked up their knowledge as they go along,
and some of them are very bright bunnies indeed.
It's entirely possible that, by sheer coincidence, I said this exact
thing both earlier today (or yesterday, but in a different time zone)
and also exactly six years ago, but it seems more likely to me by far
that Spinny's guessed the year wrong.
But there's a more significant error, which is the attribution "(with
pride)". So far as I can tell, this is pretty much guaranteed to be
in error, as my brain does not appear to generate the experiences
usually referred to by the word "pride" (or by the word "shame"; at
least I'm an equal-opportunity sort). I am neither proud of, nor
ashamed of, the coincidence that I never happen to have taken a CS
class. It has sometimes been a bit of a nuisance in terms of trying
to get my job done, but then, the degree I *did* pick up (psych) turns
out to have been, arguably, more useful to me. (I also did most of
math and philosophy degrees, and have no regrets about either.) It
probably would have been useful to pick up CS, and certainly I did
pick a fair bit up by osmosis and exposure.

Where's the bragging or boasting here?

It's in the fact that he's unqualified,

I don't agree with you that this is an established fact.
and to say that the absence of
this training is in any way a good thing is bragging and boasting and
false.

I don't agree here either. Humans have a finite number of hours
in which to accomplish whatever they want to accomplish with their
lives, and choosing not to spend any of them on formal academic
coursework in computer science allows spending more of them on other
things, things that might ultimately be more useful or interesting.
"YMMV", maybe.

(As someone who teaches CS to undergraduates, I do think that formal
coursework provides something of value, namely a conceptual framework
on which to hang the technical knowledge one picks up in the course
of a career in IT, but I would not want to claim that there is no
other way to acquire such a framework.)
His humility is feigned. I detected this when he called me a "moron".
Rahm Emanuel has apologized for this type of language: Seebs has not.
He hurls invective which is not to be humble, and deletes email
offering to discuss differences UNREAD.

Presumably as a result of discussions in this newsgroup. I'll say
that I would probably have been curious enough to at least read the
e-mail, even if I was fairly certain there would be no point in
replying, but there are certainly many e-mail messages that I delete
unread, based on the combination of sender and subject header.

[ snip ]
 
B

blmblm

[ snip ]
God, I hate that word, "eccentric". Its use normalizes deviance.

Propose a better one. (I'm mildly curious about what "normalizes
deviance" means in context, but not optimistic that an attempt to
clarify would help. <shrug>)

[ snip ]
 

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