The below program is intended to make all characters in a string lowercase, remove all vowels, and then print a full stop before every letter. For example, an input of "umbrella" would become ".m.b.r.l.l". But when I input "tour", the 'u' is not removed.
char ChangeToLow(char letter) {
if(letter <= 'Z' && letter >= 'A')
return letter - ('A' - 'a');
return letter;
}
int main()
{
string name;
cin>>name;
for (int i = 0 ; i < name.length() ; i++)
{
name[i] = ChangeToLow(name[i]);
if (name[i] == 'y' || name[i] == 'a'|| name[i] == 'u'|| name[i] == 'i'|| name[i] == 'e'|| name[i] == 'o')
{
name.erase(i,1);
}
}
for (int i = 0 ; i < name.length() ; i++)
{
cout<<'.'<<name[i];
}
}
I expect the output ".t.r" but instead it prints ".t.u.r".
Thanks in advance.
When you erase a character from the string, the remaining contents move over to fill the space. Their indexes adjust accordingly. With your tour example, it'll look something like the following:
Your loop counter, i, was incremented to 2 after you deleted the 'o' from tour, and name[i] is now 'r'. One option to avoid this behavior is to decrement i when you delete a vowel.
I have some suggestion for you. Firstly you shouldn't put using namespace std; in your code. It just adds confusion and is considered a bad practice. I think it would be also a good thing, if you would consider to learn the STL, if it is really your aim to learn C++ in depths. As for the error I think that the already posted answer shows your wrong assumptions.
#include <iostream>
#include <cstdlib>
#include <locale>
#include <set>
#include <algorithm>
int main()
{
std::string name;
std::cin>>name;
std::set<char> vowels={'a','u','i','e','o'};
std::transform(name.begin(), name.end(), name.begin(), [](auto v){ return std::tolower(v, std::locale());});
auto iter=std::remove_if(name.begin(), name.end(), [&vowels](auto v){ return vowels.find(v)!=vowels.end();});
name.erase(iter,name.end());
for (int i = 0 ; i < name.length() ; i++)
{
std::cout<<'.'<<name[i];
}
return EXIT_SUCCESS;
}
Related
char arr[5000];
ifstream is("test.txt");
is.get(arr,5000);
int i = 0;
int j = 0;
cout << arr << endl;
char anar[5000];
while (arr[i] != '\0')
{
if (arr[i] == 'i' || arr[i] == 'a' || arr[i] == 'e' ||
arr[i] == 'o' || arr[i] == 'u')
{
++i;
}
else anar[j] = arr[i]; ++j; ++i;
}++j; anar[j] = '\0';
cout << anar << endl;
ofstream os("test.txt");
os.write(anar, sizeof(char));
cout << "written successfully" << endl;
should read the data from a file and delete the vowels from this string. After deleting vowels, it should assign the result to another string. But vowels seem strange characters and the writen file is only one character long.
How big do you think sizeof(char) is? So how many characters is this going to write?
os.write(anar, sizeof(char));
You actually have j characters in your array, so this works
os.write(anar, j);
But since you have a null terminated character array even simpler would be
os << anar;
Some other errors, look at this loop
while (arr[i] != '\0')
{
if (arr[i] == 'i' || arr[i] == 'a' || arr[i] == 'e' ||
arr[i] == 'o' || arr[i] == 'u')
{
++i;
}
else anar[j] = arr[i]; ++j; ++i;
}++j; anar[j] = '\0';
It looks like you are missing {} around the else part of the if statement. You also have an extra ++j after the while loop for some reason. Here's how it should look (I think)
while (arr[i] != '\0')
{
if (arr[i] == 'i' || arr[i] == 'a' || arr[i] == 'e' ||
arr[i] == 'o' || arr[i] == 'u')
{
++i;
}
else
{
anar[j] = arr[i];
++j;
++i;
}
}
anar[j] = '\0';
Notice how much easier these problems are to spot if you get into the habit of consistently indenting your code. You should do this.
BTW there are no C++ strings in your code, only character arrays.
A very good answer has been given by john already. So, the problem is solved.
I would like to recommend to you to learn a little bit about C++ and all the existing libraries. Especially the C++ - algorithms library is very powerful.
Look at the below program:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
int main() {
// Open files and check, if they could be opened
if (std::ifstream is("withvowels.txt"); is)
if (std::ofstream os("withoutvowels.txt"); os)
// Copy file and remove vowels
std::copy_if(std::istreambuf_iterator<char>(is), {}, std::ostreambuf_iterator<char>(os), [](const char c) { return !((0x208222 >> (c & 0x1f)) & 1); });
}
So, in essence, we have just 3 statements: 2 times if with initializer. And then one copy_if with a lambda for vowel detection.
If you want to know more about the lambda and vowel detection you can read in one of my other posts here.
EDIT
Op asked, how to read the file into a std::string. I added a new piece of code, where I first read the complete file into a std::string and then erase/remove the vowels. The result is shown on std::cout
Please see:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <string>
int main() {
// Open file and check, if it could be opened
if (std::ifstream is("r:\\withvowels.txt"); is) {
// Read the complete file into string variable s
std::string s(std::istreambuf_iterator<char>(is), {});
// Remove all vowels from string
s.erase(std::remove_if(s.begin(), s.end(), [](const char c) { return ((0x208222 >> (c & 0x1f)) & 1); }), s.end());
// Show result
std::cout << s;
}
}
As you can see from title I want to change each character's ASCII value in struct data type.
For this example I chose name and I want to change lowercase characters to uppercase characters (a to A and so on). I am also reading data from .txt file.
The words I want to "change" are:
Kayak
Ahmed
Samed
Here is the code I got so far:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
struct letterStr
{
string name;
string object;
};
int main(int argc, char** argv)
{
ifstream letter;
letterStr things[200];
letter.open("pismo.txt");
ofstream novoPismo;
int numberOfThings= 0;
while(letter >> things[numberOfThings].name >> things[numberOfThings].object)
{
numberOfThings++;
}
for (int i = 0; i < numberOfThings; i++)
{
vector <letterStr> vec = {letterStr{things[i].name}};
for (auto obj : vec)
{
if (obj.name.at(i) > 'A' && obj.name.at(i) < 'Z');
obj.name.at(i) += 32;
cout << obj.name;
i++;
}
}
}
And here is the cout in console:
kayakSaìed
Well I think this
if (obj.name.at(i) > 'A' && obj.name.at(i) < 'Z');
obj.name.at(i) += 32;
Should have been written like this
if (obj.name.at(i) >= 'A' && obj.name.at(i) <= 'Z')
obj.name.at(i) += 32;
So >= not > and <= not <, but most importantly of all no semi-colon at the end of the if statement.
But there is an easier way
#include <cctype>
obj.name.at(i) = tolower((unsigned char)obj.name.at(i));
The tolower function converts an upper case letter into a lower case letter, and it works even if your system isn't using ASCII.
As you can see from the title I want to change lowercase charachter in word to uppercase and vice versa.
Also I need to use struct object (in my case name).
I have a problem when I change charachter from lowercase to uppercase it only changes in the first word not in the second,third and so on. I am also reading words from file
Here is the input file
Aayak Audi
Ahmed Golf7
Samed Golf5
Here is the code
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
struct pismaStr
{
string ime;
string objekat;
};
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break;
}
}
int main()
{
ifstream pismo;
pismo.open("pismo.txt");
ofstream novoPismo;
novoPismo.open("novaSlova.txt");
pismaStr stvari[200];
int brojStvari = 0;
while(pismo >> stvari[brojStvari].ime >> stvari[brojStvari].objekat)
{
brojStvari++;
}
for (int i = 0; i < brojStvari; i++)
{
vector <pismaStr> vec = {pismaStr{stvari[i].ime}};
for (auto obj : vec)
{
malaVelikaSlova (obj.ime);
}
}
Here is the output:
aayak
ahmed
samed
It was:
Aayak
ahmed
samed
I want it to look like this
aAYAK
sAMED
aHMED
How can I fix this?
Any tips?
Tangential,
but it will be an issue, is this line
for (int i = 0; i < name.length()-1; i++)
This will loop from name[0] to name[name.length() - 2]. The std::string::length returns the number of usable characters. It does not include the null terminator, so you don't need to subtract 1. It should be
for (int i = 0; i < name.length(); i++)
Your bigger problem
is the break statement at the end of your loop (indentation added for clarity)
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break; // <--- this exits the loop entirely
}
Your break; tells the program to exit the loop immediately. No further iterations of the loop are performed. Your cout statement is also within the loop. Once you do get the loop running for each iteration, you'll output each step of the transformation. To only output it once (at the end) you put it outside of the loop. If you want to loop over every character (and you do), your final code looks like
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length() - 1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
}
cout << name;
}
Other things you can change
You don't need to do bounds checking on your string indexes, since you're looping based on the string length, and it's not changing, so you don't need to extra overhead of std::string::at. You can just use the index operator:
// name.at(i); // <-- no need to do this anywhere
name[i] // <-- slightly faster
Since you're applying some operation to each element (character) in your container (string), this is a great candidate for std::transform, from the <algorithm> library. I'm also using a lambda expression here, which is a great too from C++ to get familiar with.
https://en.cppreference.com/w/cpp/algorithm/transform
https://en.cppreference.com/w/cpp/language/lambda
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](char c) -> char
{
if (c >= 'A' && c <= 'Z')
return c + 32;
if (c >= 'a' && c <= 'z')
return c - 32;
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
You could even take advantage of the std::isupper, std::islower, std::toupper, and std::tolower functions to make your code more explicit. Note that std::string is an alias for std::basic_string<char> (its value type is char), the upper and lower functions operate on unsigned chars, so you'll need to convert the chars to unsigned chars:
https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/string/byte/tolower
https://en.cppreference.com/w/cpp/string/byte/toupper
https://en.cppreference.com/w/cpp/string/byte/isupper
https://en.cppreference.com/w/cpp/string/byte/islower
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](unsigned char c) -> unsigned char // <-- must convert to unsigned to be safe with upper/lower functions
{
if std::isupper(c) return std::tolower(c);
if std::islower(c) return std::toupper(c);
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
I'm new to programming, so I created number guessing game which worked perfectly but I can't seem to finish with the word guessing code. My goal is to print "Congratulations" when the guessed string is correct, but I tried many ways and I still can't make it work.
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand(time(0));
int i;
const string wordList[17] = { "television",
"computer", "keyboard", "laptop", "mouse", "phone", "headphones",
"screen", "camera", "sound", "science", "programming",
"entertainment",
"graphics", "intelligent", "memory", "remote" };
string word = wordList[rand() % 17];
for(i = 0; i < word.length(); i++)
{
if(word[i] == 'a' || word[i] == 'e' || word[i] == 'i' ||
word[i] == 'o' || word[i] == 'u')
{
word[i] = '_';
}
}
cout << word << endl;
int n=0;
string x;
do
{
n++;
cin >> x;
}
while(x!=word[i]);
cout<<"Congratulations! You guessed the word!";
return 0;
}
I'd say most of your problems come down to this line:
while(x!=word[i]);
As the comments suggest, word is your modified word, not the word list. But also, i is the wrong index. So save the word index you chose earlier:
size_t wordIndex = rand() % 17;
string word = wordList[wordIndex];
Then change your do loop condition:
while (x != wordList[wordIndex]);
I'd also recommend that you don't use using namespace std;.
You could argue about the use of rand(), but it might not be worth it. Just be aware that rand() has shortcomings and better alternatives exist.
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;
}