C++ comparing Char to Strings - c++

I'm trying to loop through a word but only vowels are working for some reason. The other type prints out the amount of words in total. Please excuse my poor choise of words mixed with Swedish and English.
#include <iostream>
using namespace std;
int main()
{
int vo = 0;
int ko = 0;
char vocals[7]
{
'A','O','U','E','I','Y'
};
char konsonanter[19]
{
'B','C','D','F','G','H','J','K','L','M','N','P','Q','R','S','T','V','X','Z'
};
string word = "Toysoldier";
for(int i = 0; i < word.length(); i++)
{
for(int v = 0; v < vocals[v]; v++)
{
if(vocals[v] == word[i])
vo++;
}
for(int k = 0; k < konsonanter[k]; k++)
{
if(konsonanter[k] == word[i])
ko++;
}
}
cout << "Konsonanter = " << ko << " Vokaler = " << vo << endl;
}

You got your loop condition wrong.
Instead of v < vocals[v] you probably meant to write v < 7 as there are 7 vocals in your array.
Writing v < vocals[v] is not an error as v is initialized to zero while the expression vocals[v] is a char which can also be used in array subscripts ('A' is translated to 65, 'E' to 69 and so on).
The same problem exists in the loop for consonants.

You have more than one bug, so I'll just remark on all the code in order.
If you write
char vocals[7] = {'A' ... 'Y'};
you have to manually keep the array size and the initializer in sync - here, for example, you missed one (you have 6 "vocals" in your initializer for a 7-element array).
It's less error-prone to write
char vowels[] = {'A', 'E', 'I', 'O', 'U'};
and let the compiler count it for you. (I renamed it to "vowels" because that's what they're called in English, and removed 'Y' because it's not one - obviously you can stick with whatever works in Swedish.)
Similarly, this loop is wrong:
for(int v = 0; v < vocals[v]; v++)
because you're comparing v (an index into your array) with vocals[v] which is a character value. They're two different types of thing, and comparing doesn't make sense here. The loop over an array would normally be written
for (int v = 0; v < sizeof(vocals)/sizeof(vocals[0]); ++v)
so for some N-element array, the index v ranges from 0 to N-1. A simpler way is to just write
for (auto v : vocals)
where v is now a character, taking the value of each vocal/vowel one-by-one in the loop body. The compiler can figure out the array size for you.
I'd honestly re-write all your loops in this style: you don't need to manage array indices and bounds manually unless you're doing something more complicated.
On top of the loop condition bugs, your character comparisons will anyway mostly fail: the vowel/vocal and consonant arrays both contain only upper-case letters, and your string is mostly lower-case. You need to manage this, for example with
#include <cctype>
// ...
for (auto c : word) {
for (auto v : vowels) {
if (v == std::toupper(c)) {

Your error is in the tests used in the "for" loops:
v < vocals[v] will compare the integer v to the integer value of the character vocals[v], which happens to be the ASCII code of that character (in practice, that'll be something between 65 and 90, look up "Ascii table" on the web).
To fix your code, you should modify your "for" loops like this:
for (char vocal : vocals) {
if (word[i] == vocal) vo++;
}
for (char konsonant : konsonanter) {
if (word[i] == vocal) ko++;
}
Also, note that you got the number of vocals wrong in your "vocals" array: it's 6, not 7.

You conditions in the loops are flawed, you should use 'for (int v = 0; v < sizeof(vocals); v++)`.
Also, check your condition for a vocal and consonant: What happens if you consider lowercase chars? 'a' != 'A', so you don't count them correctly.
Hint: Use toupper() or tolower() so you don't need to have excessive lists of chars.

Related

Replacing Items In Vector C++

So I'm supposed to write a function that takes a vector of strings and sort it alphabetically but based on the last character of each string. For example, {“apple”, “banana”, “carrot”}, would be {“banana“, “apple“, “carrot”} because the last “a” in banana comes before the “e” in “apple” and the “t” in “carrot”.
This is my code so far:
#include <iostream>
#include <vector>
#include <string>
void SortByReverse(std::vector<std::string> &v)
{
std::vector<int> int_v;
for(int i = 0; i < v.size(); i++) // for loop to store ascii values of each last ch
{
int last_ch_index = v[i].size() - 1;
int_v.push_back(int(v[i][last_ch_index]));
std::sort(int_v.begin(), int_v.end()); // sort ascii value vector in ascending order
}
for(int u = 0; u < int_v.size(); u++) // iterate through ascii values vector and print corresponding str
{
for(int q = 0; q < v.size(); q++)
{
int last_ch_index = v[q].size() - 1;
if(int_v[u] == int(v[q][last_ch_index]))
{
std::cout << v[q] << "\n";
}
}
}
}
int main()
{
std::vector<std::string> v = {"apple", "banana", "carrot"};
SortByReverse(v);
}
which outputs my strings in the correct order but I don't know how to change the order in the vector itself. I tried doing
v[u] = v[q]
but that outputs "banana, banana, carrot" because it assigns "banana" to "apple" to when "apple" is supposed to be printed, you just get "banana" again. Surely there is a way to add on to the code I already have and fix this issue but I don't know how.
If sorting the original vector by back letter is your goal, there is much neater method:
std::sort(v.begin(),v.end(),[](string& lhs, string& rhs)(return <expr>;)); will sort the std::string vector by the <expr> criteria. make <expr> expression return true or false based on the back letter.
std::string has member function back() which has access to the back element, which is last char.
As #paddy pointed out, if you wish to make stable program, make <expr> able to handle empty string & error check.
As your program seems to be a homework, you figure out where to put it.

Make floor pattern

How do i make this?
image of my homework
note: Batasan means limitaion and Contoh means example
So, my professor wants me to do make output the same size horizontal and vertically in pattern shown in the image
I dont know what to do, but the best i can make is this:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
const char * array1[4];
const char * array2[4];
array1[0] = "O", array1[1] = ">", array1[2] = "X", array1[3] = "<";
array2[0] = "v", array2[1] = "/", array2[2] = "^", array2[3] = "\\";
cin>>n;
for(int i = 1; i <= n; i++){
if (i%2 != 0){
for(int j = 0; j <=n; j++){
cout << array1[j];
}
cout<<"\n";
} else if (i%2 != 0) {
for(int j = 0; j <=n; j++){
cout << array2[j];
}
cout<<"\n";
}
return 0;
}
}
I dont know if array is necessary or not.
If you guys have any suggestion about my program feel free to give me some.
This is my first time asking in this web and im sorry if my post and english are terrible
Thanks in advance:)
We are here to help.
I will first show you the problems in your code and then make a proposal on how to make it better.
So, let us first check your code:
#include<bits/stdc++.h> is a non C++ compliant compiler extension. It should never be used. On my machine, it does not compile.
using namespace std; should not be used. It is better to always use full qualified names. This will avoid name clashes from different scopes or namespaces
Variables should have meaningful names. One character variables are in most cases not that good
All variables should be initialized during definition
C-Style arrays should not be used in C++. Always use a specialized STL container like std::vector or std::array
In C++ we use std::string for strings and not char[] or char *
Array indices in C/C++ start with 0. If you use <= in the end condition of a for loop, you will access an element one past the end. This is a severe out of bound error. You do that in you for loop with the 'j'
There is anyway a severe out of bound bug here. You access array[j] and j might be 4 or bigger. That is a bug and must be corrected. You can simply do a modulo devision % by 4. Then you do never exceed the 4. it will then always be 0,1,2,3,0,1,2,3,0,1,2,3 . . .
You should write as much as possible comments
If we correct all this findings, then we could come up with:
#include <array>
#include <iostream>
constexpr size_t NumberOfLinePatterns = 2;
constexpr size_t NumberOfElementsPerLinePattern = 4;
using Pattern = std::array<std::array<char, NumberOfElementsPerLinePattern>, NumberOfLinePatterns>;
// If you do not yet know the std::array. Then uncomment the following and
// remove on opening and closing curly brace in the initialization below
// using Pattern = char[NumberOfLinePatterns][NumberOfElementsPerLinePattern];
Pattern pattern{{
{'O','>','X','<'},
{'v','/','^','\\'}
}};
int main() {
// Get number of rows and columns to print
unsigned int numberOfElements{}; std::cin >> numberOfElements;
// Now, for all rows and columns
for (unsigned int row{}; row < numberOfElements; ++row) {
for (unsigned int column{}; column < numberOfElements; ++column) {
// Print the selected character
std::cout << pattern[row % NumberOfLinePatterns][column % NumberOfElementsPerLinePattern];
}
std::cout << '\n';
}
return 0;
}

looking for a faster way to help reduce/create a huge list of strings

I tried to write an algorithm to guess correctly in the game "Masterminds",
it works the average number of guesses is 6, but it takes a lot of time to calculate the best guess.
I used the idea of Knuth the algorithm works as follows:
Create the set S of 1296 possible codes (1111, 1112 ... 6665, 6666).
Start with initial guess 1122 (Knuth gives examples showing that other first guesses such as 1123, 1234 do not win in five tries on
every code).
Play the guess to get a response of colored and white pegs.
If the response is four colored pegs, the game is won, the algorithm terminates.
Otherwise, remove from S any code that would not give the same response if the current guess were the code.
In my code step 2 is to take random number.
I used vector<string> for this.
AllPoss is the vector full of strings, I guess is the last guess that was used. answer is the count of bulls and cows looks like "x,y" (where x and y are numbers)
void bullpgia::SmartGuesser::remove(string guess, string answer)
{
for (auto i= AllPoss.begin();i != AllPoss.end();i++){
string token = *i;
if (calculateBullAndPgia(token, guess) != answer)
AllPoss.erase(i--);
}
}
this is the part it take a lot of time to calculate is there any way of improvement?
to creating the list i used :
void bullpgia::SmartGuesser::All() {
/**
* creates a pool of all the possibilities strings
* we then delete the ones we dont need
* #param length is the length of the word we need to guess
*/
for(int i=0;i<pow(10,length);i++){
stringstream ss;
ss << setw(length) << setfill('0') << i;
string s = ss.str();
AllPoss.push_back(s);
}
}
the function calculateBullAndPgia(string , string) is:
string calculateBullAndPgia(const string &choice, const string &guess) {
string temp = choice;
string temp2 = guess;
unsigned int bull = 0;
unsigned int pgia = 0;
for (int i = 0; i < temp.length(); i++) {
if (temp[i] == temp2[i]) {
bull++;
temp[i] = 'a';
temp2[i] = 'z';
}
}
for (int i = 0; i < temp.length(); i++) {
for (int j = 0; j < temp2.length(); j++) {
if (i != j && temp[i] == temp2[j]) {
pgia++;
temp[i] = 'a';
temp2[j] = 'z';
}
}
}
return to_string(bull) + "," + to_string(pgia);
}
Erasing a single element in the middle of a vector is O(n). My guess is that you wind up doing it O(n) times per call to SmartGuesser::remove. Then you loop over that so you probably have a O(n^3) algorithm. You instead could use std::remove_if, which is O(n), to move all the to-be-erased elements to the end of the vector where they can be cheaply erased.:
AllPoss.erase(std::remove_if(AllPos.begin(), AllPos.end(), [&](const std::string& token, const std::string& guess) { return calculateBullAndPgia(token, guess) != answer; }), AllPos.end());

Though ran for for a while but Program has stopped working?

There is neither anything wrong nor it is an infinity loop then why this is happening? I am trying to analyze but I couldn't find out the reason as I am real beginner of c++ language! :) Thank you in advance! Have a good day!
#include<iostream>
using namespace std;
main()
{
char UPPERCASE[27];
char LOWERCASE[27];
int j = 97;
for (int i = 65; i <= 90 && j <= 122; i++ && j++) {
UPPERCASE[i] = i;
LOWERCASE[j] = j;
cout << UPPERCASE[i];
cout << LOWERCASE[j] << endl;
}
}
The "&&" in for increment portion is very confusing.
I have rewritten this using only one index.
The original code uses a base index of 65 and 97. However, the array itself only is allocated with 27 cells. This will not work.
To solve this, I allocated 26 cells for each array (only 26 letters in the English alphabet) and then put 'A' and 'a' in cell [0] of each array.
#include<iostream>
int main(){
char upperCaseArray[26];
char lowerCaseArray[26];
for(int i=0; i < 26; i++){
upperCaseArray[i]=(char) i + 'A';
lowerCaseArray[i]=(char) i + 'a';
std::cout << upperCaseArray[i];
std::cout << lowerCaseArray[i] << std::endl;
}
}
The values of each cell should be the '65', '66', and so forth (i.e. 'A', 'B' ...). But, we can use the actual letter 'A' instead of the decimal value of 65, avoiding a mistake caused by writing down the wrong value.
So, we add the index of the cell to the value of the letter and store that, rather than using the value as the index.
I have reduced this to only one index, used in both arrays, so we do not need i and j.

C++, return duplicate instances from an array to a string

Background to this: This is not homework, it's completely optional review for a basic c++ class. As I want to pass, I'm going through each example the best I can, This one I'm super stuck on, and have been for about three hours now.
Problem: Write a function to return a string composed of the most frequent lowercase letter found in each row of a 10 x 10 array of lowercase alphabetic chars in the range a through z.
If there is more than one most frequent character, use the one that come first alphabetically.
Use neither cin nor cout.
#include <iostream>
#include <string>
using namespace std;
string mostFrequent(char c[10][10]){
// this is the function I need to create
}
int main(){
char c[10][10] = {
'a','b','f','d','e','f','g','h','i','j',
'a','b','c','r','c','r','g','h','r','j',
'a','b','c','d','e','f','g','h','o','o',
'z','w','p','d','e','f','g','h','i','j',
'o','d','o','d','o','b','o','d','o','d',
'a','l','l','d','e','f','f','h','l','j',
'a','b','c','d','i','f','g','h','i','j',
'a','b','z','v','z','v','g','g','v','z',
'a','b','c','d','e','f','g','h','i','e',
'a','b','s','d','e','f','g','h','s','j',
};
cout << mostFrequent(c) << endl;
return 0;
}
So in research for this I found some material that allows me to count how many times a specific int or char would appear inside the array, but it doesn't quite suit the needs of the problem as it needs to return a string composed of the most frequent character. See below.
int myints[] = {10,20,30,30,20,10,10,20};
int mycount = std::count (myints, myints+8, 10);
Because it doesn't work though, I was thinking a for loop, to go row to row, I'll mostly likely need to save things into an array to count, but I'm not sure at all how to implement something like that. I even considered a caesar shift with an array, but I'm not sure where to go if that is the solution.
If I understood the task correctly, you have a matrix 10x10 and you have to create a string of length 10, where character at position i is the one that is most frequent among characters in the row i.
string mostFrequent(char c[10][10]) {
// The idea here is to find the most common character in each row and then append that character to the string
string s = "";
for (int i = 0; i < 10; i++) s += findMostFrequentCharacter(c[i]);
return s;
}
Now we just have to implement a function char findMostFrequentCharacter(char c). We are going to do that by counting all of the characters and picking the one that is most frequent (or it comes alphabetically before if there is more than one most frequent character):
char findMostFrequentCharacter(char c[10]) {
int counts[256]; // Assuming these are ASCII characters, we can have max 256 different values
// Fill it with zeroes (you can use memset to do that, but for clarity I'll write a for-loop
for (int i = 0; i < 256; i++) c[i] = 0;
// Do the actual counting
for (int i = 0; i < 10; i++) // For each character
counts[ c[i] ]++; // Increase it's count by 1, note that c[i] is going to have values between 65 (upper case A) and 122 (lower case z)
char mostFrequent = 0;
// Find the one that is most frequent
for (char ch = 'A'; ch <= 'z' ch++) // This will ensure that we iterate over all upper and lower case letters (+ some more but we don't care about it)
if (counts[ch] > counts[c]) c = ch; // Take the one that is more frequent, note that in case they have the same count nothing will happen which is what we want since we are iterating through characters in alphabetical order
return c;
}
I have written the code out of my head so I'm sorry if there are any compile errors.