reverse a string

M

Mark

Hello

as an exercise routine, here is a short C function, reversing a source
string and writing the result in the destination buffer. Would be glad to
hear some critics and advices on improvements. Thanks in advance.

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

void reverse(char *d, const char *s)
{
int i = 0;
size_t len = strlen(s) - 1;
do {
d[i++] = s[len--];
} while (len != 0);
d = '\0';
}

int main(void)
{
char s[100];
reverse(s, "This is a fairy long string to be reversed soon.");
printf("%s\n", s);

return 0;
}
 
S

Scooser

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

void reverse(char *d, const char *s)

At least the size of the destination buffer ist missing so there is no
way to check for buffer overflows.
{
    int i = 0;
    size_t len = strlen(s) - 1;

What if s == NULL, what if s = "" ?
size_t len = (size_t)(strlen("") - 1) == (size_t)-1 == SIZE_MAX!
    do {
        d[i++] = s[len--];

What if d == NULL or sizeof(d[]) < i?
    } while (len != 0);
    d = '\0';

}

int main(void)
{
    char s[100];
    reverse(s, "This is a fairy long string to be reversed soon.");
    printf("%s\n", s);


So what if your code looks like this?
char s[10];
reverse(s, "This is a fairy long string to be reversed soon.");

or
char s[100];
reverse(s, "");

    return 0;

}

Scooser
 
S

Seebs

#include <stdio.h>
#include <string.h>
void reverse(char *d, const char *s)
{
int i = 0;

This should perhaps be a size_t. What if you're on a system with 16-bit
int and someone hands you a 33,000 byte string? :)
size_t len = strlen(s) - 1;
do {
d[i++] = s[len--];
} while (len != 0);

I would probably write that last as "while (len)"; I don't like to use
explicit "!= 0" in C. (Personal preference, and I'm not sure it's the
right preference to have; it has certainly hurt me in Lua and Ruby.)

That said... I don't think this will copy the first character of s.

Imagine that s points to "foo". strlen(s) = 3, so len starts out 2.

do
d[i++] = s[len--]; /* d = "o???????", i = 1, len = 1 */
d[i++] = s[len--]; /* d = "oo??????", i = 2, len = 0 */
.... and now we reach the while, and len is 0.

But we haven't actually copied s[len].

You now face a problem. Obviously, idiomatically, you'd change it to
while (len >= 0)
except that len's a size_t, which is an unsigned type, and this is just
an infinite loop.

Perhaps:

do {
d[i++] = s[len];
} while (len-- > 0);

I don't really like the name len for the control, though, because it's not
exactly right. Hmm.

char *end = s + strlen(s) - 1;

do {
*d++ = *end--;
} while (end >= s);
.... nope, won't do, it decrements "end" off the beginning of s, which isn't
allowed.

char *end = s + strlen(s);
do {
*d++ = *--end;
} while (end > s);
*d = '\0';

Note that it's perfectly safe to increment 'd' locally, you don't need to
track a separate index. Note the use of predecrement, and starting end
pointing at the '\0' in s, so that the loop condition is now idiomatic and
testable. This makes some sense; conceptually, we use postincrement while
counting through a string, so we probably ought to predecrement for symmetry.

-s
 
U

user923005

Hello

as an exercise routine, here is a short C function, reversing a source
string and writing the result in the destination buffer. Would be glad to
hear some critics and advices on improvements. Thanks in advance.

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

void reverse(char *d, const char *s)
{
    int i = 0;
    size_t len = strlen(s) - 1;
    do {
        d[i++] = s[len--];
    } while (len != 0);
    d = '\0';

}

int main(void)
{
    char s[100];
    reverse(s, "This is a fairy long string to be reversed soon.");
    printf("%s\n", s);

    return 0;

}


Your function doesn't actually work.

Give it this interface:

void reverse(char *d, const size_t dsize, const char *const
s);

Test it with this:

#ifdef UNIT_TEST
int main(void)
{
char s[100];
size_t apparent_length;

reverse(s, sizeof s, "");
puts(s);
reverse(s, sizeof s, "0");
puts(s);
reverse(s, sizeof s, "10");
puts(s);
reverse(s, sizeof s, "102");
puts(s);
for (apparent_length = sizeof s; apparent_length > 0;
apparent_length--) {
reverse(s, apparent_length, "This is a fairy long string to be
reversed soon.");
puts(s);
}
return 0;
}
#endif


I get this in debug mode:

0
01
201
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
Assertion failed: len < dsize, file ..\oops.c, line 10

And this in release mode:

0
01
201
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT
..noos desrever eb ot gnirts gnol yriaf a si sihT

Of course, I have a working string reversal using the API I provided.
 
P

Phil Carmody

Seebs said:
This should perhaps be a size_t. What if you're on a system with 16-bit
int and someone hands you a 33,000 byte string? :)

Yikes, I appear to have a 4 bajillion character long string with the
example I chose.
do {
d[i++] = s[len--];
} while (len != 0);

I would probably write that last as "while (len)"; I don't like to use
explicit "!= 0" in C. (Personal preference, and I'm not sure it's the
right preference to have; it has certainly hurt me in Lua and Ruby.)

That said... I don't think this will copy the first character of s. [SNIP, yup]

You now face a problem. Obviously, idiomatically, you'd change it to
while (len >= 0)
except that len's a size_t, which is an unsigned type, and this is just
an infinite loop.

Perhaps:

do { ....
do { ....
do {
....

How about while(...) { ?

Phil
 
S

Seebs

How about while(...) { ?

.... Now, now, just because that's obvious, simple, and clear, doesn't mean
it's the best choice. It was, uhm. A teaching moment!

Yes, that's it.

The REAL lesson is "never pay any attention to things I write before my
meds have kicked in".

-s
 
U

user923005

... Now, now, just because that's obvious, simple, and clear, doesn't mean
it's the best choice.  It was, uhm.  A teaching moment!

Yes, that's it.

The REAL lesson is "never pay any attention to things I write before my
meds have kicked in".

This was my implementation:

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

void reverse(char *d, const size_t dsize, const char *const
s)
{
size_t i;
size_t len = strlen(s);

assert(len < dsize);
assert(dsize > 0);

if (dsize > 0) {
d[0] = 0;

if (len < dsize) {
for (i = 0; i < len; i++) {
d = s[len - i - 1];
}
d = 0;
}
}
}

#ifdef UNIT_TEST
int main(void)
{
char s[100];
size_t apparent_length;

reverse(s, sizeof s, "");
puts(s);
reverse(s, sizeof s, "0");
puts(s);
reverse(s, sizeof s, "10");
puts(s);
reverse(s, sizeof s, "102");
puts(s);
for (apparent_length = sizeof s; apparent_length > 0;
apparent_length--) {
reverse(s, apparent_length, "This is a fairy long string to be
reversed soon.");
puts(s);
}
return 0;
}
#endif
 
U

user923005

     If compiled with NDEBUG, neither assert() does anything.  If
compiled without NDEBUG and dsize==0, the first assert() will fire.
Either way, the second assert() never does anything.

If the API is used properly, and the design is correct, then no assert
will ever fire.
In a sense, they are comments about what I assert to be true.
[...]
#ifdef UNIT_TEST
int             main(void)
{
    char            s[100];
    size_t          apparent_length;
    reverse(s, sizeof s, "");
    puts(s);
[...]

     How about a few more self-verifying test cases?

        reverse(s, sizeof s, "able was i ere i saw elba");
        assert (strcmp(s, "able was i ere i saw elba") == 0);

:)
 
M

Mark

Eric said:
If compiled with NDEBUG, neither assert() does anything. If
compiled without NDEBUG and dsize==0, the first assert() will fire.
Either way, the second assert() never does anything.

Could you guys explain me *when* one should use 'assert'. I do understand
what it does and I have read c-FAQ 20.24b, but consider the code proposed by
user923005 earlier:

void reverse(char *d, const size_t dsize, const char *const s)
{
size_t i;
size_t len = strlen(s);

assert(len < dsize);
assert(dsize > 0);
....
}

would not it be better to gracefully process 'len < dsize' or 'dsize > 0'
situations - for instance, setting 'errno' value or returning negative
value, provided 'int reverse(...)' prototype, rather then kill the execution
of the routine?

In other words, as I understand (and correct me if I'm wrong), assert is
suitable for catching logical errors on a development and debugging stage,
not at run-time.
 
M

Mark

Thanks to everyone for commentaries. Followed is a working routine, I hope I
have not missed anything:

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

#define BUFLEN 50

static const char *p[] = {
"This is a fairy long string to be reversed soon.",
"",
"This is a string",
"and very-very-very-very awfully long string full of garbage",
"another one",
"and one more lengthy string with numbers 123",
"just one more",
NULL
};

int reverse2(char *d, const char *s, size_t dlen)
{
size_t i = 0;
size_t slen;

if (NULL == s) {
return -1;
} else {
slen = strlen(s);
}

/* check if buffer is large enough */
if (NULL == d || dlen < slen)
return -1;
while (slen) {
d[i++] = s[--slen];
}
d = '\0'; /* terminate string */

return 0;
}

int main(void)
{
int i = 0;
char s[BUFLEN] = { '\0', };

while (p) {
if (reverse2(s, p, sizeof s) == 0) {
puts(s);
}
++i;
}

return 0;
}
 
U

user923005

Could you guys explain me *when* one should use 'assert'. I do understand
what it does and I have read c-FAQ 20.24b, but consider the code proposed by
user923005 earlier:

void            reverse(char *d, const size_t dsize, const char *const s)
{
    size_t          i;
    size_t          len = strlen(s);

    assert(len < dsize);
    assert(dsize > 0);
...

}

would not it be better to gracefully process 'len < dsize' or 'dsize > 0'
situations - for instance, setting 'errno' value or returning negative
value, provided 'int reverse(...)' prototype, rather then kill the execution
of the routine?

In other words, as I understand (and correct me if I'm wrong), assert is
suitable for catching logical errors on a development and debugging stage,
not at run-time.

The use of assert() is a technique to show that you have certain
assumptions about program data and processing. My ground rule is that
tests in asserts should also be accounted for in the program source as
well.

The value of an assert is that if something strange happens, the
program will throw an assert and it is easy to debug it.

An assert is not to change the behavior of a program. It has two
purposes in my mind. First, it shows what assumptions you have about
inputs and logical steps in a program. Second, it is an aid in
debugging, because you will get thrown to the spot in the debugger if
any of your assumptions are ever violated.
 
U

user923005

Thanks to everyone for commentaries. Followed is a working routine, I hope I
have not missed anything:

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

#define BUFLEN 50

static const char *p[] = {
        "This is a fairy long string to be reversed soon.",
        "",
        "This is a string",
        "and very-very-very-very awfully long string full of garbage",
        "another one",
        "and one more lengthy string with numbers 123",
        "just one more",
        NULL

};

int reverse2(char *d, const char *s, size_t dlen)
{
    size_t i = 0;
    size_t slen;

    if (NULL == s) {
        return -1;
    } else {
        slen = strlen(s);
    }

    /* check if buffer is large enough */
    if (NULL == d || dlen < slen)
        return -1;
    while (slen) {
        d[i++] = s[--slen];
    }
    d = '\0'; /* terminate string */

    return 0;

}

int main(void)
{
    int i = 0;
    char s[BUFLEN] = { '\0', };

    while (p) {
        if (reverse2(s, p, sizeof s) == 0) {
            puts(s);
        }
        ++i;
    }

    return 0;

}


This is nicely done.

Most of the time, when someone asks student questions they are really
just fishing to have someone do their homework for them. I can see
plainly that you have incorporated feedback, tried to improve your
program, and succeeded at it.

I guess that you are going to do very well.
 
P

Phil Carmody

Mark said:
Could you guys explain me *when* one should use 'assert'. I do
understand what it does and I have read c-FAQ 20.24b, but consider the
code proposed by user923005 earlier:

void reverse(char *d, const size_t dsize, const char *const s)
{
size_t i;
size_t len = strlen(s);

assert(len < dsize);
assert(dsize > 0);
...
}

would not it be better to gracefully process 'len < dsize' or 'dsize >
0' situations - for instance, setting 'errno' value or returning
negative value, provided 'int reverse(...)' prototype, rather then
kill the execution of the routine?

In other words, as I understand (and correct me if I'm wrong), assert
is suitable for catching logical errors on a development and debugging
stage, not at run-time.

Phase 1 of defensive programming is knowing when to insert assert()s.
Phase 2 of defensive programming is knowing when to not insert them.

Use asserts only for situations which show a logical inconsistency,
not things that you don't want to happen, or things that mustn't happen,
but things that cannot, with working code, ever logically happen.

If the only input to reverse() above was a string generated by a
never-empty sprintf, then you could use assert() to check the length
was non-0. However, graceful handling makes much more sense for
many reasons. (It's very cheap, and there's no semantic reason to
not define the reverse of an empty string, for a start.)

Phil
 
N

Nick Keighley

In circumstances where the condition is true unless the program is
broken. That is, in circumstances where an assertion failure means
that you as a programmer got it wrong.




Poor use of assert.


Poor use of assert.


Yes.



Well, its catches do happen at runtime, but yes, they should only ever
fire during the development process. If an assertion fires in
production, it's a sure sign that you didn't test properly. It's
*also* a sure sign that you didn't compile it properly. Assertions
are scaffolding, and you don't leave the scaffolds up around a
building after you've finished building it.

for the same reason we remove lifeboats before going to sea
 
S

Seebs

for the same reason we remove lifeboats before going to sea

No, for the same reason that the scaffolding which was probably around a ship
during its construction isn't still around the ship when it goes to sea.
Something which might be essential to safety for one usage might be
detrimental to it in another.

When I've had programs fail due to assertions, it's usually been pretty bad,
and often been much worse than merely continuing would have been.

I guess... If you think the assertion should be there at runtime, it
shouldn't *be* an assertion. It should be a diagnostic with some attempt
at error recovery.

-s
 
J

James Kuyper

Nick said:
for the same reason we remove lifeboats before going to sea

If you need the programming equivalent of a lifeboat, you're looking for
something substantially more sophisticated than assert(). A lifeboat
needs, at an absolute minimum, to float better than the ship it's
escaping from; ideally it should include mechanisms for attracting the
attention of rescuer (dye for the water, signal flare, brightly colored
flags, a flashing light, or even a radio beacon) some means of
propulsion (oars, a sail, or even a small motor), a signal beacon,
medical supplies, and even some food and water. As far as such analogies
go, in production code assert() more closely resembles a depth charge
(with trigger_depth==surface) than a lifeboat.
 
N

Nick Keighley

In



So much for analogies!

I figured you deserved a counter analogy. It was actually
a quote by A Famous Computer Scientist (Dijkstra? Hoare? Wirth?)
Because assertions are removed from the production version, we have
the capacity to use assertions to do a huge amount of program
validation processing which would, if left in production code, be an
intolerable burden on the user. For example, I use assertions to
check the integrity of data structures.

I tend to write an XXX_is_valid() predicate and call it heavily
in the test harness.
This is appropriate because
the data structures can't become corrupted if the program is correct,
no matter what data the program is asked to process. These checks can
take a considerable amount of time (at the very least, a check is
O(n), since every element is touched on every check - and even if
there are only n checks, you have O(n*n) right there).

um aren't those two ns different?
 
N

Nick Keighley

If you need the programming equivalent of a lifeboat, you're looking for
something substantially more sophisticated than assert(). A lifeboat
needs, at an absolute minimum, to float better than the ship it's
escaping from; ideally it should include  mechanisms for attracting the
attention of rescuer (dye for the water, signal flare, brightly colored
flags, a flashing light, or even a radio beacon)

I don't use the real assert() I use one that writes to a log file
(hence attracting the attention of the rescuers!)

some means of
propulsion (oars, a sail, or even a small motor), a signal beacon,
medical supplies, and even some food and water. As far as such analogies
go, in production code assert() more closely resembles a depth charge
(with trigger_depth==surface) than a lifeboat.

there are days when I'd prefer no answer to the wrong answer
 
C

Chris M. Thomasson

Mark said:
Thanks to everyone for commentaries. Followed is a working routine, I hope
I have not missed anything:
[...]

I would personally prefer a two-level API. One "low-level" function which
accepts a length parameter, and a "high-level" wrapper API which would call
`strlen()'. And perhaps another "high-level wrapper would would allocate a
new string. Perhaps something like this:


<pseudo-code typed in news reader, please forgive any typo's>
_________________________________________________________________________
#include <stdio.h>
#include <stdlib.h>
#include <string.h>




char*
reverse_string_ex(char* buffer, size_t size)
{
if (buffer && *buffer && size > 1)
{
char* cur = buffer;
char* end = buffer + size;

do
{
char tmp = *cur;
*cur = *--end;
*end = tmp;
++cur;
}

while (end - cur > 1);
}

return buffer;
}


char*
reverse_string(char* buffer)
{
if (buffer)
{
reverse_string_ex(buffer, strlen(buffer));
}

return buffer;
}


char*
reverse_string_alloc(char const* buffer)
{
if (buffer)
{
size_t size = strlen(buffer) + 1;
char* new_buffer = malloc(size);

if (new_buffer)
{
return reverse_string_ex(memcpy(new_buffer, buffer, size),
size - 1);
}
}

return NULL;
}




int main(void)
{
char* dynamic_buffer;
char buffer[] = "Hello World";

puts(reverse_string_ex(buffer, sizeof(buffer) - 1));

if ((dynamic_buffer = reverse_string_alloc("John Doe")))
{
puts(dynamic_buffer);
puts(reverse_string(dynamic_buffer));
free(dynamic_buffer);
}

puts(reverse_string(buffer));

return 0;
}
_________________________________________________________________________




One nice thing, the `reverse_string_ex()' function is O(N / 2).
 
P

Phil Carmody

Richard Heathfield said:
I'm sure that's true of all of us. But it's really simple - if you're
not confident enough of the code to release it without assertions in
place, it is not yet ready for release.

Amen. Unfortunately, in the real world...

I unfortunately have become notorious as the assert-Nazi at work,
when I see a faux assert in syslog (they are too cowardly to actually
terminate - which is the worst of both worlds) I create a bug report
indicating that the component is not yet ready for release. I believe
I now spend about as long following up on syslog asserts than I do
actually coding now :-(. Fortunately, code quality has improved almost
measurably in the last few months...

Phil
 

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
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top