I wrote a function that will search a string with a substring. When the substring is found, it is replaced with another substring. The problem I have with my code is that it wont replace the substring unless it is in the beginning of the string. Here's the code and thanks for the help!

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

int length(char str[])
{
	int i=0;
	while(str[i] != '\0')
	{
		i++;
	}
	return i;
}

int substring(char str1[], char str2[], char str3[])
{
	int len = length(str1);
	int len2 = length(str2);
	int len3 = length(str3);
	
	if(len2 != len3)
	{
		cout << "ERROR: The find and replace strings are of different length." << endl;
		cout << "Please change the find and replace strings to the same length." << endl;
		return false;
	}

	for (int i= 0; i <=9; i++)
	{
		for (int j = 0; j <= (str1[i] -1); j++)
		{
			if (str1[j] == str2[0]) 
			{
				bool found = true;
				int k = 0;
				
				while (k < (len2) and found==true) 
				{
					if (str2[k] == str1[k])
						k++;
					else
						found = false; 
				}

          		if (found == true) 
				{
					char templine[10];
                    templine[i] = str1[i]; 
					int temp=0;

         			for (int m = j; m <= (len2-1); m++ )
					{
						str1[m] = str3[temp];
						temp++;
					}

					int temp2 = j+(len3);
					int test = (length(templine)-1);
					for (int n = (j+len2); n <= test; n++)
					{
						str1[temp2] = templine[n];
						temp2++;
					}
				}

			}
		}
	}
    return 0;
}

int main ()
{
	char array[]="stupid";
	char array2[]="up";
	char array3[]="hi";
	substring(array, array2, array3);
	cout << "array: " << array <<endl;
	system("PAUSE");
	return 0;
}

Recommended Answers

All 6 Replies

1) It shouldn't matter if the length of the search string is the same as the replacement string. When the search string is found, copy the original string up to the beginning of the search string, then append the destination string, finally move the pointer past the end of the search string in the source string and append the remainder of the source string.

Example: NOTE: I didn't compile or test this, so it could contain one or more bugs. But the algorithm should be ok. I used strcpy(), strcat() and strlen() for brievity, but you may have to use your own functions in your assignment if that is what your prof required.

char temp[255] = {0};
char source[] = "Once upon a time there were three little pigs";
char search[] = "time";
char replace[] = "How now brown cow";
char *ptr1 = 0;
char *ptr2 = 0;
// find the search string in the source string
ptr1 = source;
while(*ptr1)
{
     if( *ptr1 == search[0] )
     {
           int i = 0, j = 0;
           while( search[i] && ptr1[j] == search[i])
           {
               i++;
               j++;
           }
           if( search[i] == 0) // end of search string, then we found it
           {
               *ptr1++ = 0; // truncate source string at point of search string
               strcpy(temp,   source ); // copy 1st part of source string
               strcat(temp, replace );  // add the replace string
               ptr1 += strlen(search) // advance past end of the search string
               strcat(temp,ptr1); // add rest of source string
           }
      }
      ptr1++;
}

To be honest, I didn't test Ancient's example, so it might work very good (although I see a small syntax error in it ;) ). But I also see that you #include <string> , so you are aware that C++ has a few nice tricks up it sleeve that C didn't have, right?

So if we would use std::strings and stringstreams, your code would look a lot simpler:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    string source = "Once upon a time there were three little pigs";
    string search = "time";
    string replace = "How now brown cow";
    string buffer = "";

    stringstream replaced("");
    stringstream original(source);

    while (original >> buffer)
    {
        if (buffer == search) replaced << replace << " ";
        else replaced << buffer << " ";
    }
    cout << replaced.str();
    return 0;
}
Output:
Once upon a How now brown cowthere were three little pigs
commented: your solution is much better than mine. :) +36

Yes, Niek, your solution is much better than mine. :)

Yes, Niek, your solution is much better than mine. :)

Thanks! Appreciate that coming from someone as experienced as yourself :)

Some remarks.
Regrettably, niek_e's solution is a solution of another problem. It can replace one word only, not an arbitrary substring.
Ancient Dragon's solution uses RTL library (not in spirit of original post, see length() function instead of strlen).

/// For this example only:
inline int length(const char* s)
{
    return s?strlen(s):0;
}
/* C-style solution w/o RTL */
/** Returns a pointer to unchanged string tail or 0 */
char* ReplaceOnce(char *str, const char* what, const char* to)
{
    int i, j, k, m, n, delta;
    int n1, n2, n3;
    char* p, *q;
    if (!str || !what)
        return 0;
    if (!to)
        to = "";
    n1 = length(str);
    n2 = length(what);
    n = n1 - n2 + 1;
    for (i = 0; i < n; ++i)
    {
        for (j = 0; j < n2 && what[j] == str[i+j]; ++j)
            ;
        if (j == n2) // found
        {
            n3 = length(to);
            delta = n3 - n2;
            m = n1 - i - n2;
            if (delta < 0) /* move left */
            {
                p = str + (i + n2 + delta);
                q = p - delta;
                for (k = 0; k <= m; ++k)
                    p[k] = q[k];
            }
            else if (delta > 0) /* move right */
            {
                q = str + n1 - m;
                p = q + delta;
                for (k = m; k >= 0; --k)
                    p[k] = q[k];
            }
            for (k = 0; k < n3; ++k)
                str[i+k] = to[k];
            return str + i + n3;
        }
    }
    return 0;
}
/** Echoes a pointer to a source string */
char* ReplaceAll(char* str, const char* what, const char* to)
{
    char* p = str;
    while ((p=ReplaceOnce(p,what,to)) != 0)
        ;
    return str;
}

C++ solution: why stringstreams?..

// Now C++ possible solution...
typedef std::string::size_type Pos;
const Pos EoS = std::string::npos;

char* CppReplaceOnce(char* str, const char* what, const char* to)
{
    if (!str || !what)
        return 0;
    if (!to)
        to = "";
    std::string sstr(str);
    std::string swhat(what);
    Pos pos = sstr.find(swhat);
    if (pos != EoS)
    {
        sstr.replace(pos,swhat.length(),to);
        return strcpy(str,sstr.c_str());
    }
    return 0;
}

char* CppReplaceAll(char* str, const char* what, const char* to)
{
    char* p = str;
    while ((p=CppReplaceOnce(p,what,to)) != 0)
        ;
    return str;
}

I tried something like this. So far it works perfect for me.
I don't use streams, the length() method was convenient enough

void strReplace(string &s, string oldstr, string newstr) {
	unsigned int count = 0;
	string 	buffer = "";
	for (unsigned int i = 0; i < s.length(); i++) {
		if (s[i] == oldstr[count]) {
			for (unsigned int j = 0; j < oldstr.length(); j++) {
				if (s[i+j] != oldstr[j]) break;
				count++;
			}
			if (count == oldstr.length()) {
				i += count - 1;
				count = 0;
				buffer += newstr;
			}
		} else {
			buffer += s[i];
		}
	}
	s = buffer;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.