Getting an error while reversing vowels in a string [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I know there are similar questions about this topic but I wanted to know error in my approach.
I'm writing a code to reverse vowels in a string. I first took all the vowels of a string into a vector and then I looped the string from backwards by replacing the vowels but I keep getting an error.
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
string reverseVowels(string s)
{
vector<char>v;
vector<char>v2;
char c;
for (int i = 0; i < s.size(); i++)
{
//taking all the vowels of the string into a vector
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
{
v.push_back(s[i]);
}
}
//reversing the vowels of the string
for (int i = s.size() - 1; i >= 0; i--)
{
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
{
s[i] = v[i]; //Getting an error here
}
}
return s;
}
int main()
{
//Required output is "holle"
string s = "hello";
string p = reverseVowels(s);
cout << p << endl;
return 0;
}

You need another index for the reversed vowels:
for (int vowelIdx = 0, i = s.size() - 1; i >= 0; i--)
{
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
{
s[i] = v[vowelIdx++]; //Getting an error here
}
}
edit
Regarding your comment below; let's examine the code for the word hello. The first loop runs through all the vowels in hello and fills the vector v as eo. It has two vowels with e as the first and o as the second/last element.
Your second loop reverse traverses the word hello, and encounters the first vowel o. You need to reset this to e which is the first element of the vector v. This is where your code get an error. The value of i is 4 now, hence you are trying to use the 4.th index of vector v which has only two elements. You have to set s[4] = v[0] and s[1] = v[1]. However, your code tries to set s[4] = v[4] (see the error?) and s[1] = v[1].
Hope it's clear now, if not try it on paper with a longer word. I'm sure you will see the point.

Related

Why does each single character of the string not equal to the character equivalent?

I am trying to check if each character of a string in a string array is equal to any of the five vowels. However, when I test it to see when a vowel character in a string is equal to 'vowel', I get that they are not equal. The problem with the code is the bolded part below. Also, when I try to do "a" || "e" || "i" || "o" || "u", I get the error that ISO C++ forbids comparison between pointer and integer. How can I be able to check if they are equal? Thank you for your time.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <cstdlib>
using namespace std;
int l, c; //l is amount of letters in password, c is amount of letters being inputted
char letters[1000000]; //the letters being inputted
vector <string> pass; //string vector of the stored passwords
void rec(string current, int index, int x){ //determining all possible passwords
if (index >= 4){
pass.push_back(current);
}
else{
for (int i=0; i<c; i++){
if (x<i){
int old;
old = x;
x = i;
rec(current + letters[i], index+1, x);
x = old;
}
}
}
}
int main (int argc, char ** argv)
{
cin >> l >> c;
int x = -1;
for (int i=0; i<c ;i++){
cin >> letters[i];
}
sort(letters, letters + c); //sorted from least to greatest
rec("", 0, x);
for (int i=0; i<pass.size(); i++){
int vl=0; //number of vowels
int nvl=0; //number of non-vowels (consonants)
for (int j=0; j<l; j++){
**if (pass.at(0)[j] == 'a' || 'e' || 'i' || 'o' || 'u'){**
vl++;
}
else{
nvl++;
}
if (j == l-1){
if (vl >= 1 && nvl >= 2){
cout << pass.at(0) << endl;
}
}
}
}
return 0;
}
In C++, X || Y means:
Test if X is true. If so, result of whole expression is true
Otherwise, test if Y is true. Result of Y is result of expression.
So your code:
pass.at(0)[j] == 'a' || 'e'
(omitting for now the i etc. as they don't change anything).
We tested pass.at(0)[j] == 'a' . That was false, so now we test 'e'. Not that you did NOT test pass.at(0)[j] == 'e'. You just tested 'e'. This is the same as testing 'e' != 0, which is true. So your expression evaluates to true at this point (and does not go onto check 'i' etc.)
You probably intended to test whether pass.at(0)[j] held any of the values 'a', 'e', etc. If so then one way to encode that is:
if ( std::strchr("aeiou", pass.at(0)[j]) )
You should make sure j < strlen(pass.at(0)) before doing this though; using [] to generate an out of bounds index causes undefined behaviour.
Because you are using the || wrong. The part either side of || is a "true or false" expressin in itself, so you need something like:
if (pass.at(0)[j] == 'a' || pass.at(0)[j] == 'e' ... )
Otherwise, the expression is always true, since || is true if the expression on left or right is true, and 'e' is true by not being zero.
This does not do what you think...
(pass.at(0)[j] == 'a' || 'e' || 'i' || 'o' || 'u')
You need to explicitly compare,
char t = pass.at(0)[j];
if (t == 'a' || t == 'e' || t == 'i' || t == 'o' || t == 'u') {

Word Unscrambling Program - C++

Hi I'm working a program to unscramble a set of letters and output all the words that can be made from that set of letters, for example: If i inputed the letters "vlei", the program would output "live", "evil", and "vile".
So far I have looked through the internet about this quiiiite a bit and can't find anything on my specific questions relevant to my skill level at this point (level 2 noob).
So far I have gotten as far as making all the possible combinations from the the given letters. Excluding any that are less than 7 letters, which is a problem.
This is the code I have so far:
string letter;
char newWord[7];
int main()
{
cout << "Type letters here: ";
cin >> letter;
for(int i = 0 ; i < 7 ; i++)
{
for(int j = 0 ; j < 7 ; j++)
{
for(int k = 0 ; k < 7 ; k++)
{
for(int l = 0 ; l < 7 ; l++)
{
for(int m = 0 ; m < 7 ; m++)
{
for(int n = 0 ; n < 7 ; n++)
{
for(int o = 0 ; o < 7 ; o++)
{
sprintf(newWord, "%c%c%c%c%c%c%c", letter[i], letter[j], letter[k], letter[l], letter[m], letter[n], letter[o]);
}
}
}
}
}
}
}
return 0;
}
I was wondering if anyone has any experience with anything like this, and can offer and hints or advice.
Specifically what I'm having difficulty with is how to read in a .txt file to use as a dictionary to compare words to.
Also, I was having trouble using strcmp() which is what I was planning to use to compare the scrambled words to the dictionary. So if there are any other maybe simpler ways to compare the two strings, that would be greatly appreciated.
Thanks in advance.
Hi guys, so I've just finished my program and I hope it can help someone else. Thanks a lot for all your help.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <array>
using namespace std;
//declaring variables
int i;
int scores[531811]; //array for scores of found words
string wordlist[531811]; //array for found matched words
string word[531811]; //array of strings for dictionary words about to be read it
string tester;//string for scrambled letters that will be read in
int scorefinder(string scrab) //SCORE FINDER FUNCTION
{
int score = 0;
int x = 0;
int j = 0;
while (scrab[j])
{
char ltr = toupper(scrab[j]); //converts to all caps
//assings values to each letter and adds it to itself
if(ltr == 'A' || ltr == 'E' || ltr == 'I' || ltr == 'L' || ltr == 'N' || ltr == 'O' || ltr == 'R' || ltr == 'S' || ltr == 'T' || ltr == 'U')
x += 1;
else if(ltr == 'D' || ltr == 'G')
x += 2;
else if(ltr == 'B' || ltr == 'C' || ltr == 'M' || ltr == 'P')
x += 3;
else if(ltr == 'F' || ltr == 'H' || ltr == 'V' || ltr == 'W' || ltr == 'Y')
x += 4;
else if(ltr == 'K')
x += 5;
else if(ltr == 'J' || ltr == 'X')
x += 8;
else if(ltr == 'Q' || ltr == 'Z')
x += 10;
++j;
}
score = x;
return score;
}
int main () {
//READS IN DICTIONARY
ifstream file("words.txt"); //reads in dictionary
if (!file.is_open()){ //checks if file is being NOT read correctly
cout << "BROEKN \n"; //prints error message if so
}
if(file.is_open()){ //checks if file IS being read correctly
for(int i = 0; i < 531811; i++){
file >> word[i]; //read in each word from the file and
} //assigns each to it's position in the words array
}
//END OF READ IN DICTIONARY
cout << "Enter scrambled letters: ";
cin >> tester; //reads in scrambled letters
sort(tester.begin(),tester.end()); //sorts scrambled letters for next_permutation
while (next_permutation(tester.begin(),tester.end())){ //while there are still permutations available
for(i=0;i<531811;i++){
if ( is_permutation (word[i].begin(),word[i].end(), tester.begin())){
wordlist[i] = word[i]; //assigns found word to foundword array
scores[i] = scorefinder(word[i]); //assigns found word score to foundscore array
}
}
}
//PRINTS OUT ONLY MATCHED WORDS AND SCORES
for(i=0;i<531811;i++){
if(scores[i]!=0){
cout << "Found word: " << wordlist[i] << " " << scores[i] << "\n";
}
}
}
Well, what you need is some sort of comparison. C++ doesn´t know, what a right word in english is. So you may need a wordlist. Then you can Brutforce(that´s what you´re doing at the moment) until you find a match.
For comparing your brutforced result, you may use a .txt with as many english words as you can find. Then you have to use a FileStream for iterating through every word and comparing it to your brutforce result.
After you sucessfully unscrambled a word, you should think about your solution again. As you can see, you are limited to a specific amount of chars which is not that nice.
This sounds like an interesting Task for a beginner ;)
Suppose you have found a word list in the form of plain text file on the Internet, you may load all the words into a vector for string first.
ifstream word_list_file("word_list.txt");
string buffer;
vector<string> all_words;
while (getline(word_list_file, buffer))
all_words.push_back(buffer);
Then we want to compare the input letters with the each entry of all_words. I suggest using std::is_permutation. It compares two sequence regardless the order. But it can have trouble when the two sequence has different length, so compare the length yourself first.
// Remember to #include <algorithm>
bool match(const string& letters, const string& each_word)
{
if (letters.size() != each_word.size())
return false;
return is_permutation(begin(letters), end(letters), begin(each_word));
}
Note that I have not tested my codes. But that's the idea.
An edit responsing the comment:
In short, just use std::string, not std::array. Or copy my match function directly, and invoke it. This will be easier for your case.
Details:
std::is_permutation can be used with any container and any element type. For example:
#include <string>
#include <array>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
//Example 1
string str1 = "abcde";
string str2 = "ecdba";
is_permutation(begin(str1), end(str1), begin(str2));
//Example 2
array<double, 4> array_double_1{ 4.1, 4.2, 4.3, 4.4 };
array<double, 4> array_double_2{ 4.2, 4.1, 4.4, 4.3 };
is_permutation(begin(array_double_1), end(array_double_1), begin(array_double_2));
//Example 3
list<char> list_char = { 'x', 'y', 'z' };
string str3 = "zxy";
is_permutation(begin(list_char), end(list_char), begin(str3));
// Exampl 4
short short_integers[4] = { 1, 2, 3, 4 };
vector<int> vector_int = { 3, 4, 2, 1 };
is_permutation(begin(list_char), end(list_char), begin(str3));
return 0;
}
Example 1 uses std::string as containers of chars, which is exactly how my match function work.
Example 2 uses two arrays of double of size 4.
Example 3 even uses two different kinds of containers, with the same element types. (Have you heard of `std::list'? Never mind, just focus on our problem first.)
Example 4 is even stranger. One container is old style raw array, another is a std::vector. There are also two element types, short and int, but they are both integer. (The exact difference between short and int is not relevant here.)
Yet, all four cases can use is_permutation. Very flexiable.
The flexibility is enabled by the following facts:
is_permutation is not exactly a function. It is a function template, which is a language feature to generate new functions according to the data type you pass to it.
The containers and is_permutation algorithm do not know each other. They communicate through a middleman called "iterator". The begin and end functions together give us a pair of iterators representing the "range" of elements.
It requires more studies to understand these facts. But the general idea is not hard. Also, these facts are also true for other algorithms in the Standard Library.
Try this :
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "vlei";
permute(a, 0, 3);
getchar();
return 0;
}

strcmpi integer without a cast error

I'm trying to create a program that removes vowels from a string, add them into a vector and then give the user the possibility of having the original code again.
In my code i have this:
char s[20];
And soon after i have this comparison:
for(j=0;j<tam;j++)
{
if(strcmpi(s[j],"a")==1 ||
(strcmpi(s[j],"e")==1 ||
(strcmpi(s[j],"i") ==1||
(strcmpi(s[j],"o") ==1||
(strcmpi(s[j],"u")==1))
{
So if the array is char and the vowels are char(""), why the compiler give me this error?:
[Warning] passing arg 1 of `strcmpi' makes pointer from integer without a cast
EDIT
As someone said the correct is s[j] == 'a', but that result in wrong way. If a put car the result is still car. Don't know why.
if(s[j] == 'a' ||
s[j] == 'A' ||
s[j] == 'e' ||
s[j] == 'E' ||
s[j] == 'i' ||
s[j] == 'I' ||
s[j] == 'o' ||
s[j] == 'O' ||
s[j] == 'u' ||
s[j] == 'U')
{
s[j] = s[j++]; }
Strcmpi is for comparing strings. The first argument to strcmpi is of type char, when it expects a char*.
In order to compare single chars, s[j]=='e' is enough, or tolower(s[j])=='e' if you need it to be case insensitive. You'll need to include ctype.h. for tolower.
The arguments to strcmpi must be strings, but s[j] is just a single character, not a string. You can use == to compare characters directly. To get case-insensitive comparisons, get the lowercase version of the character first and compare it.
for (j = 0; j < tam; j++) {
char lower = tolower(s[j]);
if (lower == 'a' || lower == 'e' || lower == 'i' || lower == 'o' || lower == 'u') {
...
}
}
You don't want to use strcmp or any of its variants.
Because you want to know whether the string contains vowels or not, you may want to use a substring search using strstr.
You use function strcmpi incorrectly. It first parameter has type const char * while you pass an argument of type char. That is the function expects a string while you pass only one character.
Moreover this function is not a standard C/C++ function. So it should not be used.
You could achieve the same result using the following approach
char vowels[] = "aeiou";
//...
if ( strchr( vowels, tolower( s[j] ) )
{
std::cout << s[j] << " is a vowel" << std::endl;
}
You have already been told that strcmpi is not the right way to check single characters. This is an answer to the edit to your question, where you ask about actually stripping the vowels.
If you want to retain the original string, you need extra memory for the string without consonants. You also need two indices, because once you have skipped a vowel in the original string, the indices are out of sync. Here's an example implementation:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char orig[] = "Jackdaws love my big sphinx of quartz.";
char cons[sizeof(orig)]; // Make new char buffer as big
// as the original
int i, j;
j = 0;
for (i = 0; orig[i]; i++) {
if (strchr("AEIOUaeiou", orig[i]) == NULL) {
cons[j++] = orig[i];
}
}
cons[j] = '\0'; // Terminate consonant string
printf("was: '%s'\n", orig);
printf("is: '%s'\n", cons);
return 0;
}
The expression strchr checks whether a character is in a string. You can use it as a shortcut to spelling out all vowels in explicit comparisons.

I'm having trouble with finding unique words, how to improve code? [duplicate]

This question already has an answer here:
How to improve my code to correctly count unique lines?
(1 answer)
Closed 9 years ago.
I need to count the number of unique words and with my code below, it doesn't seem to be counting correctly. I am not sure what else I can do to make it work and would really appreciate any suggestions.
#include <iostream>
#include <string>
#include <set>
using std::string;
using std::set;
unsigned long countUWords(const string& s)
{
set<string> uw;
string word = "";
for(size_t i = 0; i < s.size(); i++){
bool words = (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z');
if(words){
word += s[i];
}
else if(!words && word != ""){
uw.insert(word);
word = "";
}
}
if (word != "")
uw.insert(word);
return uw.size();
}
int main ()
{
string s;
unsigned long UWords = 0;
while(getline(cin, s)){
UWords += countUWords(s);
}
cout << UWords << endl;
return 0;
}
At the end of the for loop you need to check if word is empty. If not you need to push the content of word inside the set.
After the end bracket of the for loop, add:
if (word != "")
uw.insert(word);
As you can see it works just fine after that edit.

How to convert a recursive solution to bottom up or top down solution?

I am solving this problem-
Given a string consisting of a,b and c's, we can take any two adjacent
distinct characters and replace it with the third character. For
example, if 'a' and 'c' are adjacent, they can replaced with 'b'. What
is the smallest string which can result by applying this operation
repeatedly?
Now I have written the following recursive solution (far from efficient), but want to convert it to either top-down or bottom-up solution.
Problem: I am not able to come up with a tabular structure for memoization. Even though I have to output only the length of resulting string, how can I solve it without actually solving the problem. The strings are getting reduced, so how do I store them?
Any hint for DP solution or Memoization would be great!
EDIT Many people have come up with top-down memoization solution, please try bottom-up as well.
#include <iostream>
#include <string>
using namespace std;
string reduce(string s)
{
if (s.length() <= 1)
return s;
int k;
char c = s[0];
string min = s;
for (k = 1; k < s.length() && c; ++k)
if (s[k] != c)
c = 0;
if (c)
return s;
if (s.length() == 2){
if (s[0] != 'a' && s[1] != 'a')
s[0] = 'a';
else if (s[0] != 'b' && s[1] != 'b')
s[0] = 'b';
else if (s[0] != 'c' && s[1] != 'c')
s[0] = 'c';
s.resize(1);
return s;
}
for (k = 1; k < s.length(); ++k){
string s1 = reduce(s.substr(0, k));
string s2 = reduce(s.substr(k));
if (s1.length() + s2.length() < min.length())
min = s1 + s2;
if (!s1.empty() && !s2.empty() && s1.back() != s2.front()){
if (s1.back() != 'a' && s2.front() != 'a')
s1.back() = 'a';
else if (s1.back() != 'b' && s2.front() != 'b')
s1.back() = 'b';
else if (s1.back() != 'c' && s2.front() != 'c')
s1.back() = 'c';
s1 = reduce(s1 + s2.substr(1));
if (s1.length() < min.length())
min = s1;
}
}
return min;
}
int main()
{
string input;
cin >> input;
cout << reduce(input) << endl;
return 0;
}
I'm a bit too lazy to think the problem through, but I'll give you an approach to memoization that often enough works.
Instead of recursing directly, introduce mutual recursion.
std::string reduce(std::string const &s)
{
// ...
string s1 = reduce_memo(s.substr(0, k));
string s2 = reduce_memo(s.substr(k));
// ...
}
where reduce_memo maintains a hash table, i.e. an unordered_map, mapping subproblems to their solutions.
// static is incredibly ugly, but I'll use it here for simplicity
static std::unordered_map<std::string, std::string> memo;
std::string reduce_memo(std::string const &s)
{
try {
return memo.at(s);
} except (std::out_of_range const &) {
std::string r = reduce(s);
memo[s] = r;
return r;
}
}
When programming in C++98, use std::map instead of unordered_map.
This doesn't solve the problem, but I noticed:
if (s.length() == 2){
if (s[0] != 'a' && s[1] != 'a')
s[0] = 'a';
else if (s[0] != 'b' && s[1] != 'b')
s[0] = 'b';
else if (s[0] != 'c' && s[1] != 'c')
s[0] = 'c';
s.resize(1);
return s;
}
doesn't work according to the problem statement:
we can take any two adjacent distinct characters and replace it with the third character.
Consider the string s = "bb". Neither s[0] nor s[1] are equal to 'a', which means the condition s[0] != 'a' && s[1] != 'a' will evaluate to true for the string "bb". This goes for any string of consecutive characters of the same value, e.g. "bb", "cc".
Perhaps in the condition you can take the difference of the two consecutive characters, and check if they're non-zero.
You can memoize your solution by storing the result of reduce(s) in a map<string,string>.
string reduce(string s, map<string,string>& memo) {
if (memo.count(s)) {
return memo[s];
}
// The rest of your code follows...
memo[s] = min;
}
Whatever i have understood from the problem the solutions should be
length of the input - if all input characters are same like
aaaaa - 5
bbb - 3
and 1 in every other case.
Correct me if I miss some part of the problem.
The absolute minimum is 1. However, the specifics of the string and replacement rules may yield between 1 and n, where n is the length of the string.
For the specific example, then the smallest possible is n/2, as you take 2 characters and replace them with 1 (which cannot be further replaced) so even if you had "acacacacacacacac", the best possible case, you would still only achieve the factor of 2 reduction.
I solved a similar problem in competitive programming workshop,
and indeed your proposed solution weren't fast enough.
My solution was creating such vector:
string s;
cin >> s;
int length = s.length();
vector<vector<int> > v(length, vector<int>(length)); // 2d array of size length*length.
where v[i][j] will be the minimal length the substring from i to j of s can get to.
Later all you have to do is fill this table in increasing size.
Hope that helped.
"a...a" (“a" * n) == > n
"b...b" (“b" * n) == > n
"c...c" (“c" * n) == > n
any other ==> 1 or 2 with my greedy algorithm.
If we get 2 in this greedy algorithm, I can't prove it is the smallest result for the input string.
Greedy algorithm
while the last two is the same character { // the number of the same characters
find the last replaceable pair // at the tail will decrease until
reduce them // it become 1
}
while find the first replaceable pair
reduce them