Google Answers Logo
View Question
 
Q: Problem with returning values from home-grown string manipulation code... ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: Problem with returning values from home-grown string manipulation code...
Category: Computers > Programming
Asked by: zefyre-ga
List Price: $5.00
Posted: 05 Feb 2004 11:44 PST
Expires: 06 Mar 2004 11:44 PST
Question ID: 303829
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
Answer  
Subject: Re: Problem with returning values from home-grown string manipulation code...
Answered By: hammer-ga on 05 Feb 2004 14:52 PST
Rated:5 out of 5 stars
 
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
zefyre-ga rated this answer:5 out of 5 stars and gave an additional tip of: $2.50
Thanks for your help!

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy