Hi,
I am working on some string manipulation code, to be compiled using
GCC on OS X 10.3. The code is as follows...
char *es_strrclip(char needle, char * haystack) {
int startpos = 0;
int endpos = es_strrchr(needle, haystack);
static char * retval[ES_MAX_RETLEN];
int copying_bytes = 0;
int pos = 0;
int count = 0;
char * cp;
cp = haystack;
fprintf(stderr, "%d\n", endpos);
for ( ; ; ) {
es_print("Bob\n");
if (pos == startpos) {
copying_bytes = 1;
}
if (copying_bytes == 1) {
retval[count] = cp;
count++;
}
if (pos == endpos) {
break;
}
fprintf(stderr, "--%d\n", pos);
pos++;
cp++;
}
retval[count] = '\0';
return(*retval);
}
es_strrpos is supposed to take the value of needle, and return the
position (base of zero) in which it last appears in haystack. I know
that this function returns the correct value...
As an example of proper operation, if I were to call this with...
char * string = es_strrclip(' ', "The First Life")
.. I would like string's value to be "The First "
My problem is that, no matter what I do, besides for setting startpos
and endpos to manual integer values, the function always returns the
exact same value that haystack is set to.
I know the answer is probably sitting right in front of me, but I'm
just looking over it, due to my continued frustration with it.
If somebody could please point out what I am doing wrong, I would appreciate it.
Thank you!
-- Quinn |
Request for Question Clarification by
hammer-ga
on
05 Feb 2004 12:09 PST
For starters, it looks like you may have a similar problem to the one
we worked on yesterday. If es_strrchr is meant to be an implementation
of strrchr, then it should be returning a char *, not an int.
Two, I'm not sure why retval is declared as static, unless you are
trying to allocate permanent memory in a somewhat kludgy way. *grin*
Three, as with yesterday, if es_strrchr returns a char * instead of an
int, this is actually a much simpler routine than you are making it.
Four, to return retval as a char *, you just want return(retval) not
return(*retval).
Should es_strrchr return a char * instead of an int?
- Hammer
|
Request for Question Clarification by
hammer-ga
on
05 Feb 2004 12:13 PST
Oh, and to do this part:
retval[count] = cp;
you need to use the * to just get the one character, like so:
retval[count] = *cp;
|
Clarification of Question by
zefyre-ga
on
05 Feb 2004 12:20 PST
Hammer,
GCC seems to generate warnings if I change some of the things you've suggested.
Man, I wish I could just pay somebody to write this code for me. ;-)
Any further suggestions are appreciated.
Thanks,
Quinn
|
Request for Question Clarification by
hammer-ga
on
05 Feb 2004 12:36 PST
Well, I can write your function for you, but I'd need you to post
es_strrchr so I can use it instead of strrchr, since you are not
actually implemeting strrchr.
- Hammer
|
Clarification of Question by
zefyre-ga
on
05 Feb 2004 12:50 PST
Hammer,
I can't thank you enough!
We'll be lucky if this isn't actually doing anything wrong. ;-)
Here you go...
int es_strrchr(char needle, char * haystack) {
int retval = 0;
char * cp;
cp = haystack;
if (needle == '\0') {
retval = NULL;
return(retval);
}
for ( ; ; ) {
if (*cp == '\0') {
break;
}
retval++;
cp++;
}
for ( ; ; ) {
if (*cp == needle) {
break;
}
if (retval == 0) {
retval = NULL;
break;
}
retval--;
cp--;
}
return(retval);
}
If it's at all unclear (which it shouldn't be to a smart person such
as yourself,) this function returns the position number (base of zero)
of the last occourance of needle in haystack.
Thanks again for your kind help -- I will be sure to give credit where
credit is due. :)
-- Quinn
|
Here is your function. Below it is a rewritten version of
es_strrchr(). I needed to rewrite it because it returned 0 on failure,
which is actually not a failure condition. Let me know if you need
anything explained!
char *es_strrclip(char needle, char *haystack)
{
int endpos = -1;
char *retval;
char *cp;
retval = NULL;
if(haystack != NULL)
{
endpos = es_strrchr(needle, haystack);
if(endpos > -1)
{
retval = (char *)strdup(haystack);
if(retval != NULL)
{
cp = retval;
if((endpos + 1) <= strlen(retval))
{
cp += (endpos + 1);
*cp = '\0';
}
else
{
fprintf(stderr, "Endpos is past end of string.\n");
}
}
else
{
fprintf(stderr, "Strdup failed.\n");
}
}
else
{
fprintf(stderr, "Needle not found in Haystack.\n");
}
}
else
{
fprintf(stderr, "Haystack is NULL.\n");
}
return(retval);
}
int es_strrchr(char needle, char *haystack)
{
int retval;
int cnt;
char *cp;
retval = -1;
if(haystack != NULL)
{
cnt = 0;
cp = haystack;
if (needle != '\0')
{
while(*cp != '\0')
{
if (*cp == needle)
{
retval = cnt;
}
cnt++;
cp++;
}
}
}
return(retval);
}
Important Note: es_strrclip allocates memory using strdup. This
allocates memory, then copies haystack into it. There are two
important things to know about this. One, this means that haystack
itself remains in its original state, instead of being clipped. Two,
in order to avoid leaking memory, the function calling es_strrclip
should free the return value after using it.
Let me know if you need any more help with this.
- Hammer |
Clarification of Answer by
hammer-ga
on
05 Feb 2004 15:07 PST
Just as a side note, here is a version that shows how it works with
strrchr itself, which returns a char *.
char *es_strrclip_pointer(char needle, char *haystack)
{
char *endpos;
char *retval;
retval = NULL;
if(haystack != NULL)
{
retval = (char *)strdup(haystack);
if(retval != NULL)
{
endpos = strrchr(retval, needle);
if(endpos != NULL)
{
endpos++;
*endpos = '\0';
}
else
{
retval = NULL;
fprintf(stderr, "Needle not found in Haystack.\n");
}
}
else
{
fprintf(stderr, "Strdup failed.\n");
}
}
else
{
fprintf(stderr, "Haystack is NULL.\n");
}
return(retval);
}
- Hammer
|
Request for Answer Clarification by
zefyre-ga
on
06 Feb 2004 02:49 PST
Hammer,
When I try to compile that with GCC, it compiles warning- and
error-free, but, when I try out es_strrclip(), I get a "bus error"
upon running.
Any ideas of why this may be?
-- Quinn
|
Clarification of Answer by
hammer-ga
on
06 Feb 2004 05:20 PST
In your case, it may mean that you are addressing illegal memory. I
don't have a compiler on my Mac, so I can't check this under OS X. How
are you "trying out" the routine? It ran fine for me.
- Hammer
|
Request for Answer Clarification by
zefyre-ga
on
06 Feb 2004 05:45 PST
Hammer,
That's odd; you have OS X, but not the developer tools? :|
Here's an example of how I tested it out...
#include <stdio.h>
#include "es_common.h" // Header for the es_ function lib -- includes es_common.c
int main() {
char * string;
string = es_strrclip(' ', "Zephyr Joseph Black");
printf("\"%s\"\n", string); // Outputs string in double quotes
so I can see leading/trailing spaces
return(0);
}
May God forbid there's anything wrong with my testing code. :D
Let me know what you find.
Thanks!
-- Quinn
|
Clarification of Answer by
hammer-ga
on
06 Feb 2004 06:02 PST
I specifically keep the Mac free of development stuff. It's a pleasure
box, not a work box. :>
Your code runs fine for me. However, in order to really look for the
error, I'll need to see the rest of it. Post any .h and .c files that
are being included (except the standard lib stuff) and show me the
command you are using to compile. Something like:
cc my_code.c es_common.c -o es_clip
- Hammer
|
Request for Answer Clarification by
zefyre-ga
on
06 Feb 2004 08:52 PST
Hammer,
/* test.c */
#include <stdio.h>
#include "es_common.h"
int main() {
char * string = es_strrclip(' ', "Zephyr Joseph Black");
printf("\"%s\"\n", string);
return(0);
}
/* es_common.h */
#include <stdio.h>
char *es_strrclip(char needle, char *haystack);
int es_strrchr(char needle, char *haystack);
#include "es_common.c"
/* es_common.c */
char *es_strrclip(char needle, char *haystack) {
int endpos = -1;
char *retval;
char *cp;
retval = NULL;
if (haystack != NULL) {
endpos = es_strrchr(needle, haystack);
if (endpos > -1) {
retval = (char *)strdup(haystack);
if (retval != NULL) {
cp = retval;
if ((endpos + 1) <= strlen(retval)) {
cp += (endpos + 1);
*cp = '\0';
} else {
fprintf(stderr, "Endpos is past end of string.\n");
}
} else {
fprintf(stderr, "Strdup failed.\n");
}
} else {
fprintf(stderr, "Needle not found in Haystack.\n");
}
} else {
fprintf(stderr, "Haystack is NULL.\n");
}
return(retval);
}
int es_strrchr(char needle, char *haystack) {
int retval;
int cnt;
char *cp;
retval = -1;
if (haystack != NULL) {
cnt = 0;
cp = haystack;
if (needle != '\0') {
while (*cp = '\0') {
if (*cp == needle) {
retval = cnt;
}
cnt++;
cp++;
}
}
}
return(retval);
}
You may notice that I took the functions you wrote and adapted the
"style" to match mine. I doubt that has anything to do with my issue,
but, please correct me if I'm wrong.
Thanks!
-- Quinn
|
Clarification of Answer by
hammer-ga
on
06 Feb 2004 12:29 PST
While changing the style, you created a logical error in es_strrchr.
This line:
while (*cp = '\0') {
Should say:
while (*cp != '\0') {
- Hammer
|