Hi guys,

This exercise goes as follows:
- Write a function that counts the number of occurences of a pair of letters in a string and another that does the same in a zero-terminated array of char(a C-style string). For example, the pair "ab" appears twice in "xabaacbaxabb".

Now, I found the following solution to the C-style version:

#include <iostream>

void compareChar(char *myArr, char *mySecArr);

int main()
{	
	char mychar[] = "xabaacbaxabb";
	char letters[2];

	compareChar(mychar, letters);
	
	std::cin.ignore(2);

	return 0;
}

void compareChar(char *myArr, char *mySecArr)
{
	int count = 0;

	std::cout << "Enter two letters to be compaired with the char string 'xabaacbaxabb'" << std::endl;

	std::cin >> mySecArr;
	
	while(strlen(mySecArr) != 2)
	{
		std::cout << "Wrong amount of letters, try again!" << std::endl;
		std::cin >> mySecArr;
	}

	for (int i = 0; myArr[i] != 0; i++)
	{
		if((myArr[i] == mySecArr[0]) && (myArr[i+1] == mySecArr[1]))
			count++;
	}

	std::cout << "The pair '" << mySecArr << "' appears " << count << " time(s) in " << myArr << "." << std::endl;
}

I was wondering if any of you could tell me how I can improve this, the reason for asking is that at the end of the last comparison if((myArr[i] == mySecArr[0]) && (myArr[i+1] == mySecArr[1])) the myArr[i+1] goes out of bound. Isn't that bad coding?

Recommended Answers

All 14 Replies

Member Avatar for iamthwee

Anything that goes beyond scope is naughty.

Jobe, my very first reaction would be, why not write a generic function instead of restricting yourself with search strings of length 2 or 3.

goes out of bound. Isn't that bad coding?

Its not bad coding, its wrong coding. How can you expect your program to perform properly and in the right manner if you are basing your programming logic on computations on areas of memory which don't belong to you ?

Also the trick which you use will soon turn out to be cumbersome if you are asked to do the same with 3 letters, 4 letters, n letters etc.

My thoughts: always look for generic patterns in the problem statement and if they don't incur additional overheads for that case, go ahead and implement them.

For eg here is one implementation which is possible. I haven't tried it but it should pretty much work.

// retuns the last position in the string where the match was found
// modifies the count parameter passed by reference which displays the
// number of times substring occurs.
int my_strstr( const char* str1, const char* str2, int* count )
{
    int i = 0 ;
    int len1 = strlen( str1 ) ;
    int len2 = strlen( str2 ) ;
    int pos = 0 ;

    *count = 0 ;    // initialize the counter

    for( i = 0; i < len1; ++i )
    {
        if( strncmp( ( str1 + i ), str2, len2 ) == 0 )
        {
            (*count)++ ;
            pos = i ;
        }
    }
    return pos ;
}

int main( void )
{
    int count ;
    char str[] = "ababababa" ;
    char search_str[] = "ab" ;
    int match = my_strstr( str, search_str, &count ) ;
    printf( "The last occurance of \'%s\' was found in \'%s\' at %d.",
                                                str, search_str, match ) ;
    printf( "\nThe count of \'%s\' is %d.", search_str, count ) ;
    getchar( ) ;

    return 0 ;
}

You can change the function so that you get it to return the char pointer rather than returning position or you can make the function do both by keeping its prototype as: char* my_strstr( const char* str1, const char* str2, int* count, int* pos ) which makes the function return char pointer to the substring found as well as modifies the parameters passed to it to reflect the count of substring as well as the position of the last substring.

Hope it helped, bye.

Hmmm, well, I came up with this int strLength = strlen(myArr)-1; and then in the loop for (int i = 0; i < strLength; i++) but I see where you're coming from :o

Thanks for the example, I'll see that I can find an equivalent to use in my program next week-end.

Hmmm, well, I came up with this int strLength = strlen(myArr)-1; and then in the loop for (int i = 0; i < strLength; i++) but I see where you're coming from :o

Thanks for the example, I'll see that I can find an equivalent to use in my program next week-end.

I would reverse the -1 and go with: int strLength = strlen(myArr); and for (int i = 0; i < strLength-1; i++) The reason is strLength actually represents the string length, which you can modify in the loop. And you can still use strLength elsewhere in your program if the need arises. By subtracting 1 first, it's really only useful for this particular part of the program.

I would reverse the -1 and go with: int strLength = strlen(myArr); and for (int i = 0; i < strLength-1; i++) The reason is strLength actually represents the string length, which you can modify in the loop. And you can still use strLength elsewhere in your program if the need arises. By subtracting 1 first, it's really only useful for this particular part of the program.

Yep, that seems to make better sence, thanks Walt.

Hi guys,

Solved the exercise, but, I'm not that happy with it because both functions actually look very similar, meaning, the c-style string and the cpp string. Don't think that was the idea of this exercise.

//Exercises from the book: The C++ Programming Language by Bjarne Stroustrup.

/*Write a function that counts the number of occurences of a pair of letters in a string and
  another that does the same in a zero-terminated array of char(a C-style string). For example,
  the pair "ab" appears twice in "xabaacbaxabb".
  */

#include <iostream>
#include <string>

int compareChar(char *myArr, char *mySecArr);
int compareString(std::string myWord, char mySecArr[2]);

int main()
{	
	char mychar[] = "xabaacbaxabba";
	char letters[2];
	std::string myWord;

	myWord = mychar;

	std::cout << "Enter two letters to be compaired with the char string '" << mychar << "'" << std::endl;
	
	std::cin >> letters;

	int count = compareChar(mychar, letters);
	std::cout << "The pair '" << letters << "' appears " << count << " time(s) in " << mychar << "." << std::endl;

	std::cout << "Enter another two letter to be compaired with the string string '" << myWord << "'" << std::endl;

	std::cin >> letters;

	count = compareString(myWord, letters);
	std::cout << "The pair '" << letters << "' appears " << count << " time(s) in " << myWord << "." << std::endl;

	std::cin.ignore(2);

	return 0;
}

int compareChar(char *myArr, char *mySecArr)
{
	int count = 0;

	for (int i = 0; i < strlen(myArr)-1; i++)
	{
		if((myArr[i] == mySecArr[0]) && (myArr[i+1] == mySecArr[1]))
			count++;
	}

	return count;
}

int compareString(std::string myWord, char mySecArr[2])
{
	int count = 0;
	
	for (int i = 0; i < myWord.size()-1; i++)
	{
		if ((myWord[i] == mySecArr[0]) && (myWord[i+1] == mySecArr[1]))
			count++;
	}

	return count;
}

Is there a better way to compare a character array with a cpp string?

Maybe the C++ version was supposed to use .find()?

This is enough room for one character plus the terminating null:

char letters[2];

Is there a better way to compare a character array with a cpp string?

There are other ways, but not necessarily better. For just two characters yours way is efficient. If you had to test 4 or more, a loop might be better.

There are also the C-string str???() functions and C++ strings compare methods. Either of those you can look into.

Maybe the C++ version was supposed to use .find()?

HI Dave, long time no see, I see you lost your mod stick, good to see you here again though :)

I tried using .find() and .compare(), but it seems that they can only be used to find if there is A resemblance of code in both strings, not several. Could it be that I have to write it in a way it traverses threw the string that I want to compare? If so, I can only traverse threw one by using a loop and either string[i] or *(string + i) right ?

This is enough room for one character plus the terminating null:
char letters[2];

DARN, I forgot the terminating null, it does work though, I'll change it to [3] and add the '\0' at the back, thanks for the tip.

There are other ways, but not necessarily better. For just two characters yours way is efficient.

Oh, ok, thanks.

If you had to test 4 or more, a loop might be better.

Nope, don't understand that, I thought I was using a loop?

There are also the C-string str???() functions and C++ strings compare methods. Either of those you can look into.

Thought so, thing is, as said above, how do I use .find() and/or .compare() when having to go threw the whole string when trying to find more then one occurence of the same piece of string?

Member Avatar for iamthwee

how do I use .find() and/or .compare() when having to go threw the whole string when trying to find more then one occurence of the same piece of string?

http://www.cprogramming.com/tutorial/string.html

commented: Great link provided! +3

iamthwee, thank you very much for that link :!:

Made this from the example you gave:

for (size_t i = myWord.find(mySecArr, 0); i != std::string::npos; i = myWord.find(mySecArr, i))
	{
		count++;
		i++;		// Move past the last discovered instance to avoid finding same string.
	}

The i++; is really necessary, otherwise the loop just keeps on going, am I correct that as the text stated, when not using this, the string never fails finding the char and therefore i != std::string::npos; (search failes) is never reached?

HI Dave, long time no see, I see you lost your mod stick, good to see you here again though :)

My choice.

Here was my tinkerings:

int compareChar(char *myArr, char *mySecArr)
{
   int count = 0;
   size_t len = strlen(mySecArr);
   while ( (mySecArr = strstr(myArr, mySecArr)) != NULL )
   {
      count++;
      mySecArr += len;
   }
   return count;
}

int compareString(std::string myWord, char *mySecArr)
{
   int count = 0;
   std::string::size_type i = 0;
   size_t len = strlen(mySecArr);
   while ( (i = myWord.find(mySecArr, i)) != std::string::npos )
   {
      i += len;
      count++;
   }
   return count;
}

Hmm...I think there is some typo mistakes in the above one posted by Mr. Dave.

int compareChar(char *myArr, char *mySecArr)
{
   int count = 0;
   size_t len = strlen(mySecArr);

   // mySecArr should be myArr
   while ( (mySecArr = strstr(myArr, mySecArr)) != NULL )

   {
      count++;
      // mySecArr should be myArr
      mySecArr += len;
   }
   return count;
}
commented: Sharp eyes. :) --joeprogrammer +4

Hmm...I think there is some typo mistakes in the above one posted by Mr. Dave.

Indeed. :o

int compareChar(char *myArr, char *mySecArr)
{
   int count = 0;
   size_t len = strlen(mySecArr);
   while ( (myArr = strstr(myArr, mySecArr)) != NULL )
   {
      count++;
      myArr += len;
   }
   return count;
}

Too many projects lying around for the same purpose; must consolidate.

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.