Trying to find isogram in a string c++ - c++

I am trying to write a code that has two functions: one that determines whether the string is an isogram or not and another one to print the outcome (true or false) to the console (for the purpose of solving the task).
Some of the things are not working correctly though. And I wonder where I need to improve the code (probably all over...). I would appreciate any advice :)
#include <iostream>
#include<string>
#include<bits/stdc++.h>
#include<iomanip>
bool find_Isogram (std::string str)
{
std::sort(str.begin(), str.end()); //sorted the string for the for loop (e.g. eHllo)
int length = str.length();
for (int i = 0; i < length; i++)
{
if (str.at(i) == str.at(i+1))
{
return false;
break;
}
else
{
return true;
}
}
}
void print_result()
{
std::string str;
if (!find_Isogram (str))
{
std::cout << "false" << std::endl;
}
else
{
std::cout << "true" << std::endl;
}
}
int main()
{
find_Isogram ("gdtub");
print_result();
return 0;
};
````````````````````````````````````````````````````

There are some problems here:
1) You always check an empty string:
print_result will just check an empty string, but it's redundant anyway.
void print_result()
{
std::string str; // empty string
if (!find_Isogram (str)) // finding isogram on empty string
{
std::cout << "false" << std::endl;
}
...
}
It can be simplified with std::boolalpha that allows you to print a bool as "true" or "false" (instead of 1 or 0). main would become
int main()
{
std::cout << std::boolalpha << find_Isogram ("gdtub"); // prints true or false
};
2) Isogram check always ends after first character
Take a look at the condition in find_Isogram. It has a return-statement in the if and else, so you always return after checking the first character.
The idea to detect duplicate characters this way is correct (except for the off-by-one-error already mentioned by others). But you want to return true; only after checking all of the characters, e.g. outside the loop:
bool find_Isogram (std::string str)
{
std::sort(str.begin(), str.end()); //sorted the string for the for loop (e.g. eHllo)
int length = str.length();
for (int i = 0; i < length - 1; i++)
{
if (str.at(i) == str.at(i+1))
{
return false; // whoops duplicate char, stop here
}
}
return true; // no duplicates found, it's an isogram
}
For some further C++-magic, you could simplify it even more with standard library functions :D
bool find_Isogram (std::string str)
{
std::sort(str.begin(), str.end());
return std::unique(str.begin(), str.end()) == str.end();
}

The condition where you check the consecutive characters for equality is wrong. It will yield true for strings like ABAB. You instead need to use a map with count of each character that has appeared.
Something like:
std::map<char, int> map_of_chars;
for(int i = 0; i < length; i++) {
map_of_chars[str.at(i)] = map_of_chars[str.at(i)] + 1;
}
If any value in the map is more than 1 return false;
Another implementation would be using the return value of std::unique():
std::sort(str.begin(), str.end());
auto intial_size = str.size();
std::unique(str.begin(), str.end());
if(str.size() == initial_size) {
/is an isogram
}
else {
//is not an isogram
}

Related

Check if a string is a number without regex or try catch

I want to implement a simple is_number function that checks if it's an integer, float or an unsigned long int using this method:
bool isNumber(const std::string& str)
{
size_t idx = 0;
//Check if it's an integer
std::stoi(str,&idx);
if (idx == str.size())
return true;
//Check if it's a float
std::stof(str,&idx);
if (idx == str.size() || str[str.size()-1] == 'f' && idx == str.size()) //Cause I do have some float numbers ending with 'f' in the database
return true;
//Check if it's an unsigned long int
std::stoul(str,&idx);
if (idx == str.size())
return true;
return false;
}
But if I test it with a pure string like "test" or "nan", it will throw an error because I'm trying to change a pure string to an integer.
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoi
However if I test it with "0nan" for example, stoi or the others will retrieve the first number and assign the index position of the first found number to the idx variable.
Is it possible to find a workaround for pure strings like "nan" or any other?
Or is there a better method to implement this without regex or try-catch?
std::stoi throws when it fails. Instead of using C i/o you can use C++ streams, try to read from the stream and check if there is something left in the stream:
#include <string>
#include <sstream>
#include <iostream>
enum Number {Float,Signed,Unsigned,NotANumber};
template <typename T>
bool is_only_a(const std::string& str){
std::stringstream ss(str);
T x;
return (ss >> x && ss.rdbuf()->in_avail() ==0);
}
Number isNumber(const std::string& str)
{
size_t idx = 0;
if (is_only_a<unsigned long>(str)) return Unsigned;
else if (is_only_a<int>(str)) return Signed;
else if (is_only_a<float>(str)) return Float;
return NotANumber;
}
int main() {
std::cout << isNumber("1.2") << "\n";
std::cout << isNumber("12") << "\n";
std::cout << isNumber("-12") << "\n";
std::cout << isNumber("asd") << "\n";
std::cout << isNumber("nan") << "\n";
}
Order is important, because 12 could be a float as well.
The link I posted in the comments is most probably what you need.
The only slight modification needed from the answers there is adding a +/- sign, and an optional (at most one) decimal point:
bool isNumber(const std::string &s) {
bool first_char = true;
bool saw_decpt = false;
for (const auto &it: s) {
if (std::isdigit(it)) { first_char = false; }
else if (it == '+' && first_char) { first_char = false; }
else if (it == '-' && first_char) { first_char = false; }
else if (it == '.' && !saw_decpt) { first_char = false; saw_decpt = true; }
else return false;
}
return true;
}

A better solution for comparing string patterns.?

Task : Create a function that returns true if two strings share the same letter pattern, and false otherwise.
I found a way to solve this task but I think it could be more simple and short. I converted all same letters to a specific char character for 2 strings. Then end of the process checked whether they are same or not. Any ideas for simpler solutions ?
#include <iostream>
#include <string>
using namespace std;
bool LetterPattern(string str1, string str2) {
// Controlling whether they have same size or not
if (str1.length() != str2.length()) {
return false;
}
else {
// Checking for ABC XYZ format type
int counter = 0;
for (int i = 0; i < str1.length()-1; i++) {
for (int k = i+1; k < str1.length(); k++) {
if (str1[i] == str1[k]) {
counter++;
}
}
}
int counter2 = 0;
for (int i = 0; i < str2.length() - 1; i++) {
for (int k = i + 1; k < str2.length(); k++) {
if (str2[i] == str2[k]) {
counter2++;
}
}
}
if (counter == 0 && counter2 == 0) {
return true;
}
// I added the above part because program below couldn't return 1 for completely different letter formats
// like XYZ ABC DEF etc.
//Converting same letters to same chars for str1
for (int i = 0; i < str1.length()-1; i++) {
for (int k = i+1; k < str1.length(); k++) {
if (str1[i] == str1[k]) {
str1[k] = (char)i;
}
}
str1[i] = (char)i;
}
}
//Converting same letters to same chars for str1
for (int i = 0; i < str2.length() - 1; i++) {
for (int k = i + 1; k < str2.length(); k++) {
if (str2[i] == str2[k]) {
str2[k] = (char)i;
}
}
str2[i] = (char)i;
}
if (str1 == str2) { // After converting strings, it checks whether they are same or not
return true;
}
else {
return false;
}
}
int main(){
cout << "Please enter two string variable: ";
string str1, str2;
cin >> str1 >> str2;
cout << "Same Letter Pattern: " << LetterPattern(str1, str2);
system("pause>0");
}
Examples:
str1
str2
result
AABB
CCDD
true
ABAB
CDCD
true
AAFFG
AAFGF
false
asdasd
qweqwe
true
As you want to see if one string is a Caesar cipher of the other, you might do:
bool LetterPatternImpl(const std::string& str1, const std::string& str2) {
if (str1.length() != str2.length()) { return false; }
std::array<std::optional<char>, 256> mapping; // char has limited range,
// else we might use std::map
for (std::size_t i = 0; i != str1.length(); ++i) {
auto index = static_cast<unsigned char>(str1[i]);
if (!mapping[index]) { mapping[index] = str2[i]; }
if (*mapping[index] != str2[i]) { return false; }
}
return true;
}
bool LetterPattern(const std::string& str1, const std::string& str2) {
// Both ways needed
// so ABC <-> ZZZ should return false.
return LetterPatternImpl(str1, str2) && LetterPatternImpl(str2, str1);
}
By 1 iteration on strings create key-value pairs That define corresponding characters.
In the second iteration check whether each character in the first/second string is compatible with the character with equal index in the second/second string. If there is no incompatibility return true, otherwise false.
First, as you did we can compare the size of 2 strings.
If they are equal we continue.
By iterating on 1 of the strings we can fill a map. Keys of the map are characters seen in the first string and its value is the corresponding character in the second string.
By reaching the nth character we check that whether we have a key or the same as this character or not.
If yes: Check the value that is equal to the nth character of the second string.
If no: we add a new key-value to the map. (the key is the nth character of the first string and the value is the nth character of the second string)
1.
After doing this we should do this again for another string. I mean for example if in the first step characters of the first string were keys, In the second step we should replace the string in the way that characters of second string become keys.
If both of them give true the answer is true. Otherwise false.
2.
Rather than replacing strings and repeat the iteration, we can prevent repetitive values to be added to the map.
To understand paragraph 1 and 2 imagine 1 iteration on strings of "ABC" and "ZZZ".
Notice that arrays can be used instead of map.
And, last but not least, an additional solution using "counting".
If we read the requirement, then you are only interested in a boolean result. That means, as soon as we have a 2nd association for a letter in the first string, then the result is false.
Example: If we have an 'a' and in the 2nd string at the same position a 'b', and then in some next position of the first string again an 'a' but then in the same position of the 2nd string a 'c', then we have 2 different associations for the letter a. And that is false.
If there is only one association per letter, then everything is ok.
How to accomplish "association" and "counting". For the "association, we will use an associative container, a std::unordered_map. And, we associate a letter from the first string, with a std::set of the already processed letters (from the 2nd string). The std::sets iinsert function will not add double letters from the secondt string. So, if there is again a 'b' associated with an 'a', that is completly fine.
But if there is a different associated letter, then the std::set will contain 2 elements. That is an indicator for a false result.
In such case, we stop evaluation characters immediately. This leads to a very compact and fast code.
Please see:
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <set>
bool letterPattern(const std::string& s1, const std::string& s2) {
// Here we will store the result of the function
bool result{ s1.length() == s2.length() };
// And here all associations
std::unordered_map<char, std::set<char>> association{};
// Add associations. Stop if result = false
for (size_t index{}; result && index < s1.length(); ++index)
if (const auto& [iter, ok] {association[s1[index]].insert(s2[index])}; ok)
result = association[s1[index]].size() == 1;
return result;
}
// Some driver test code
int main() {
std::vector<std::pair<std::string,std::string>> testData{
{"AABB", "CCDD"},
{"ABAB", "CDCD"},
{"AAFFG", "AAFGF"},
{"asdasd", "qweqwe"}
};
for (const auto& p : testData)
std::cout << std::boolalpha << letterPattern(p.first, p.second) << "\t for: '" << p.first << "' and '" << p.second << "'\n";
return 0;
}
Not sure about better, but a C++17 solution that builds a regular expression based on the first string's letters and matches it against the second:
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <tuple>
#include <regex>
bool match(const std::string &pattern, const std::string &s) {
std::unordered_map<char, int> indexes;
std::ostringstream builder;
int ref = 1;
for (char c : pattern) {
if (auto backref = indexes.find(c); backref != indexes.end()) {
builder << '\\' << backref->second;
} else {
if (ref > 1) {
builder << "(?!";
for (int n = 1; n < ref; n += 1) {
if (n != 1) {
builder << '|';
}
builder << '\\' << n;
}
builder << ')';
}
builder << "(.)";
indexes.emplace(c, ref++);
}
}
// std::cout << builder.str() << '\n';
return std::regex_match(s, std::regex{builder.str()});
}
int main() {
std::tuple<std::string, std::string, bool> tests[] = {
{"AABB", "CCDD", true},
{"ABAB", "CDCD", true},
{"AAFFG", "AAFGF", false},
{"asdasd", "qweqwe", true},
{"abc", "zzz", false}
};
std::cout << std::boolalpha;
for (const auto &[s1, s2, expected] : tests) {
if (match(s1, s2) == expected) {
std::cout << s1 << " => " << s2 << " = " << expected << ": PASS\n";
} else {
std::cout << s1 << " => " << s2 << " = " << (!expected) << ": FAIL\n";
}
}
return 0;
}
A simple (maybe not very efficient) approach:
#include<iostream>
#include<unordered_map>
using namespace std;
int main(void) {
string s1, s2;
unordered_map<string, char> subs;
cout<<"Enter the strings: ";
cin >> s1 >> s2;
if (s1.length() != s2.length())
cout<<"False"<<endl;
else {
for (int i=0; i<s1.length(); ++i) {
string key(1, s2[i]);
subs[key] = s1[i];
}
string s1_2 = "";
for (int i=0; i<s2.length(); ++i) {
string key(1, s2[i]);
s1_2 += subs[key];
}
if (s1 == s1_2)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
return 0;
}
Time Complexity O(n); Space Complexity O(n)
If I understood right and:
AABB - CCDD = true
AAFFG - AAFGF = false
asdasd - qweqwe = true
That's not pattern, it's check if second string is result of encryption by substitution of first. You can do it in simpler way, by attempting to built substitution table. If it fails, i.e. there are more than one association between source and result, the outcome is false.
Simplest case is that we have to check whole string. If we would need to find that if any substring is substitution of pattern contained in second string, that squares the complexity:
#include <string>
#include <vector>
#include <map>
#include <optional>
#include <limits>
bool is_similar (const std::string& s1, const std::string& s2)
{
if(s1.length() != s2.length()) return false;
using TCh = std::decay_t<decltype(s1)>::value_type;
// for non-unicode characters can use an array
//std::optional<TCh> table[ std::numeric_limits<TCh>::max ];
// std::optional used for clarity, in reality may use `TCh`
// and compare with zero char
std::map< TCh, std::optional<TCh>> table;
for (size_t it = 0; it < s1.length(); ++it)
{
if( table[s1[it]].has_value() && table[s1[it]] != s2[it] ) return false;
if( table[s2[it]].has_value() && table[s2[it]] != s1[it] ) return false;
table[s1[it]] = s2[it];
//table[s2[it]] = s1[it]; if symmetric
}
return true;
}
If we find a new character, we will make it equal to the same position as the other string characters. Next time, if we found it again, we will check based on it.
Suppose we have 'aa' and 'cd'.
1st iteration: 'a'='c'
2nd iteration: already 'a'='c'(1st iteration), so we must need 'c' in our 2nd string.
But in our 2nd string, it is 'd'. so simply it will return false.
#include <bits/stdc++.h>
using namespace std;
// if you want to use map
bool LetterPattern_with_map(string str1,string str2)
{
if(str1.size()!=str2.size()) return false;
map<char,char> mp;
for(int i=0;i<str1.size();i++)
{
if(!mp[str1[i]]) { mp[str1[i]]=str2[i]; continue; }
if(mp[str1[i]]!=str2[i]) return false;
}
return true;
}
// if you want to use array instead of map
bool LetterPattern_with_array(string str1,string str2)
{
if(str1.size()!=str2.size()) return false;
int check[128]={0};
for(int i=0;i<str1.size();i++)
{
if(!check[str1[i]-'A'+1]) { check[str1[i]-'A'+1]=(int)(str2[i]-'A'+1); continue; }
if(check[str1[i]-'A'+1]!=(int)(str2[i]-'A'+1)) return false;
}
return true;
}
int main()
{
cout << "Please enter two string variable: ";
string str1, str2;
cin >> str1 >> str2;
cout << "Same Letter Pattern: " << LetterPattern_with_map(str1, str2)<<'\n';
cout << "Same Letter Pattern: " << LetterPattern_with_array(str1, str2);
}

check if string contains only unique chars using .at(int)

Really basic question but I can't figure this out. My program checks if a string is unique by setting flags for each ASCII in an array to true if found in the string. It's not working(it compiles, but doesn't give correct answer), and I can't for the life of my figure out why.
The output I get is 0:
main.cpp
#include "main.hpp"
#include <iostream>
bool isUnique(std::string str) {
if(str.length() > 128)
return false;
bool theChars[128];
for(int i = 0; i < str.length(); i++) {
int loc = str.at(i);
if(theChars[loc])
return false;
else
theChars[loc] = true;
}
return true;
}
int main() {
std::string timmy = "abcdefghijklmnop";
std::cout << isUnique(timmy);
return 0;
}
You forgot to initialize the bool array:
bool theChars[128] = {};
The empty initializer means "use the default value" which is zero, aka false for bool.
P.S. Your code produces undefined behavior if you have any character outside [0, 127]. You could fix this by making theChars 256 long and casting the character to uint8_t before indexing. Or use std::array<char, 128> and theChars.at(loc) to throw an exception if out of bounds.
easier way is use set:
#include <iostream>
#include <set>
using namespace std;
bool isUnique(string str) {
set<char>st(str.begin(),str.end());
if(st.size()==str.size())
return true;
return false;
}
int main() {
string timmy = "abcdefghijklmnop";
cout << boolalpha<<isUnique(timmy)<<endl;
timmy = "aaaaabbbcdefghijklmnop";
cout << boolalpha<<isUnique(timmy)<<endl;
return 0;
}
p.s. if not use boolalpha, it will print 1 for true and 0 for false.
std::sort(str.begin(), str.end());
return std::adjacent_find(str.begin(), str.end()) == str.end();
This doesn't use any additional space, and works for any character encoding.

C++ detecting if input is Int or String

I'm a C++ newbie who came from Java, so I need some guidance on some really basic issues I'm stumbling upon as I go.
I'm reading lines from a file, and each line consists of 6 strings/ints, which will be sent as parameters to a temporary variable.
Example:
Local1,Local2,ABC,200,300,asphalt
However, there are two subtypes of variable. One has a string as the last parameter (like 'asphalt' in the example above). The other one has an int instead. I have a method that reads each parameter and sends it to a variable, but how do I detect if the last bit of string is an integer or a string beforehand, so I know if I should send it to a Type1 variable or a Type2 one?
Many thanks!
Since you want to determine the type of the last column, then this ought to work:
#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <sstream>
#include <cctype>
#include <algorithm>
enum Types {
NONE,
STRING,
INTEGER,
DOUBLE
};
struct Found {
std::string string_val;
int integer_val;
double double_val;
enum Types type;
};
//copied verbatim from:
//http://stackoverflow.com/a/2845275/866930
inline bool isInteger(const std::string &s) {
if(s.empty() || ((!std::isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
char * p ;
std::strtol(s.c_str(), &p, 10);
return (*p == 0);
}
//modified slightly for decimals:
inline bool isDouble(const std::string &s) {
if(s.empty() || ((!std::isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ;
char * p ;
std::strtod(s.c_str(), &p) ;
return (*p == 0);
}
bool isNotAlpha(char c) {
return !(std::isalpha(c));
}
//note: this searches for strings containing only characters from the alphabet
//however, you can modify that behavior yourself.
bool isString (const std::string &s) {
std::string::const_iterator it = std::find_if(s.begin(), s.end(), isNotAlpha);
return (it == s.end()) ? true : false;
}
void determine_last_column (const std::string& str, Found& found) {
//reset found:
found.integer_val = 0;
found.double_val = 0;
found.string_val = "";
found.type = NONE;
std::string temp;
std::istringstream iss(str);
int column = 0;
char *p;
while(std::getline(iss, temp, ',')) {
if (column == 5) {
//now check to see if the column is an integer or not:
if (isInteger(temp)) {
found.integer_val = static_cast<int>(std::strtol(temp.c_str(), &p, 10));
found.type = INTEGER;
}
else if (isDouble(temp)) {
found.double_val = static_cast<double>(std::strtod(temp.c_str(), &p));
found.type = DOUBLE;
}
else if (isString(temp)) {
found.string_val = temp;
found.type = STRING;
}
}
++column;
}
if (found.type == INTEGER) {
std::cout << "An integer was found: " << found.integer_val << std::endl;
}
else if(found.type == DOUBLE) {
std::cout << "A double was found: " << found.double_val << std::endl;
}
else if(found.type == STRING) {
std::cout << "A string was found: " << found.string_val << std::endl;
}
else {
std::cout << "A valid type was not found! Something went wrong..." << std::endl;
}
}
int main() {
std::string line_t1 = "Local1,Local2,ABC,200,300,asphalt";
std::string line_t2 = "Local1,Local2,ABC,200,300,-7000.3";
Found found;
determine_last_column(line_t1, found);
determine_last_column(line_t2, found);
return 0;
}
This outputs and correctly assigns the appropriate value:
A string was found: asphalt
An integer was found: -7000.3
This version works on int, double, string; does not require boost; and, is plain vanilla C++98.
REFERENCES:
UPDATE:
This version now supports both positive and negative numbers that are integers or doubles, in addition to strings.
First, create an array that can store both strings and integers:
std::vector<boost::variant<std::string, int>> items;
Second, split the input string on commas:
std::vector<std::string> strings;
boost::split(strings, input, boost::is_any_of(","));
Last, parse each token and insert it into the array:
for (auto&& string : strings) {
try {
items.push_back(boost::lexical_cast<int>(string));
} catch(boost::bad_lexical_cast const&) {
items.push_back(std::move(string));
}
}

How to search words that contain more than three of the same letter through out the entire word

For some reason this code is printing out all the words in my list, while I want it to just print out words with more than three z's
I've managed to solve the code, below its searching for words that that have "zz" in them, an example buzz or blizzard. My main goal is to search for words that three z's through out the entire word an example off the top of my head would be zblizzard or something.
Word* Dictionary::findzs()
{
int wordIndex = 0;
cout << "List : " << endl;
while (wordIndex < MAX_WORDS) {
string word1 = myWords[wordIndex]->word;
wordIndex++;
if (word1.find("zz") != std::string::npos){
cout << word1 << endl;
}
}
return 0;
}
update:
bool has_3_zs(const std::string& s)
{
return std::count(std::begin(s), std::end(s), 'z') >= 3;
}
void Dictionary::has3zs()
{
int wordIndex = 0;
string word = myWords[wordIndex]->word;
while (wordIndex < MAX_WORDS) {
for (auto& s : { word })
{
if (has_3_zs(s))
{
std::cout << s << '\n';
}
}
}
}
There are several problems:
string::find_first_of() is not the right function to use. It searches the string for the first character that matches any of the characters specified in its argument. In other words, your code does indeed look for a single letter z (since that's the only distinct letter that appears in subString). If you wish to find three z's in a row, use string::find() instead. If you wish to find three z's anywhere in the string, use std::count().
Your are not checking the return value correctly. You are implicitly comparing the return value to zero, whereas you need to be comparing against string::npos.
The wordIndex++ is misplaced.
return myWords[wordIndex] looks like out-of-bounds access, potentially resulting in undefined behaviour.
I get it now. You want to match strings that contain a least 3 'z' characters anywhere.
Use std::count. This example:
#include <algorithm> // std::count
#include <iostream> // std::cout
#include <iterator> // std::begin, std::end
#include <string> // std::string
// This is the function you care about.
// It returns `true` if the string has at least 3 'z's.
bool has_3_zs (const std::string& s)
{
return std::count(std::begin(s), std::end(s), 'z') >= 3;
}
// This is just a test case. Ignore the way I write my loop.
int main()
{
for (auto& s : {"Hello", "zWorzldz", "Another", "zStzzring"} )
{
if (has_3_zs(s))
{
std::cout << s << '\n';
}
}
}
prints:
zWorzldz
zStzzring
Edit:
Ok, I've written an example a bit more like yours. My loop is written roughly the same way as yours (which in my opinion is not the best, but I don't want to add further confusion).
// This is the function you care about.
// It returns `true` if the string has at least 3 'z's.
bool has_3_zs (const std::string& s)
{
return std::count(std::begin(s), std::end(s), 'z') >= 3;
}
struct SomeTypeWithAWord
{
std::string word; // The bit you care about
// Allow me to easily make these for my example
SomeTypeWithAWord(char const * c) : word(c) {}
};
// This will contain the words.
// Don't worry about how I fill it up,
// I've just written it the shortest way I know how.
std::vector<SomeTypeWithAWord> myWords
{"Hello", "zWorzldz", "Another", "zStzzring"};
// This is the function you are trying to write.
// It loops over `myWords` and prints any with 3 or more 'z's.
void findzs()
{
std::cout << "List : \n";
std::vector<SomeTypeWithAWord>::size_type wordIndex = 0;
while (wordIndex < myWords.size()) // Loop over all the words
{
const std::string& testWord = myWords[wordIndex].word;
if (has_3_zs(testWord)) // Test each individual word
{
std::cout << testWord << '\n'; // Print it
}
++wordIndex;
}
}
int main()
{
findzs();
}
EDIT- BoB TFish is the simpler, hence better solution.
You may use find_first_of 3 times to see if you have (at least) 3 z's spread throughout the word.
Try something like this:
Word* Dictionary::findzs()
{
int wordIndex = 0;
cout << "List : " << endl;
size_t where;
int i;
string subString = "z"; // or "zZ" if you want uppercase as well
while (wordIndex < MAX_WORDS) {
string word1 = myWords[wordIndex]->word;
where = 0;
for (i = 0 ; i < 3 ; i++)
{
where = word1.find_first_of(substring, where);
if (where == string::npos)
break;
where++; // fix...
}
if (i == 3)
{
cout << word1 << endl;
}
wordIndex++;
}
//return myWords[wordIndex]; - this will try to return myWords[MAX_WORDS] which is probably outside array bounds
return NULL; // or whatever else you see fit
}