# A little help with string manipulation

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 11-04-2005
InvertedSaint
A little help with string manipulation
Basically, what I'm trying to do is take a line of text from the user as input, then spew it back, but with "I am" replaced with "You are". There are a few printf's in here that are just there to show me what my own program is doing, for debugging purposes, but I can't seem to get this code working with more than one "I am" in the input, even though it should. I know there are some things I could be doing more efficiently, so if you see them, please point them out.

Please have a look and tell me what you think I should change. Thanks in advance :)

Code:

```#include <stdio.h> #include <string.h> char    recent[99]; int main(void) {     int    i, q[3], w = 0, x, b[3];         /* Set arrays to zero */     for (i = 0; i <= 99; ++i) {         recent[i] = -1;     }     for (i = 0; i <= 3; ++i) {         q[i] = -1;         b[i] = 0;     }         /* Get a string from the user, then check for 'I' */     fgets(recent, 100, stdin);     recent[(strlen(recent) - 1)] == '\0';     for (i = 0; i <= 99; ++i) {         if (recent[i] == 'I') {             q[w] = i;             ++w;         }     }         /* Check to see if 'I' is followed by ' am' */     for (i = 0; i <= 3; ++i) {         if (recent[(q[i] + 1)] == ' ') {             if (recent[(q[i] + 2)] == 'a') {                 if (recent[(q[i] + 3)] == 'm') {                     printf("\nq[%i] is an \"I am\" statement.", i);                     b[i] = 1;                 }             }         }     }         /* Replace 'I am' with 'You are' */     for (i = 0; i <= 3; ++i) {         if (b[i] == 1) {             for (x = 99; x >= q[i]; --x) {                 recent[(x + 3)] = recent[x];             }             recent[(q[i])] = 'Y';             recent[(q[i] + 1)] = 'o';             recent[(q[i] + 2)] = 'u';             recent[(q[i] + 3)] = ' ';             recent[(q[i] + 4)] = 'a';             recent[(q[i] + 5)] = 'r';             recent[(q[i] + 6)] = 'e';         }     }         printf("\n\nq[0] = %i\nq[1] = %i\nq[2] = %i\nq[3] = %i\n", q[0], q[1], q[2], q[3]);     printf("\n\nb[0] = %i\nb[1] = %i\nb[2] = %i\nb[3] = %i\n", b[0], b[1], b[2], b[3]);         /* Print final text */     printf("\n%s\n", recent);         /* System pauses */     printf("\n");     system("PAUSE");     return 0; }```
• 11-04-2005
Ancient Dragon
use strstr() function to check for string "I am".
Code:

```char* ptr; while( (ptr = strstr(recent,"I am")) != NULL) {   // replace stirng here   char tmp[100];   // copy string starting after "I am"   strcpy(tmp,ptr + 4);   // truncate remainder of string in original buffer   *ptr = 0;   // add "You are"   strcat(recent,"You are");   // add back original string   strcat(recent,temp); }```

also this line needs assignment operator '=', not logical operator "=="
Code:

`recent[(strlen(recent) - 1)] == '\0';`
• 11-04-2005
InvertedSaint
Thank you. I will make these adjustments and see if I can get the code to work fully now :)

EDIT: Yep, it works. Thanks for that. I'm gonna change it a little so that if the "You are" doesn't start the scentence, it's not uppercase. I'll post the code here when I'm done, just for future refference :)

Code:

```#include <stdio.h> #include <string.h> int main(void) {     int    i;     char    recent[99], temp[99];     char*  ptr;         /* Set arrays to zero */     for (i = 0; i <= 99; ++i) {         recent[i] = 0;         temp[i] = 0;     }         /* Get a string from the user and strip newline */     fgets(recent, 100, stdin);     recent[(strlen(recent) - 1)] = '\0';         /* Find "I am" and replace with "You are" */     while ((ptr = strstr(recent, "I am")) != NULL) {         strcpy(temp, ptr + 4);         *ptr = 0;         strcat(recent, "you are");         strcat(recent, temp);     }         /* Check if "y" begins scentence */     if (recent[0] == 'y') {         recent[0] = 'Y';     }         /* Print final text */     printf("\n%s\n", recent);         /* System pauses */     printf("\n");     system("PAUSE");     return 0; }```

Thanks again. The strstr() function wasn't under the strings tutorial, so I had no idea it existed, but I've had a bit of a muck around with it now. :)
• 11-04-2005
Ancient Dragon
here is another example of how to do it without using a temporary variable. just shift all characters right (or left) to expand (or contract) the string, making more (or less) space to add the new string
Code:

```int main() {   char recent[100] = "Hello I am the one I am the two";   char* search_string = "I am";   char* replace_string = "you are";   char* ptr;   int delta_len = strlen(replace_string) - strlen(search_string);   while ((ptr = strstr(recent, search_string)) != NULL) {             // width the string by 1 character.  This could either             // make the string longer or shorted, dependong on the             // size of each of the two strings         memmove(ptr+delta_len,ptr,strlen(ptr)+1);                 // copy new text         memcpy(ptr,replace_string,strlen(replace_string));     }         return 0; }```
• 11-04-2005
Dave_Sinkula
AD: you've got some issues when the replacement string is shorter that the search string.
• 11-04-2005
quzah
You've also got issues in that memmove doesn't allocate any space, so your "making it longer" doesn't really do that. All you do is move stuff around. You're screwed if your initial buffer isn't big enough to handle all of the replacements.

Quzah.
• 11-04-2005
Ancient Dragon
Quote:

Originally Posted by quzah
You've also got issues in that memmove doesn't allocate any space, so your "making it longer" doesn't really do that. All you do is move stuff around. You're screwed if your initial buffer isn't big enough to handle all of the replacements.

Quzah.

yes, its true that memmove doesn't allocate space, but it doesn't have to. The space is already allocated. The algorithm is making the null-terminated string longer, not changing the size of the buffer. The danger with memmove(), memcpy(), strcpy() and most other C string handling fucntions is that they make no sanity checks for buffer overflow, which is why I always make the destination buffer somewhat larger than actually needed. You will notice in the posted program the destination buffer is 100 bytes, sufficent size for the strings in the OPs program. Adjust the size of the destination buffer as needed to accommodate larger strings.

Dave: It worked ok on the strings I tested. Just make the replacement string shorter than the search string. I didn't notice any problems with the end result, but there might be with some other strings or when the search string appears at the beginning of the buffer.

And for the benefit of new programmers, neither altorithm I posted works with string literals because the length of those strings cannot be changed.
• 11-04-2005
Dave_Sinkula
Code:

```#include <stdio.h> #include <string.h> int main() { #if 0   char recent[100] = "Hello I am the one I am the two";   char* search_string = "I am";   char* replace_string = "you are"; #else   char recent[100] = "Hello you are the one you are the two";   char* search_string = "you are";   char* replace_string = "I am"; #endif   char* ptr;   int delta_len = strlen(replace_string) - strlen(search_string);   puts(recent);   while ( (ptr = strstr(recent, search_string)) != NULL )   {       // width the string by 1 character.  This could either       // make the string longer or shorted, dependong on the       // size of each of the two strings       memmove(ptr+delta_len,ptr,strlen(ptr)+1);       // copy new text       memcpy(ptr,replace_string,strlen(replace_string));   }   puts(recent);   return 0; } /* my output Hello you are the one you are the two HelyouI am the oyouI am the two */```
• 11-04-2005
Ancient Dragon
this will fix it
Code:

```  while ( (ptr = strstr(recent, search_string)) != NULL )   {       // width the string by 1 character.  This could either       // make the string longer or shorted, dependong on the       // size of each of the two strings           if(delta_len > 0)           {                         memmove(ptr+delta_len,ptr,strlen(ptr)+1);                         // copy new text                         memcpy(ptr,replace_string,strlen(replace_string));           }           else           {                         memmove(ptr,ptr-delta_len,strlen(ptr-delta_len)+1);                         // copy new text                         memcpy(ptr,replace_string,strlen(replace_string));           }   }```
• 11-04-2005
dwks
Code:

```int main(void) {     int    i;     char    recent[99], temp[99];     char*  ptr;         /* Set arrays to zero */     for (i = 0; i <= 99; ++i) {         recent[i] = 0;         temp[i] = 0;     }```
• 11-04-2005
dwks
Is it better to use memcpy over memmove when the buffers will not overlap? Is memcpy faster?
• 11-04-2005
Ancient Dragon
if you know the buffers do not overlap then memcpy is ok, and faster too.

This is also a lot faster way to clear buffers because it does not involve c loops. As noted by someone else a while back this is not such a good thing to do with integer or float arrays.
Code:

```int main(void) {     int    i;     char    recent[99], temp[99];     char*  ptr;     memset(recent,0,sizeof(recent));     memset(temp,0,sieof(temp));```
• 11-04-2005
dwks
That's what I thought (about memcpy). Thanks.

Quote:

this is not such a good thing to do with integer or float arrays.
I think it's okay if you're setting it to zero. Isn't it?

BTW, you have sieof instead of sizeof. :)
• 11-04-2005
dwks
Couldn't you just go like this?
Code:

`char recent[99] = {0};`
• 11-04-2005
Dave_Sinkula
Quote:

Originally Posted by dwks
I think it's okay if you're setting it to zero. Isn't it?

http://www.eskimo.com/~scs/C-faq/q7.31.html
Quote:

The zero fill is all-bits-zero, and does not therefore guarantee useful null pointer values or floating-point zero values.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last