I'm currently making a quick Hangman game and I'm struggling to take the correctly guessed letters from the word and insert them into the string that I show the user as they play the game. This is my code so far:
std::string word_to_guess = "ataamataesaa";
std::string word_to_fill(word_to_guess.length(), '-');
char user_guess = 'a';
for (auto &character : word_to_guess) {
if (character == user_guess) {
std::size_t index = word_to_guess.find(&character);
word_to_fill[index] = user_guess;
}
}
std::cout << word_to_fill;
This almost works however it ignores the last two As of the string to guess which I cannot understand.
"Find" will return only the first occurrence.
Instead of iterating over characters, iterate simultaneously over the indexes of both word_to_guess and word_to_fill.
for (int i = 0 ; i < word_to_fill.length ; ++i) {
if (word_to_guess[i] == user_guess) {
word_to_fill[i] = user_guess;
}
}
Related
I need to make a function that identifies the number of words by spaces (Ignoring trailing and leading ones). I'm having trouble with the equation that recognizes a space within the string variable. It doesn't count a space like it should. I should be getting the number "2" with the test case I have.
#include<iostream>
#include<string>
using namespace std;
void numWords(string phrase)
{
for (int index = 0; index < phrase.length(); index++)
int words = 0;
int space = 0;
if (phrase[index] == ' ')
{
words++;
space++;
}
}
if (space == 0) //This is for single words with no spaces
{
words++;
}
cout << words << endl;
}
int main()
{
string phrase;
int words = 0;
numWords("hello, world");
//A test case
return 0;
}
Problems with your code / your approach:
You haven't initialized the number of words.
You count words and spaces the exact same way - but they're not the same.
You haven't properly defined what's a word:
Does the empty string contain a word?
If a space delimits words, is there an empty word between two consecutive spaces?
What about punctuation marks, do they count as parts of words?
What about non-printing characters?
So, there's little wonder your output doesn't satisfy your expectations.
check the solution of "dash-tom-bang" in :
C++ function to count all the words in a string
a Copy of it
#include <cctype>
int CountWords(const char* str)
{
if (str == NULL)
return error_condition; // let the requirements define this...
bool inSpaces = true;
int numWords = 0;
while (*str != NULL)
{
if (std::isspace(*str))
{
inSpaces = true;
}
else if (inSpaces)
{
numWords++;
inSpaces = false;
}
++str;
}
return numWords;
}
I'm trying to replace every space character with '%20' in a string, and I'm thinking of using the built in replace function for the string class.
Currently, I have:
void replaceSpace(string& s)
{
int len = s.length();
string str = "%20";
for(int i = 0; i < len; i++) {
if(s[i] == ' ') {
s.replace(i, 1, str);
}
}
}
When I pass in the string "_a_b_c_e_f_g__", where the underscores represent space, my output is "%20a%20b%20c%20e_f_g__". Again, underscores represent space.
Why is that the spaces near the beginning of the string are replaced, but the spaces towards the end aren't?
You are making s longer with each replacement, but you are not updating len which is used in the loop condition.
Modifying the string that you are just scanning is like cutting the branch under your feet. It may work if you are careful, but in this case you aren't.
Namely, you take the string len at the beginning but with each replacement your string gets longer and you are pushing the replacement places further away (so you never reach all of them).
The correct way to cut this branch is from its end (tip) towards the trunk - this way you always have a safe footing:
void replaceSpace(string& s)
{
int len = s.length();
string str = "%20";
for(int i = len - 1; i >= 0; i--) {
if(s[i] == ' ') {
s.replace(i, 1, str);
}
}
}
You're growing the string but only looping to its initial size.
Looping over a collection while modifying it is very prone to error.
Here's a solution that doesn't:
void replace(string& s)
{
string s1;
std::for_each(s.begin(),
s.end(),
[&](char c) {
if (c == ' ') s1 += "%20";
else s1 += c;
});
s.swap(s1);
}
As others have already mentioned, the problem is you're using the initial string length in your loop, but the string gets bigger along the way. Your loop never reaches the end of the string.
You have a number of ways to fix this. You can correct your solution and make sure you go to the end of the string as it is now, not as it was before you started looping.
Or you can use #molbdnilo 's way, which creates a copy of the string along the way.
Or you can use something like this:
std::string input = " a b c e f g ";
std::string::size_type pos = 0;
while ((pos = input.find(' ', pos)) != std::string::npos)
{
input.replace(pos, 1, "%20");
}
Here's a function that can make it easier for you:
string replace_char_str(string str, string find_str, string replace_str)
{
size_t pos = 0;
for ( pos = str.find(find_str); pos != std::string::npos; pos = str.find(find_str,pos) )
{
str.replace(pos ,1, replace_str);
}
return str;
}
So if when you want to replace the spaces, try it like this:
string new_str = replace_char_str(yourstring, " ", "%20");
Hope this helps you ! :)
Hey I'm quite new to programming and I'm having trouble using the isalpha function in my programme. This a part of the code for a palindrome class. What I'm trying to do is remove all the non alphabetic characters from the input. So if the user inputs "Hi, How are you" I need to first count the size of the array of just the letters then in my removeNonLetters subclass, I need to get rid of the non alphabetical characters. Can someone please help me with this. Thank you so much!
#include <iostream>
#include <string>
#include <stdio.h>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <ctype.h>
using namespace std;
class palindrome
{
private:
int only_letters_size;
string input_phrase;
string* only_letters;
public:
string inputPhrase();
string removeNonLetters();
string* new_Array;
int size_new_Array;
};
string palindrome::inputPhrase()
{
cout << "Input phrase: "; //asks the user for the input
getline(cin,input_phrase);
size_new_Array = input_phrase.length(); //creating a dynamic array to store
the input phrase
new_Array = new string[size_new_Array];
int i;
for (i=0; i<size_new_Array; i++)
{
new_Array[i]=input_phrase[i];
}
only_letters_size = 0;
while(new_Array[i])
{
if (isalpha(new_Array[i])) //PROBLEM OCCURS HERE
{
only_letters_size=only_letters_size+1;
}
}
cout << only_letters_size << endl;
return new_Array;
}
string palindrome::removeNonLetters()
{
int j=0;
int str_length = new_Array.length(); //string length
only_letters = new string[only_letters_size];
for (int i=0;i<size_new_Array;i++) //PROBLEM OCCURS HERE AS WELL
{
if (isalpha(new_Array[i]))//a command that checks for characters
{
only_letters[j] = new_Array[i];//word without non alphabetical c
characters is stored to new variable
j++;
}
}
cout << only_letters << endl;
return only_letters;
}
I've found the best way to determine if a string is a palindrome is to walk toward the center from both sides. In your case I would just opt to skip non-alpha characters like so.
bool is_palindrome(string mystring)
{
int start = 0, end = mystring.length() - 1;
while (start < end)
{
// Skip over non-alpha characters
while (!isalpha(mystring[start]))
{
start++;
}
while (!isalpha(mystring[end]))
{
end--;
}
if (tolower(mystring[start]) != tolower(mystring[end]))
{
return false;
}
else
{
start++;
end--;
}
}
return true;
}
If you must save the input first and remove nonalpha characters, I would do it like this.
string remove_non_alpha(string mystring)
{
string ret_string = "";
for (int i = 0; i < mystring.length(); i++)
{
if (isalpha(mystring[i]))
{
ret_string += tolower(mystring[i]);
}
}
return ret_string;
}
And then feed the result into the above function.
Sorry for being hard, but your trying far too much copying around. You can achieve all this with one single loop after retrieving your data and all on one single string object (unless you want to keep the original input for some other purposes):
getline(cin,input_phrase);
std::string::iterator pos = input_phrase.begin();
for(char c : input_phrase)
{
if(isalpha(c))
{
*pos++ = tolower(c);
}
}
input_phrase.erase(pos, input_phrase.end());
After that, your string is ready to use...
Explanation:
std::string::iterator pos = input_phrase.begin();
An iterator something similar than a pointer to the internal data of the string. We keep the position to move the alpha only characters to, skipping the non-alpha ones.
for(char c : input_phrase)
Simply iterating over all characters...
if(isalpha(c))
The essential check, is the current character an alpha one?
*pos++ = tolower(c);
If so, convert it to lower case immediately. Assign it to the current string position, and advance the "pointer" (iterator!).
input_phrase.erase(pos, input_phrase.end());
And at very last, drop the remaining part of the string occupied with surplus characters. You might note that there might be some characters you wanted to keep within, but you copied these to a position more to the left already...
I try with the following code to check if the string contain specific characters, but i want to check if this characters in order way this my code
string string1= "Amed";
string string2= "Anbhsmegfd";
std::string x(string1);
if (x.find_first_not_of(string2) != std::string::npos)
{
std::cerr << "Error\n";
}
in my code check if the string contain characters that give string1 but i want to check if find this character in order way
as an example
string1 ="Amed";
string2= "Aehdkm"
the string1 found in string2
but i need the output will be error because e appear before m
how can i make that ?
Would something like this work for you?
string s1 = "Amed";
string s2 = "Aehkm";
size_t k = 0;
for (size_t i = 0; i < s2.size(); ++i)
if (s1[k] == s2[i]) {
k++;
if (k == s1.size()) {
cout << "found" << endl;
break;
}
}
just write the code.Here is psuedo code, I leave it to you to convert to c++
char* s = str2
foreach (char c in str1)
char *find = indexof(s, c)
if(!find)
error;
s = find
ie - look for the first char - if found move pointer to where you found that char and search for next char, else fail
Been working on this program which requires the use of a function that compares a string input by the user and gives the user the opportunity to leave the characters that he/she doesn't know out of the input, replacing them with * . The input represents a license-plate of a car that has 6 characters (for instance ABC123) and the user is allowed to leave any of those characters out (for instance AB** 23 or ** C12* etc.). So the function needs to return all objects that match the characters in the right position, but it cannot return if, say, A is in the right position but any of the other characters are not. The user is, however, allowed to only enter A* * * * *, for instance, and the function should return all objects that have A in the first position.
What I did was use a function to remove all the asterisks from the input string, then create sub-strings and send them to the function as a vector.
string removeAsterisk(string &rStr)// Function to remove asterisks from the string, if any.
{
stringstream strStream;
string delimiters = "*";
size_t current;
size_t next = -1;
do
{
current = next + 1;
next = rStr.find_first_of( delimiters, current );
strStream << rStr.substr( current, next - current ) << " ";
}
while (next != string::npos);
return strStream.str();
}
int main()
{
string newLicensePlateIn;
newLicensePlateIn = removeAsterisk(licensePlateIn);
string buf; // Have a buffer string
stringstream ss(newLicensePlateIn); // Insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf)
tokens.push_back(buf);
myRegister.showAllLicense(tokens);
}
The class function that receives the vector currently looks something like this:
void VehicleRegister::showAllLicense(vector<string>& tokens)//NOT FUNCTIONAL
{
cout << "\nShowing all matching vehicles: " << endl;
for (int i = 0; i < nrOfVehicles; i++)
{
if(tokens[i].compare(vehicles[i]->getLicensePlate()) == 0)
{
cout << vehicles[i]->toString() << endl;
}
}
}
If anyone understand what I'm trying to do and might have some ideas, please feel free to reply, I would appreciate any advice.
Thanks for reading this/ A.
Just iterate through the characters, comparing one at a time. If either character is an asterisk, consider that a match, otherwise compare them for equality. For example:
bool LicensePlateMatch(std::string const & lhs, std::string const & rhs)
{
assert(lhs.size() == 6);
assert(rhs.size() == 6);
for (int i=0; i<6; ++i)
{
if (lhs[i] == '*' || rhs[i] == '*')
continue;
if (lhs[i] != rhs[i])
return false;
}
return true;
}
Actually, you don't have to restrict it to 6 characters. You may want to allow for vanity plates. In that case, just ensure both strings have the same length, then iterate through all the character positions instead of hardcoding 6 in there.