Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > struggling with strings

Reply
Thread Tools

struggling with strings

 
 
tuchka
Guest
Posts: n/a
 
      11-13-2003
Hi guys!
I am trying to learn C programming but my java background blocks my
brains.
I have a book with a lot of functions and some of them don't work
correctly, so I have opportunity to exercise in C by correction
(strange, huh?).
For example, i want to write function that removes all occurences of
given substring from string.
I have two functions so far:

1. removes first substring from the string (i made it after
corrections of the function that i had in the horrible book:

char *strstr_rem_first(char *string, char *substring) {

int i, j, k, loc=-1;

for(i=0; string[i] && (loc==-1); i++) {
for(j=i, k=0; string[j] ==substring[k];j++, k++)
if(!substring[k+1])
loc=i;
if(loc != -1) { //substring was found
for(k=0; substring[k];k++); {
for(j=loc, i=loc+k; string[i]; j++, i++) {
string[j] = string[i];
string[i]='\0';
}
}
}
}
return (string);
}
2. finds rightmost index of the substring (returns -1 if not found):

int substring_index(const char *string, const char *substring) {

int i, j, k;
for(i=0; string[i];i++)
for(j=i,k=0; string[j] == substring[k]; j++, k++)
if(!substring[k+1])
return(i);

return(-1);
}

Now, armed with these I wanted to construct function that removes all
substrings.

I though about somthing like this:

while(substring_index() > 0)
string_original becomes substring_rem_first

return string_original

Unfortunately, because strings are treated as arrays and i can't
transfer references as easily as i got used to, i can't figure out how
to accomplish it in C.
I shuffled some pointers and some strcpy() etc in vain.
Especially this 'string_original becomes substring_rem_first' bothers
me.
I always end up with 'undefined' reference to 'substring_rem_first'.

Could you help me out?
 
Reply With Quote
 
 
 
 
Ekkehard Morgenstern
Guest
Posts: n/a
 
      11-14-2003
Hi tuchka,

"tuchka" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed) om...
> 1. removes first substring from the string (i made it after
> corrections of the function that i had in the horrible book:
> 2. finds rightmost index of the substring (returns -1 if not found):


Check out the functions declared in "string.h".

Here's a function to remove all occurrences of "substring" from "string":

#include <string.h>

char* strstr_rem_all( char* string, const char* substring ) {
char* occurrence; int substr_len = strlen( substring ); int move_len =
strlen( string ) - substr_len + 1; /* +1 b/c of terminating '\0' */
while ( occurrence = strstr( string, substring ) ) {
memmove( occurrence, string + substr_len, move_len );
}
return string;
}

memmove() is used instead of memcpy(), because it handles overlapping
copies.

I hope that helps!

Regards,
Ekkehard Morgenstern.


 
Reply With Quote
 
 
 
 
tuchka
Guest
Posts: n/a
 
      11-14-2003
Thank you, Ekkehard,
I see how that function could've work but i still cannot get it to
work.
The function as written by you gives the following error:

C:\Sveta\C_PROG~1\STRING~1>str_test
123fart456fart789fart

Reverse traf987traf654traf321 is traf987traf654traf321
Filled with x became xxxxxxxxxxxxxxxxxxxxx
After removing first fart became 123456fart789fart
After removing all fart became
123art456rt456rt456rt456rt456rt456rt456rt?

Exiting due to signal SIGSEGV
General Protection Fault at eip=0000772e
eax=00000000 ebx=00000000 ecx=ffffffff edx=ffffffff esi=ffffffff
edi=ffffffff
ebp=00090390 esp=0008ef6c
program=C:\SVETA\C_PROG~1\STRING~1\STR_TEST.EXE
cs: sel=01a7 base=029a0000 limit=0009ffff
ds: sel=01af base=029a0000 limit=0009ffff
es: sel=01af base=029a0000 limit=0009ffff
fs: sel=017f base=00005a50 limit=0000ffff
gs: sel=01bf base=00000000 limit=0010ffff
ss: sel=01af base=029a0000 limit=0009ffff
App stack: [00090560..00010560] Exceptn stack: [000104c0..0000e580]

Call frame traceback EIPs:
0x0000772e
0x00003946
0x00001b82
0x000033d8

I re-wrote it like this but again i've got 'undefined reference' for
str_rem_first(string,substring):

char *strstr_rem_all(char *string, const char *substring) {
//char occurence[strlen(string)];
char *ptr;
int substr_len=strlen(substring);
int move_len=strlen(string)-substr_len+1;

while(ptr=strstr(string, substring)) {
char occurence[strlen(string)];
memmove(occurence, str_rem_first(string,substring),
strlen(string)-substr_len+1);
}
return string;
}

Sigh, sigh
Why the lang. is so hard?


"Ekkehard Morgenstern" <(E-Mail Removed)> wrote in message news:<bp1gfj$ssc$(E-Mail Removed)>...
> Hi tuchka,
>
> "tuchka" <(E-Mail Removed)> schrieb im Newsbeitrag
> news:(E-Mail Removed) om...
> > 1. removes first substring from the string (i made it after
> > corrections of the function that i had in the horrible book:
> > 2. finds rightmost index of the substring (returns -1 if not found):

>
> Check out the functions declared in "string.h".
>
> Here's a function to remove all occurrences of "substring" from "string":
>
> #include <string.h>
>
> char* strstr_rem_all( char* string, const char* substring ) {
> char* occurrence; int substr_len = strlen( substring ); int move_len =
> strlen( string ) - substr_len + 1; /* +1 b/c of terminating '\0' */
> while ( occurrence = strstr( string, substring ) ) {
> memmove( occurrence, string + substr_len, move_len );
> }
> return string;
> }
>
> memmove() is used instead of memcpy(), because it handles overlapping
> copies.
>
> I hope that helps!
>
> Regards,
> Ekkehard Morgenstern.

 
Reply With Quote
 
Anupam
Guest
Posts: n/a
 
      11-14-2003
"Ekkehard Morgenstern" <(E-Mail Removed)> wrote in message news:<bp1gfj$ssc$(E-Mail Removed)>...
> Hi tuchka,
>
> "tuchka" <(E-Mail Removed)> schrieb im Newsbeitrag
> news:(E-Mail Removed) om...
> > 1. removes first substring from the string (i made it after
> > corrections of the function that i had in the horrible book:
> > 2. finds rightmost index of the substring (returns -1 if not found):

>
> Check out the functions declared in "string.h".
>
> Here's a function to remove all occurrences of "substring" from "string":
>
> #include <string.h>
>
> char* strstr_rem_all( char* string, const char* substring ) {
> char* occurrence; int substr_len = strlen( substring ); int move_len =
> strlen( string ) - substr_len + 1; /* +1 b/c of terminating '\0' */
> while ( occurrence = strstr( string, substring ) ) {
> memmove( occurrence, string + substr_len, move_len );
> }
> return string;
> }
>
> memmove() is used instead of memcpy(), because it handles overlapping
> copies.


Isn't there something a bit weird here.
Be careful abt how much you are moving ... the length of the initial
string - that of the substring +1 . This does not change inside the
loop but each time the string gets shorter.

What about this ? It should work.

char* strstr_rem_all( char* string, const char* substring ) {
char* occurrence;
int substr_len = strlen( substring );
int move_len;
while ( occurrence = strstr( string, substring ) ) {
move_len = strlen( occurrence ) - substr_len + 1;
memmove( occurrence, occurrence + substr_len, move_len );
}
return string;
}

>
> I hope that helps!
>
> Regards,
> Ekkehard Morgenstern.

 
Reply With Quote
 
Ekkehard Morgenstern
Guest
Posts: n/a
 
      11-14-2003
Hi tuchka,

I didn't test my code before posting it, because I assumed you'd be having
some thought about it before using it, but yeah, there's an obvious bug in
it:

"tuchka" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed) om...
> > #include <string.h>
> >
> > char* strstr_rem_all( char* string, const char* substring ) {
> > char* occurrence; int substr_len = strlen( substring ); int

move_len =
> > strlen( string ) - substr_len + 1; /* +1 b/c of terminating '\0' */
> > while ( occurrence = strstr( string, substring ) ) {
> > memmove( occurrence, string + substr_len, move_len );
> > }
> > return string;
> > }


Instead of "memmove( occurrence, string + substr_len, move_len )", it should
read "memmove( occurrence, occurrence + substr_len, move_len )", of course.


Regards,
Ekkehard Morgenstern.


 
Reply With Quote
 
Ekkehard Morgenstern
Guest
Posts: n/a
 
      11-14-2003
Hi tuchka,

Sorry this didn't work either.

"Ekkehard Morgenstern" <(E-Mail Removed)> schrieb im
Newsbeitrag news:bp2hl0$oas$(E-Mail Removed)...
> Instead of "memmove( occurrence, string + substr_len, move_len )", it

should
> read "memmove( occurrence, occurrence + substr_len, move_len )", of

course.

Anupam was right, I moved too much.

Here's a complete test program that works:

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

char* strstr_rem_all( char* string, const char* substring ) {
char* occurrence; int substr_len = strlen( substring );
while ( occurrence = strstr( string, substring ) ) {
int move_len = strlen( occurrence ) - substr_len + 1; /*
+1 b/c of terminating '\0' */
memmove( occurrence, occurrence + substr_len, move_len );
}
return string;
}

int main( int argc, char** argv ) {
if ( argc >= 3 ) {
printf( "string = '%s', substr = '%s'\n", argv[1],
argv[2] );
strstr_rem_all( argv[1], argv[2] );
printf( "result = '%s'\n", argv[1] );
}
return 0;
}

Notice that the first argument in strstr_rem_all() must point to modifyable
memory, like a string buffer like argv[1]. If you let it point to a constant
(string literal), you will get an access violation error.

I hope this helped!

Regards,
Ekkehard Morgenstern.


 
Reply With Quote
 
Ekkehard Morgenstern
Guest
Posts: n/a
 
      11-14-2003
Hi Anupam,

"Anupam" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed) om...
> char* strstr_rem_all( char* string, const char* substring ) {
> char* occurrence;
> int substr_len = strlen( substring );
> int move_len;
> while ( occurrence = strstr( string, substring ) ) {
> move_len = strlen( occurrence ) - substr_len + 1;
> memmove( occurrence, occurrence + substr_len, move_len );
> }
> return string;
> }


Yup, you're right!

I didn't test the code beforehand, and it was late! I posted a complete test
program now for tuchka in the other branch of the message tree.

Coincidentially we have the same solution, I guess there's not many ways to
do it right!

Regards,
Ekkehard Morgenstern.


 
Reply With Quote
 
tuchka
Guest
Posts: n/a
 
      11-14-2003
Thank you very much Ekkehard and Anupam! It works!
I see that I need to get better book. When I tried to re-write
'memmove'
function (i looked it up in internet) for some reason i did not notice
that type of
arguments were 'void'. I thought it arrays. 'void' does not make much
sense to me. I am lacking
essential information, i see that much. One last small question.

When i place the function directly into the program and call it from
'main' it works like a charm,
but when i put it into 'library' file (that is with asossiated header
file) and call it from test
program it gives the following:

////////////////////////////////////////////////////

After removing first fart became 123456fart678fart
After removing all fart became 123456678
Exiting due to signal SIGSEGV
General Protection Fault at eip=0000767e
eax=00000000 ebx=00000000 ecx=ffffffff edx=ffffffff esi=ffffffff
edi=ffffffff
ebp=00090390 esp=0008ef6c
program=C:\SVETA\C_PROG~1\STRING~1\STR_TEST.EXE
cs: sel=01a7 base=029a0000 limit=0009ffff
ds: sel=01af base=029a0000 limit=0009ffff
es: sel=01af base=029a0000 limit=0009ffff
fs: sel=017f base=00005a50 limit=0000ffff
gs: sel=01bf base=00000000 limit=0010ffff
ss: sel=01af base=029a0000 limit=0009ffff
App stack: [00090560..00010560] Exceptn stack: [000104c0..0000e580]

Call frame traceback EIPs:
0x0000767e
0x00003896
0x00001942
0x000033d8
////////////////////////////////////////////////////

I'm using gcc compiler and link like this:
gcc -c -g strutil.c

gcc -c -g str_test.c

gcc -o str_test.exe str_test.o strutil.o


What it can be? Maybe my compiler or my computer?
Do you have any ideas?

Thanks once again for your help. I'm going for a new book right away.

 
Reply With Quote
 
Ekkehard Morgenstern
Guest
Posts: n/a
 
      11-14-2003

Hi tuchka,

"tuchka" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed) om...
> When i place the function directly into the program and call it from
> 'main' it works like a charm,
> but when i put it into 'library' file (that is with asossiated header
> file) and call it from test
> program it gives the following:


I don't know what you're doing, but it could be that you used a string
literal for both parameters like:

strstr_rem_all( "123123abc123abc", "abc" );

This will cause an access violation, since the function assumes that the
first parameter is a buffer, not a constant.

It will be better to declare the function such that it returns no pointer.
This way you'll have to provide a buffer to get the result:

void strstr_rem_all( char* string, const char* substring ) {
char* occurrence; int substr_len = strlen( substring );
while ( occurrence = strstr( string, substring ) ) {
int move_len = strlen( occurrence ) - substr_len + 1; /* +1 b/c
of terminating '\0' */
memmove( occurrence, occurrence + substr_len, move_len );
}
}

btw, the "void*" in memmove() and memcpy() mean that these parameters can be
assigned any pointer value. Note that "void" is not the same as "void*".

I hope this helps.

Regards,
Ekkehard Morgenstern.


 
Reply With Quote
 
tuchka
Guest
Posts: n/a
 
      11-14-2003
Thank you, Ekkehard,
i see that i need to read regular text book not a 'bible' that i have,
to understand many concepts clearly. All my troubles are originating
from the fact that i don't know what i'm doing I just bought two
books for beginners and going to study it.
Your input was most helpful.

Cheers,
tuchka


"Ekkehard Morgenstern" <(E-Mail Removed)> wrote in message news:<bp35do$tmf$(E-Mail Removed)>...
> Hi tuchka,
>
> "tuchka" <(E-Mail Removed)> schrieb im Newsbeitrag
> news:(E-Mail Removed) om...
> > When i place the function directly into the program and call it from
> > 'main' it works like a charm,
> > but when i put it into 'library' file (that is with asossiated header
> > file) and call it from test
> > program it gives the following:

>
> I don't know what you're doing, but it could be that you used a string
> literal for both parameters like:
>
> strstr_rem_all( "123123abc123abc", "abc" );
>
> This will cause an access violation, since the function assumes that the
> first parameter is a buffer, not a constant.
>
> It will be better to declare the function such that it returns no pointer.
> This way you'll have to provide a buffer to get the result:
>
> void strstr_rem_all( char* string, const char* substring ) {
> char* occurrence; int substr_len = strlen( substring );
> while ( occurrence = strstr( string, substring ) ) {
> int move_len = strlen( occurrence ) - substr_len + 1; /* +1 b/c
> of terminating '\0' */
> memmove( occurrence, occurrence + substr_len, move_len );
> }
> }
>
> btw, the "void*" in memmove() and memcpy() mean that these parameters can be
> assigned any pointer value. Note that "void" is not the same as "void*".
>
> I hope this helps.
>
> Regards,
> Ekkehard Morgenstern.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Strings, Strings and Damned Strings Ben C Programming 14 06-24-2006 05:09 AM
Struggling with Wireless network. =?Utf-8?B?T0MxMQ==?= Wireless Networking 3 06-09-2005 07:15 PM
struggling at starting blocks getting workgroup recognised =?Utf-8?B?Q2Fyb2wgQg==?= Wireless Networking 2 02-13-2005 10:33 PM
Struggling With Concept One Handed Man \( OHM#\) ASP .Net 1 06-12-2004 02:07 PM
enableSessionState - still struggling Martin ASP .Net 6 12-29-2003 03:30 PM



Advertisments