tags:

views:

302

answers:

5

Hi guys, just brushing up on some C for a class and I've run across a little something that makes me scratch me head. For this code:

char * findString(const char * s){
/* Allocate space */    
char * ret = malloc(strlen(s) + 1);    
/* Copy characters */
char * n;
n = ret;
for ( ;*s != 0; s++)
 if (isLetter(*s))
  *n++ = *s;
*n = 0;   
/* return pointer to beginning of string */
return ret;

}

(We're just assuming an isLetter that returns a 1/0).

The idea of the snippet is to take a string with a bunch of crap in it, and return a string that contains only the letters.

So, how does 'ret' work in this instance? I'm very confused by the returning of 'ret' when 'n = ret' is declared above the for loop and 'ret' never gets set to anything afterwards. Obviously I'm missing something here. Help!

-R. L.

A: 

ret, while semantically being a string, is actually a pointer to the first character of the string. n is used as a pointer to the current position in that string. So ret stays pointing to the start of the string, while n moves along the string as it is filled in. the *n = 0 then adds the null terminator. Thus while ret doesn't get set to anything, the contents of the string it points to are set.

Yuliy
+1  A: 

both ret and n are pointers to the same block of memory. their 'values' are simply memory addresses -- when you change *n, you change *ret, even though n and ret retain their original values.

//make n point to the beginning of the block of memory pointed
//to by ret
n = ret;

//iterate through the string which was passed to
//the function
for ( ;*s != 0; s++)
        //if the current character is a letter:
        if (isLetter(*s))
                //set the character pointed to by n to
                //the current character in the string, and then
                //make n point to the next one.
                *n++ = *s;

note that the loop increments n, and then after the loop sets the last character to 0 (to null terminate the string). Now, n points to the end of the string -- but since ret was never changed it still points to the beginning of the memory that you malloced before the loop. When you return it, you're returning a pointer to the new string which is the string you passed to the function, minus all non-letters.

Note that after this function returns, it is the caller's responsibility to free() the memory allocated by the function, lest ye roam into memory leaks.

Carson Myers
Alright so let me throw this your way Carson...Considering the above, how would you return the longest string within that string?If you were given s = "(hey1234 thisisgood9998"; How in God's name would you get back the longest string? I've been toiling with this for hours!!!
K.R.
And I'm just talking about getting the longest string of letters! (consecutive)
K.R.
It's the same concept but with a bit more fun in the for loop. Maybe post that as another question, if you haven't already? It's hard to elaborate in a comment :)
Carson Myers
Done and done!http://stackoverflow.com/questions/1512899/c-largest-string-from-a-big-one
K.R.
A: 

n and ret are pointers, which means they contain addresses. In this case they both contain the address of the same character buffer that's being allocated with malloc. In this sense, n and ret are interchangeable.

Eli Bendersky
A: 

Not much to it, really, line 3 allocates an empty string, ret, that is long enough to hold the argument even if it is all letters. That string will eventually be returned. the function then iterates through the argument and if it is a letter, puts it into the return string, by way of an intermediate pointer, n, which keeps track of the current position in the returned string.

TokenMacGuy
A: 

The ret is a pointer to the beginning of the string to be returned. You need to create another pointer, n, because this pointer will not always point to the beginning of the string to be returned, it will walk on it, changing its characters. And, to be able to return a string, you must return a pointer to the beginning of the string, and you need to know where it ends (that's why you need the 0 added to the end).

Hope I helped!

jpmelos
`(*s != '\0')` is equivalent to `(*s != 0)`. `'\0'` and `0` are both 0.
Carson Myers
Oops, that's true! Thank you!
jpmelos