PDA

View Full Version : Strings and pointers in C




CsRookie
Apr 20, 2011, 04:08 PM
int findString (const char source[], const char s[])
{
int i, j, foundit = false;

// try each character in source

for ( i = 0; source[i] != '\0' && !foundit; ++i ) {
foundit = true;

// now see if corresponding chars from s match

for ( j = 0; s[j] != '\0' && foundit; ++j )
if ( source[j + i] != s[j] || source[j + i] == '\0' )
foundit = false;

if (foundit)
return i;
}

return -1;
}



How would I go about using pointers in this function rather than array notation? Kind of confused on the pointers and their uses. Thanks in advance for the help. :apple:



subsonix
Apr 20, 2011, 04:21 PM
So what is the function suppose to do? Find the sub-string s in source and return the index in source if found? In any case, if you intend to manipulate the pointers directly in the function you cannot declare them as const.

jiminaus
Apr 20, 2011, 04:23 PM
The following 2 declarations are equivalent, the array notation in a parameter list just expresses an expectation that the pointer is an array, and not just a pointer to a single value.


int findString (const char source[], const char s[]);
int findString (const char *source, const char *s);


The following two sets of statements are equivalent, where the first line is equivalent to the second line.

char c = s[i];
char c = *(s + i);


s[i] = 'a';
*(s + i) = 'a';

subsonix
Apr 20, 2011, 04:37 PM
That is true, but if the choice lays between, s[i] and *(s + i), why not use the more clear: s[i]?

If you want to do this with the pointers directly, do it without an index. That is my suggestion at least.

CsRookie
Apr 20, 2011, 04:39 PM
The following 2 declarations are equivalent, the array notation in a parameter list just expresses an expectation that the pointer is an array, and not just a pointer to a single value.


int findString (const char source[], const char s[]);
int findString (const char *source, const char *s);


The following two sets of statements are equivalent, where the first line is equivalent to the second line.

char c = s[i];
char c = *(s + i);


s[i] = 'a';
*(s + i) = 'a';


Thank you very much for the help :apple:

CsRookie
Apr 20, 2011, 04:41 PM
That is true, but if the choice lays between, s[i] and *(s + i), why not use the more clear: s[i]?

If you want to do this with the pointers directly, do it without an index. That is my suggestion at least.




int main()
{

//find
printf("Found at %i\n", findString("chatterbox", "hat"));
printf("Found at %i\n", findString("chatterbox", "att"));
printf("Found at %i\n", findString("chatterbox", "box"));
printf("Found at %i\n", findString("chatterbox", "boxx"));

return 0;

}


int findString (const char source[], const char s[])
{
int i, j, foundit = false;

// try each character in source

for ( i = 0; source[i] != '\0' && !foundit; ++i ) {
foundit = true;

// now see if corresponding chars from s match

for ( j = 0; s[j] != '\0' && foundit; ++j )
if ( source[j + i] != s[j] || source[j + i] == '\0' )
foundit = false;

if (foundit)
return i;
}

return -1;
}




that is what it looks like right now, you are suggesting to do it with pointers directly, do it without an index? Can you explain to me a little more please, thanks for the help, I am having trouble grasping pointers.

subsonix
Apr 20, 2011, 04:48 PM
It's always helpful with a small comment about what the code is suppose to do, if you want help, that was my point. Anyway, this is a simple example (my simple attempt which might have errors in it) but it shows the principle behind what I meant.


char *findString(char *source, char *s) {
char *found = NULL;

for(; *source != 0 ; source++) {
for(found = source; *source == *s && *s != 0 && *source != 0; source++, s++ ) {
if( s[1] == 0 )
return found -1;
}
}
return NULL;
}



int main()
{
char *source = "sub-string";
char *s = "string";
char *found = NULL;

found = findString(source, s);
if( found )
puts(found);
else
puts("Not found");


return 0;
}

jiminaus
Apr 20, 2011, 10:43 PM
That is true, but if the choice lays between, s[i] and *(s + i), why not use the more clear: s[i]?

Personally, I can't see any reason to use *(s + i) over s. I've never used the former syntax in my own code.



char *findString(char *source, char *s) {
char *found = NULL;

for(; *source != 0 ; source++) {
for(found = source; *source == *s && *s != 0 && *source != 0; source++, s++ ) {
if( s[1] == 0 )
return found -1;
}
}
return NULL;
}



Great. I always forget about this technique of sliding a pointer along an array in C.

OP really analyse this code and you'll learn [i]alot about pointers. Step through it expression at time, and notice and think about what happens and why it's happening.

chown33
Apr 21, 2011, 12:18 AM
Personally, I can't see any reason to use *(s + i) over s[i]. I've never used the former syntax in my own code.

Just because expressions are equivalent doesn't mean they have the same level of clarity. That's why C has a separate -> operator, which is precisely equivalent to an indirection followed by a dot: sp->sname is identical to (*sp).sname, only the former is a lot clearer than the latter, and easier to write. -> is especially useful in a sequence, such as sp->sptr->othername, which is pretty horrific with only * and . (left as an exercise for the reader).

dmi
Apr 21, 2011, 01:24 AM
Personally, I can't see any reason to use *(s + i) over s[i]. I've never used the former syntax in my own code.

Have you ever used *(s + 0) == *(s) over s[0] in your own code?
Or *(0 + i) == *i over 0[i] in your own code?
Or (s + i) over &s[i]?
s+=i over s=&s[i]?

Sander
Apr 21, 2011, 03:05 AM
If the requirement for your findString() is that it returns the position at which the substring was found, you will have to keep around some kind of index anyway. In that case, I'd say your code won't become any clearer by using pointer arithmetic directly.

jiminaus
Apr 21, 2011, 03:22 AM
Have you ever used *(s + 0) == *(s) over s[0] in your own code?
Or *(0 + i) == *i over 0[i] in your own code?
Or (s + i) over &s[i]?
s+=i over s=&s[i]?


Of these I have only ever used s + i over &s[i] and s +=i over s = &s[i]. But I don't get your point DMI.

I didn't/don't advocate explicit pointer arithmetic over array indexing. I just attempted to answer the OP's question "How would I go about using pointers in this function rather than array notation?".

MasConejos
Apr 21, 2011, 10:58 AM
As a side note, the inner loop can be replaced by the built in function strncmp (http://www.cplusplus.com/reference/clibrary/cstring/strncmp/), which means that both pointers and arrays are barely needed at all.

int findString(const char* str, const char* matchStr)
{
int ix = 0;
int matchLength = strlen(matchStr);

while(str[ix] != '\0')
{
if(strncmp(&str[ix], matchStr, matchLength) == 0)
{
return ix;
}
ix++;
}
return -1;
}

subsonix
Apr 21, 2011, 11:05 AM
That is true, but then you might as well use the function strstr() that finds a substring in a string. :)

MasConejos
Apr 21, 2011, 12:50 PM
...And somehow, despite having perused the header reference many times, I've always managed to miss that function. :o

thanks!