English is not my main language so I apologize for any mistakes I've done.
Basically, the exercise says that we initialize and read from keyboard an array t, with maximum 400 characters, made up of words separated by a space. The words are only made up of letters. And I have to write a program in C that finds the first word in the array that has 2 vowels on consecutive positions and it prints that word along with the number of appearances. If there are no such words, "Invalid" is printed instead.
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
ifstream in("ex.in");
ofstream out("ex.out");
char t[401], voc[] = "aeiouAEIOU", s[401];
int n, nr, i;
int main()
{
in.getline(t, 401);
char *cuv = strtok(t, " ");
char a, b;
n = strlen(cuv);
while(cuv && !nr)
{
for(i = 0; i < strlen(cuv); i )
{
a = cuv[i];
b = cuv[i 1];
if(strchr(voc, a) && strchr(voc, b))
{
nr ;
strcpy(s, cuv);
break;
}
}
cuv = strtok(NULL, " ");
}
while(cuv)
{
if(strcmp(s, cuv) == 0)
nr ;
cuv = strtok(NULL, " ");
}
if(nr == 0)
out << "Invalid";
else
out << s << " " << nr;
return 0;
}
This is what I've done so far, but when I add in the ex.in file the words, if the first word doesn't have 2 vowels next to each other, but the last letter is a vowel, that's the one that will be shown in exe.out despite not fulfilling the criteria and I don't understand what's wrong with what I have written. For example, if my array is "wing book bear book" the print is "book 2" and it's good. But when my array is "vine book bear book" the print is "vine 1" instead of "book 2".
CodePudding user response:
First of all. Your code is C and not C . My compiler, Visual Studio, will not compile your code and throw 4 errors and 1 warning. Because you really should or must not use strtok
or even strcpy
.
Then there is only one simple out of bound problem in your code. In your for loop for (i = 0; i < strlen(cuv); i )
you iterate until the length of the string, but with b = cuv[i 1];
you always access the final '\0' at the end of the string.
And if you then call strchr(voc, b)
with b being '\0' it will find this '\0' also in the vowels string. So, if the word does not contain double vowels, strchr(voc, b)
will always return true.
That causes the bug.
Solution is simple. Write
for (i = 0; i < strlen(cuv)-1; i )
instead.
.
.
In C we would implement the solution for example like this:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
// Functor for double vowel finder
struct DoubleVowel {
bool operator ()(const std::string& s) const noexcept {
if (not s.empty()) for (size_t i{}; i<s.length()-1; i)
if ((((0x208222 >> (s[i] & 0x1f)) & 1) and (((0x208222 >> (s[i 1] & 0x1f)) & 1))))
return true;
return false;
}
};
int main() {
// First open input file and check, if it could be opened
if (std::ifstream ifs{ "ex.in" }; ifs)
// now open the out file and check, if it could be opened
if (std::ofstream ofs{ "ex.out" }; ofs) {
// Both files are open. Read all words from the file
const std::vector words{ std::istream_iterator<std::string>(ifs),{} };
// Now, find first word with 2 consecutive vowels
if (auto it = std::find_if(words.begin(), words.end(), DoubleVowel()); it != words.end())
// Count the number of words equal to the above found and show result
std::cout << (*it) << '\t' << std::count(words.begin(), words.end(), *it) << '\n';
}
else std::cerr << "\n\n*** Error: Could not open output file for writing\n\n";
else std::cerr << "\n\n*** Error: Could not open input file for reading\n\n";
}
And if the consecutive vowels in the word should be the same then we can replace the if statement in
the functor with:
if ((s[i] == s[i 1]) and (((0x208222 >> (s[i] & 0x1f)) & 1)))
CodePudding user response:
As mentioned in the comments, using std::adjacent_find to find two consecutive vowels basically makes the work a lot simpler:
#include <algorithm>
#include <string>
#include <cstring>
#include <iostream>
#include <sstream>
bool isVowel(char c)
{
static constexpr const char *vowels = "AaEeIiOoUu";
return strchr(vowels, c);
}
int main()
{
std::string test = "vine book bear book";
std::string word;
int count = 1;
bool found = false;
std::istringstream strm(test);
while (strm >> word)
{
auto iter = std::adjacent_find(word.begin(), word.end(), [](char c1, char c2)
{ return isVowel(c1) && isVowel(c2); });
if (iter != word.end())
{
found = true;
std::cout << word << " " << count << "\n";
break;
}
count;
}
if ( !found )
std::cout << "Invalid";
}
Output:
book 2