C++ Recursive Search Function (school assignment) - c++

For my assignment I have to have two functions (a main function and a recursive helper function) and the purpose is to search for a string within a string then provide the index that string starts at. Example:
String: Hi I am a horse
String to search for: horse
Returns: 10
I have written a program that will do this, but the only problem is in my recursiveHelper function I check the next index by
return recursiveHelper(s.substr(1), t, ++count);
which my teacher informs me that string s should not be changed when calling the helper function. Can someone tell me why and also provide me a way to do it as I have been looking all weekend to not avail. Thanks!
Full program:
#include <iostream>
#include <string>
using namespace std;
// recursiveHelper function
// purpose: locate the first instance of the string t within the string s
// Parameters: string, string, int
// Returns: int
int recursiveHelper(string s, string t, int count)
{
// Length variables
int inputOneLength = s.length();
int inputTwoLength = t.length();
// Figure out the base case. Same format as lab10 really
if (inputOneLength < inputTwoLength)
{
return -1;
}
else
{
// Check the first index -- compare the strings character by character
if (s.substr(0, inputTwoLength) == t)
{
return count;
}
else
{
// Check the next index
return recursiveHelper(s.substr(1), t, ++count);
}
}
}//end of recursiveHelper
// index_of function
// purpose: locate the first instance of the string t within the string s
// Parameters: string, string
// Returns: int
int index_of(string s, string t)
{
// Initialize the count
int count = 0;
// Send to the helper
count = recursiveHelper(s, t, count);
return count;
}//end of index_of
int main()
{
// Variables
string inputOne = "";
string inputTwo = "";
// Prompt user input
cout << "This program will find the occurence of one string inside another." << endl;
cout << "\nEnter the string to be searched: ";
getline(cin, inputOne);
cout << "Now enter the string you want to search for: ";
getline(cin, inputTwo);
// Pass to index_of function
int index = index_of(inputOne, inputTwo);
// Output results
if (index != -1)
{
cout << "The index of substring is = " << index << endl;
}
else
{
cout << "Can't find this string." << endl;
}
system("PAUSE");
return 0;
}//end of main

Your teacher is wrong.
s is never changed!
here is the definition of string::substr()
string substr (size_t pos = 0, size_t len = npos) const;
the const keyword means the method doesn't change the object.
you always get a new string from the call tostring::substr()

Related

Array- looping through secondary array

Unable to get the index from the second array to match the first array
// array constants
const int people = 7;
const int phoneNumbers = 7;
int main() {
char person, family;
int index;
string found;
int size =7;
//array declaration and set values
string people [] ={"Darryl","Jasmine","Brian","Duane","Ayana","Mia","Maya"};
// const char phoneNumbers = 7;
string phoneNumbers[] = {"678-281-7649", "818-933-1158", "212-898-2022",
"361-345-3782","817-399-3750","313-589-0460","818-634-4660"};
//set boolean value
found = "False";
//initialize index
index = 0;
// search variable and user input
cout << "who are you looking for? " << endl;
cin >> people[index];
for (index=0; index<=6; index--) {
if (people[index] == people[index] )
cout << "phone num for " << people[index] << " is "<<
phoneNumbers[index] << endl;
}
return 0;
}
When I put in Jasmine which is the people[] array, the phoneNumbers[] array brings back the first index of phoneNumbers[] which it should bring back the second index on phoneNumbers[] array
There are two problems here.
You are replacing content of the people[0] with the cin - so first item of the array will be always user's input.
You are decrement index, so the FOR cycle goes to the indexes 0,-1,-2... This is problem as arrays in C and C++ goes from 0 to upper values.
I would prefer to add one variable:
string input;
then:
cin >> input;
for cycle should be used:
for (index = 0; index < 6; index++)
and in your condition I would use:
if (person[index] == input) ...
A much cleaner way of doing this would be too use std::map provided by the C++ standard template library. Below is my take on what you're trying to achieve:
// phoneNumber.cpp
#include <iostream>
#include <map>
int main()
{
// delcare a map variable that maps people's names to phone numbers
std::map <std::string,std::string> lookUpPhoneNumber = {
{"Darryl", "678-281-7649"},
{"Jasmine", "818-933-1158"},
{"Brian", "212-898-2022"},
{"Duane", "361-345-3782"},
{"Ayana", "817-399-3750"},
{"Mia", "313-589-0460"},
{"Maya", "818-634-4660"}
};
// take input name
std::string inputName;
// user prompt
std::cout << "who are you looking for?: ";
std::cin >> inputName;
// look up name in map
if(lookUpPhoneNumber.find(inputName) != lookUpPhoneNumber.end()){
std::cout << "Phone num for " << inputName << " is: " << lookUpPhoneNumber[inputName] << "\n";
} else{
std::cout << "Name does not exist!\n";
}
return 0;
}
To compile and run, use the following command:
g++ -std=c++11 -o phoneNumber phoneNumber.cpp
./phoneNumber
Or check your compiler option to enable compiling with c++11 standard or higher.

Sorting string array alphabetically in a 2D array (C++)

I have coded thus far and I am not sure how to sort using the 2-dimensional array. Basically, one function is for sorting an array of strings, another function is for swapping two strings. Any help would be appreciated. (Also I am not allowed to use c++ 11 :/)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void input_name(string&);
void sort_names(string&);
void repeat_pro(int&);
void sortArray(string, int);
int main() {
string b_list[100][2];
string name;
int choice;
int count=0;
cout << "Welcome to the Business Sorting Program!" << endl;
do{
input_name(name);
b_list[count][1] = name;
count++;
repeat_pro(choice);
cout<<"\n \n Your Businesses are:"<<endl;
for(int j=0; j<count; j++){
cout<<b_list[j][1]<<endl;
}
cout << "\n\n";
}while(choice == 0);
cout << "Thanks for using this program"<<endl;
return 0;
}
void input_name(string &name){
cout << "Enter in the name of the business: ";
getline(cin, name);
}
void sort_names(string &name){
}
void repeat_pro(int &choice){
cout << "Do you want to enter in more names: ";
string answ;
cin>>answ;
cin.ignore(1000,'\n');
if (answ == "YES" || answ == "Y" || answ == "yes" || answ == "y"){
choice = 0;
}
else {
choice = 1;
}
}
it is not clear to me from the description what problem the program really tried to solve. I'm assuming it's kind of like a two column spreadsheet, the second column is the name entered by the user(but what is in the first column?).
assume you need to keep the array in sorted order as the data goes in, just do a binary search (you can do a linear search for small dataset like 100 entries).
// we don't have lambda before C++11
struct comparator {
bool operator () (const string (&x)[2], const string (&y)[2]) const {
return x[1] < y[1];
}
};
//... omitted
string data[100][2];
int count = 0;
while (count < 100) {
// no rvalue, move, rvo, etc. before C++11
string name;
input_name(name);
// no type deduction and lambda
string (*position)[2] =
std::lower_bound(&data[0], &data[count], name, comparator());
int index = position - &data[0];
// simulate an vector::insert operation, but for our array
for (int i = count; i > index; --i) {
// before we had move in C++, we would do swap with an empty element.
// in this case, the entry at data[count] is default constructed
std::swap(data[i][1], data[i-1][1]);
}
data[index][1] = name;
}
//... omitted
of course we can use a typedef to make it cleaner, but that's left to you.

process is terminated due to StackOverflowException from bool function C++

I am trying to make a bool function that will allow an input of a string and the input of a substring to be searched in that string's input. The bool function should search recursively for a match, then return true if there is a match inside of the string. For example: 'word' is entered as the string, then 'or' is the substring I am looking for inside the string. The function should then return true since 'or' is inside 'word'. When I run the code, on the command line it will say, "process is terminated due to StackOverFlowException" I am confused as to what this error means and how it relates to my code.
#include <iostream>
#include <string>
using namespace std;
bool find(string s, string t)
{
if(s.length() <= 1){
return false;
}
int t_len = t.length() - 1;
string se = s.substr(0, t_len);
if(se == t){
return true;
}
else
s.erase(0,0);
return find(s, t);
}
int main()
{
string s;
string t;
cout << "Enter string s: " << endl;
cin >> s;
cout << "Enter string t: " << endl;
cin >> t;
bool is_found = find(s, t);
if(is_found = true)
{
cout << "Found: " << t << " in " << s << endl;
}
system("pause");
return 0;
}
Your call to erase is not deleting any characters. The definition of erase is:
erase( size_type index = 0, size_type count = npos );
So you want to erase 1 character, not 0 characters.
Additionally, your test at the end should read:
if(is_found == true)
as otherwise, you're trying to assign is_found the value true and test that value (which will always be true in that case.
Additionally, you have:
string se = s.substr(0, t_len);
where t_len is incorrect (off by one), so the string comparison will not work.
Fundamentally, it looks like you've not understood the definitions of erase or substr, which would be essential to getting this to work properly.

Searching substrings

I am a programming student. I have been asked to write a program that searches for a substring of another string, but I am not suppose to use the find() function that is provided in the string class. The code I have written thus far works, but it uses the find() function. How can I change this to not use the find function and still give me the location of the substring? Here is my code:
#include <iostream>
#include <string>
using namespace std;
int f_r(string, string);
int main()
{
string s;
string t;
cout << "\nEnter the string to be searched: ";
getline(cin,s);
cout << "Now enter the string you want to search for: ";
cin >> t;
if (f_r(s,t) == 0)
{
cout << "\n Substring could not be found.";
}
else
{
cout << "\nThe index of substring is = " << f_r(s,t) << endl;
}
system("PAUSE");
return 0;
}
int f_r(string str, string c)
{
int pos = 0;
pos = str.find(c, pos);
if (pos > str.length())
{
return 0;
}
else
{
pos++;
return pos - 1;
}
}
You need to search for matches within the string ONE character at a time, i.e. seeing the strings as if they were arrays of characters (since you're apparently working in C/C++ that is quite convenient since string and char[] are synonymous).
You will likely need to maintain indexes or pointers into the current location in both strings..
This will be the naive / initial approach, and when you get that working rather well, assuming you are a bit curious, you'll start wondering if there are more efficient ways of doing so, for example by skipping some characters in some cases, or by using general statistics about text in the underlying languages.
This art may help:
|_|_|_|_|_|_|_|_|_|_|_|
^ ^
i i+j
|
|_|_|_|_|
^
j
int search(char *a,char *b)
{
int i=0,j=0,k=0,m,n,pos;
m=strlen(a);
n=strlen(b);
while(1)
{
while((a[i]==b[j]) && b[j]!=0)
{
i++;
j++;
}
if (j==n)
{
pos=i-j;
return(pos);
}
else
{
i=i-j+1;
j=0;
}
}}
I have this code with me. I hope it will help you.
Note:- its an old code

Anagram generator for C++ (not using STL)

I am trying to create an anagram solver just using a very basic, procedural approach. I am finding out that I probably should have done this using classes, but now it is too late and my assignment is about due. Any suggestions on how to figure this out would be great!
Basically, this is what the algorithm should do:
Get all words in the dictionary; store them in a container
Get a word from the user; quit if appropriate
Get all permutations of the word that the user entered
Strip the word the user entered from the permutations
Strip all words in the permutation collection that aren't also in the dictionary I collected in part 1
Now for the last step, I must make sure that I don't display duplicate anagrams (i.e. anagrams which contain the same letter, such as "loop"). I cannot seem to get this check to work, which is noted below with under the TODO comment block.
Any suggestions would be awesome!!
#include <iostream>
#include <fstream>
#include <string>
//
// Change size below to accomodate more anagrams and dictionary words
//
#define MAX_ANGM_SIZE 4096
#define MAX_WORD_SIZE 1048576
using namespace std;
//
// Determines whether anagram is valid or not; will not display word
// which user entered or words not contained in dictionary
//
bool isValidAnagram(string word, string userWord,
string dictionary[], unsigned int listIdx)
{
for(unsigned int idx = 0; idx < listIdx; ++idx)
{
if(word == userWord)
return false;
else if (word == dictionary[idx])
return true;
}
return false;
}
//
// Determines whether user's word is contained in the dictionary
// or not
//
bool isValidWord(string word, string dictionary[],
unsigned int listIdx)
{
for(unsigned int idx = 0; idx < listIdx; ++idx)
{
if(word == dictionary[idx])
return true;
}
return false;
}
//
// TODO:This function should test for duplicate anagrams and return
// true if duplicates are found.
//
bool isRepeated(string anagrams[], unsigned int anaIdx)
{
for(unsigned int idx = anaIdx; idx != 0; --idx)
{
if(anagrams[idx] == anagrams[anaIdx])
return true;
else
return false;
}
return false;
}
//
// Only display elements in array which aren't blank and don't
// display duplicate anagrams; notify user if no anagrams
// were found.
//
void displayAnagrams(string anagrams[], unsigned int next)
{
int flag = 0;
for (unsigned int idx = 0; idx < next; ++idx)
{
if((anagrams[idx] != "") || (!(isRepeated(anagrams, idx))))
{
if(idx == 1)
cout << " Anagrams: ";
if(idx > 0)
flag = 1;
cout << anagrams[idx] << " ";
}
else
continue;
}
if(flag == 0)
cout << " no anagrams found" << endl;
}
static void swap(char &c1, char &c2)
{
char temp = c1;
c1 = c2;
c2 = temp;
}
//
// Pass in word to be altered, the userWord for comparison, the array to store
// anagrams, the dictionary for comparison, the count for the number of anagrams
// and the count for number of dictionary words
//
static void permute(string word, string userWord, int k, string anagrams[],
string dictionary[], unsigned int &next, unsigned int listIdx)
{
if(k == word.length()-1)
{
if(isValidAnagram(word, userWord, dictionary, listIdx))
anagrams[next] = word;
++next;
}
else
{
for(int idx = k; idx < word.length(); ++idx)
{
swap(word[k], word[idx]);
permute(word, userWord, k+1, anagrams, dictionary, next, listIdx);
}
}
}
//
// Create container to store anagrams, validate user's word in dictionary, get all
// of the anagrams, then display all valid anagrams
//
void getAnagrams(string word, string dictionary[], unsigned int listIdx)
{
string anagrams[MAX_ANGM_SIZE];
unsigned int next = 0;
if(isValidWord(word, dictionary, listIdx))
{
permute(word, word, 0, anagrams, dictionary, next, listIdx);
}
else
{
cerr << " \"" << word << "\"" << " is not a valid word" << endl;
return;
}
displayAnagrams(anagrams, next);
}
//
// Read in dictionary file, store contents of file in a list, prompt
// the user to type in words to generate anagrams
//
int main()
{
string file;
string word;
string quit = "quit";
string dictionary[MAX_WORD_SIZE];
unsigned int idx = 0;
cout << "Enter a dictionary file: ";
cin >> file;
cout << "Reading file \"" << file << "\"" << endl;
cout << endl;
ifstream inFile(file.c_str());
if(!(inFile.is_open()))
{
cerr << "Can't open file \"" << file << "\""
<< endl;
exit(EXIT_FAILURE);
}
while(!inFile.eof())
{
inFile >> dictionary[idx];
++idx;
}
inFile.close();
while(true)
{
cout << "Enter a word: ";
cin >> word;
if(word == quit) break;
getAnagrams(word, dictionary, idx);
cout << endl;
}
return 0;
}
You may want to rethink your step (3). If the user enters a 12-letter word you have 479,001,600 permutations of it which will probably be impractical to assemble all at once (and if that's not, then a 16-letter word will be...).
Instead, try thinking about how you could store the words and look up potential anagrams in a way that doesn't require you to do that.
Edit: I get that ability to solve largeish words may not be your biggest concern at this point, but it might actually make your fourth and fifth steps easier if you do them by assembling the set of valid words rather than starting with all possibilities and removing all the ones that don't match. 'Removing' an item from an array is a bit awkward since you have to shuffle all the following items up to fill in the gap (this is exactly the kind of thing that STL manages for you).
Better algorithm : don't store your word, but store a tupple containing (your word, sorted letters). Moreover, you sort that big storage by the second key (hint, you could use a sqlite database to do the work for you and use an index (can't be unique!))
E.g. to store
"Florent", "Abraham","Zoe"
you would store in memory
("aaabhmr", "abraham"),("eflnort","florent"),("eoz","zoe")
When you got your word from your user, you just use same "sorting letter inside word" algorithm.
Then you look for that pattern in your storage, and you find all anagrams very quickly (log(size of dictionary)) as it's sorted. Of course, original words are the second elements of your tuple.
You can do that using classes, standard structures, a database, up to you to choose the easiest implementation (and the one fitting your requirements)