I have to solve a task so it prints the min, the max and the mode of a set of strings. First I store the strings in a vector, than I sort them and then I print the first and the last of the elements of the vector, which is fine. But I have hard times finding the mode of them. Here is the code I wrote.
#include<stdafx.h>
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
vector<string>words;
cout << "Please enter some words. When finished, just enter 'stop'.\n";
string ant;
int count = 0;
int max = 0;
while (cin >> ant) {
if (ant != "stop") {
words.push_back(ant);
}
else
break;
}
sort(words.begin(), words.end());
cout << "The min of the entered words is " << words[0] << "\n";
cout << "The max of the entered words is " << words.back() << "\n";
}
So far this is good. It does the job as I want. But the problem comes when I have to find the mode of the strings. I found some code on the net for finding mode of given integers and it works for integers. I tried to modify it for strings but I could not get it to work. Here is the code:
for (string test = 0; test<words.size(); ++test) {
if (words[test] == words[test + 1]) {
count++;
}
else if (words[test] != words[test + 1]) {
if (count>max) {
max = count;
mode = words[test];
}
count = 0;
}
}
This gives me a lot of errors, I do not know where to begin. I think the problem is that this is not a proper way to make iteration of strings. I found some explanations about iteration of strings, but its so confusing for me. Any help will be appreciated.
Your modified version of the algorithm that finds the mode of the entered words is correct. The only thing i can say about it is, count and max are keywords in C++ so you'd have to change the names to avoid undesired effects. Also, don't forget to declare mode as type string.
With little modification of your code, this works;
#include<iostream>
#include<vector>
#include <map>
#include<string>
#include<algorithm>
using namespace std;
int main() {
vector<string>words;
cout << "Please enter some words. When finished, just enter 'stop'.\n";
string ant;
int count = 0;
int max = 0;
while (cin >> ant) {
if (ant != "stop") {
words.push_back(ant);
}
else
break;
}
sort(words.begin(), words.end());
cout << "The min of the entered words is " << words[0] << "\n";
cout << "The max of the entered words is " << words.back() << "\n";
//Finding the mode of the entered words
int _count = 0;
int _max = 0;
string mode;
for (unsigned int test = 0, j = 1; test<words.size(); test++, j++) {
if (words[test] == words[j]) {
_count++;
}
else if (words[test] != words[j]) {
if (_count>_max) {
_max = _count;
mode = words[test];
}
_count = 0;
}
}
cout << "The mode of the entered words is " << mode;
}
Related
I'm writing a wordcount function that should be able to read elements from stdin into a string. Then evaluate the string and return the number of words, number of lines, size of the string, and the number of unique words.
My issue is when it comes to adding words to the unique set. When I write it to add elements to a set, it would count the whitespace as part of the word then push entirely into my set.
Example:
Input:
this is
is
a test
test
Output
a
test
is test this
line is 4
Words = 7
size is 27
Unique is 6
It counts 7 words in total and 6 unique. I tried debugging it by printing bits of the code as i go so i can keep track of where I went wrong. I can only conclude that the issue lies within my if loops. How can I get past this, I've been stuck for some time now.
Here is my code:
#include<iostream>
#include<string>
#include<set>
using std::string;
using std::set;
using std::cin;
using std::cout;
set<string> UNIQUE;
size_t sfind(const string s) //will take string a count words, add to set
{
string a;
int linecount = 0;
int state = 0; //0 represents reading whitespace/tab, 1 = reading letter
int count = 0; //word count
for(size_t i =0; i < s.length(); i++) {
a+=s[i]; //add to new string to add to set
if(state ==0) { //start at whitespace
if(state != ' ' && state != '\t') { //we didnt read whitespace
count++;
state =1;
}
}
else if(s[i]== ' ' || s[i] == '\t' || s[i] == '\n') {
state = 0;
UNIQUE.insert(a); //add to UNIQUE words
a.clear(); // clear and reset the string
}
if (s[i] == '\n') {
linecount++;
}
}
for(set<string>::iterator i = UNIQUE.begin(); i!= UNIQUE.end(); i++) {
cout << *i;
}
cout << '\n';
cout << "line is " << linecount << '\n';
return count;
}
int main()
{
char c;
string s;
while(fread(&c,1,1,stdin)) {
s+=c; //read element add to string
}
cout << "Words = " << sfind(s) << '\n';
cout << "size is " << s.length() << '\n';
cout << "Unique is "<< UNIQUE.size() << '\n';
return 0;
}
Also I will be using
fread(&c,1,1,stdin)
because i will be using it later on with a larger wordcount function.
Rather than writing code trying to parse the string on spaces, use std::istringstream to do the parsing.
Here is an example:
#include <string>
#include <iostream>
#include <sstream>
#include <set>
int main()
{
std::set<std::string> stringSet;
std::string line;
while (std::getline(std::cin, line))
{
std::istringstream oneline(line);
std::string word;
while (oneline >> word)
{
std::cout << word << "\n";
stringSet.insert(word);
}
}
std::cout << "\n\nThere are " << stringSet.size() << " unique words";
}
Live Example
I have a completed code for my class; it creates a randomized string based on how many characters that the user asks for, and it then allows for the user to specify if they want to find a particular pair of characters in the string. That last part is based on a if/else statement that either gives the location, or is suppose to tell them there is no pair in the string.
My issue is that, when given a pair to find, if its in the string it gives the corrected statement, however, it also gives the else statement, repeated several times. if the pair is not in the string, it then gives the correct else statement, but repeats the cout several times. I don't know how to solve this issue.
Here is my code and screen shots of my outputs.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main() {
int i=0, n;
char alphabet[26];
char RandomStringArray [100];
char Ltr1, Ltr2;
srand(time(0));
cout <<"How many letters do you want in your random string (no less than 0, no more than 100): ";
cin >> n;
for (int i=0; i<=25; i++)
alphabet[i] = 'a' + i;
while(i<n) {
int temp = rand() % 26;
RandomStringArray[i] = alphabet[temp];
i++;
}
for(i=0; i<n; i++)
cout<<RandomStringArray[i];
cout<<"\n";
cout<<"What letter pair would you like to find? ";
cin>>Ltr1>>Ltr2;
for (i=0; i<n; i++)
if (Ltr1==RandomStringArray[i] && Ltr2== RandomStringArray[i+1]){
cout<<"The pair is in the string starting at character number "<<i+1<<" in the string. \n";
}
else if (Ltr1!=RandomStringArray[i] && Ltr2!= RandomStringArray[i+1])
cout<<"no";
return 0;
}
Your final for loop is looping through every character in the random string from begin to end, which is fine for searching, but it is outputting the result of comparing every character, which is not what you want. Don't display any output at all until the loop is finished, eg:
for (i = 0; i < (n-1); i++)
{
if (RandomStringArray[i] == Ltr1 && RandomStringArray[i+1] == Ltr2)
break;
}
if (i < (n-1))
cout << "The pair is in the string starting at character number " << i+1 << " in the string.\n";
else
cout << "The pair is not found in the string.\n";
I would suggest wrapping the search in a function, eg:
int findPair(const char *str, int len, char Letter1, char Letter2)
{
for (i = 0; i < (len-1); i++)
{
if (str[i] == Letter1 && str[i+1] == Letter2)
return i;
}
return -1;
}
...
i = findPair(RandomStringArray, n, Ltr1, Ltr2);
if (i != -1)
cout << "The pair is in the string starting at character number " << i+1 << " in the string.\n";
else
cout << "The pair is not found in the string.\n";
That being said, since you are using C++ anyway, you should go full C++, not a mix of C and C++, eg:
#include <iostream>
#include <string>
#include <random>
#include <algorithm>
int main() {
int n;
char alphabet[26];
std::string RandomString;
char LtrPair[2];
std::generate(std:begin(alphabet), std::end(alphabet), [ch = 'a'] () mutable { return ch++; } );
std::cout << "How many letters do you want in your random string: ";
std::cin >> n;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 25);
RandomString.resize(n);
std::generate(RandomString.begin(), RandomString.end(), [&](){ return alphabet[dis(gen)]; };
std::cout << RandomString << "\n";
std::cout << "What letter pair would you like to find? ";
cin >> LtrPair[0] >> LtrPair[1];
auto pos = RandomString.find(LtrPair, 0, 2);
if (pos != std::string::npos)
std::cout << "The pair is in the string starting at character number " << pos+1 << " in the string.\n";
else
std::cout << "The pair is not found in the string.\n";
return 0;
}
Since you have placed your if...else construct inside of a for loop, it is evaluated every time. This means that for every instance where the first condition isn't true, the else clause is executed, causing your "no" message to repeat.
I'm trying to have a user enter a number, and then have double check that they haven't already entered that particular number. I thought storing the user entered number in an array using one counter and then checking that same array with a for loop controlled counter would do the trick, but when I use the for loop counter in the array elements, it seems to always be zero. Can someone point me in the right direction here? I can't figure out what I'm doing wrong.
#include <iostream>
using namespace std;
int main() {
int guess[101] = { 0 };
int count = 0;
int check = 0;
while (guess[count] != 1) {
count++;
cout << "Enter an integer." << endl;
cin >> guess[count];
if (guess[count] == 0) {
return 0;
}
for (check = 0; check < count; check++) {
cout << guess[check] << endl;
if (guess[count] = guess[check]) {
cout << "You already guessed " << guess[check] << ". Try a different integer between 1 and 100.\n" << endl;
}
}
}
}
if (guess[count] == guess[check]) double equal to should be used for comparison.
For my assignment, I have to call a function that takes the user input and spits out the number of non-whitespace characters. Inside the program, I have this code:
int GetNumOfNonWSCharacters(const string givenText) {
int counter;
for (int i = 0; i < givenText.length(); i++) {
if (givenText.at(i) != ' ') {
counter++;
}
}
return counter;
}
When I return the counter integer, this is how I output it with the string sampleText being the input:
if (menuInput == 'c' || menuInput == 'C') {
cout << "Number of whitespaces: " << GetNumOfNonWSCharacters(sampleText) << endl;
}
It returns an answer like 1231341235 or something along those lines. Now, when I type this code into a different file, pretty sure it's identical, I get the correct result every time:
int NumNonWhitespaces(const string userInput) {
int counter;
for (int i = 0; i < userInput.length(); i++) {
if (userInput.at(i) != ' ') {
counter++;
}
}
return counter;
}
int main() {
string userString;
cout << "Enter some text" << endl;
getline(cin, userString);
cout << "You entered: " << userString << endl;
cout << NumNonWhitespaces(userString);
return 0;
}
Does anyone have a solution to the problem ?
There is even more simple way to count the number of non white spaces by using the STL count algorithm:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string userString;
cout << "Enter some text" << endl;
getline(cin, userString);
cout << "You entered: " << userString << endl;
//count the number of white spaces
int numberOfWhiteSpace = count(userString.begin(), userString.end(), ' ');
//substruct that number from the total length of your string
cout << "number of non-whitespace: " << userString.length() - numberOfWhiteSpace;
return 0;
}
But in your solution you have to initialize the variable counter to 0
If you use counter without initializing it first, you'll get whatever junk memory existed at its memory address before your program started using it (C++ does not automatically zero-out the memory when you declare a variable). The fact it works when you copy it into a new file is purely coincidental.
The fix is simply to initialize counter to 0 before using it:
int counter = 0;
In some programming languages if a variable is allocated but not assigned, it is said to have a "garbage value" , that is, some information that was being held any random piece of the computer's memory. So initialize the counter variable to 0
You have to initialise the counter variable otherwise it will contain any old value.
int counter=0;
Using C++, I'm trying to make a hangman game to become better at using C++ and programming in general. Anyways, the issue I'm facing is that I'm not sure how to replace the dashes within a string with the letter the user has guessed.
I think my problem is with the fact the word chosen is randomly chosen from an array and I'm not sure how to go about finding the positions within the randomly chosen string which consists of the guessed character.
I have commented out the area that's causing the issue.
#include <iostream>
#include <array>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <cstddef>
#include <algorithm>
using namespace std;
int main()
{
string words[3] = {"stack", "visual", "windows"};
string guess;
cout << "Welcome to hangman.\n";
cout << "\n";
srand(time(NULL));
int RandIndex = rand() % 3;
string selected = words[RandIndex];
for (int i = 1; i <= selected.size(); i++) {
cout << "_ ";
}
cout << "\n";
cout << "\nType in a letter: ";
cin >> guess;
cout << "\n";
if (selected.find(guess) != string::npos) {
/*for (int i = 1; i <= selected.size(); i++) {
if (selected.find(guess) != string::npos) {
cout << "_ ";
} else {
cout << guess << " ";
}
}*/
} else {
cout << "\nNay!\n";
cout << "\n";
}
cout << "\n";
cout << "\n";
system("PAUSE");
return 0;
}
I was thinking about using the replace() function but the problem I face here is that I'm not replacing the string within selected variable but sort of iterating through the word itself, if that made any sense whatsoever?
Use a second string, that is initialized with the underscores. If the find function doesn't return string::npos it returns the position in the string, and this is the same position you should change in the string with the underscores as well.
You actually need to use a second string to store the "guessed" string; this is because you need to keep track of all the guessed letters and display them.
something like :
string s ="test";
string t=""; //empty string
for(int i=0;i<s.size();i++)
t.append("_"); //initialize the guess string
cout<<t<<'\n';
char c;
cin >> c;
int pos = s.find(c); //get the first occurrence of the entered char
while(pos!=-1) //look for all occurrences and replaced them in the guess string
{
t.replace(pos,1,1,c);
pos = s.find(c, pos+1);
}
I think you need to maintain some extra state while looping - to keep track of which letters have / haven't been guessed.
You could add a new string current_state which is initially set to the same length as the word but all underscores. Then, when the player guesses a letter, you find all instances of that letter in the original word, and replace the underscore with the letter guessed, at all the positions found but in current_state.
First i would initialize a new string to show the hidden word:
string stringToDisplay = string( selected.length(), '_');
Then For each letter given by the user i would loop like this:
(assuming guess is letter)
size_t searchInitPos = 0;
size_t found = selected.find(guess, searchInitPos));
if (found == string::npos)
{
cout << "\nNay!\n";
cout << "\n";
}
while( found != string::npos)
{
stringToDisplay[found] = guess;
searchInitPos = found+1;
found = selected.find(guess, searchInitPos));
}
cout << stringToDisplay;
Hope this will help
I think it should be that:
string words[3] = {"stack", "visual", "windows"};
char guess;
string display;
cout << "Welcome to hangman.\n";
cout << "\n";
srand(time(NULL));
int RandIndex = rand() % 3;
string selected = words[RandIndex];
for (int i = 0; i < selected.size(); i++) {
display.insert(0, "_ ");
}
cout << display;
while(display.find("_ ") != string::npos) {
cout << "\n";
cout << "\nType in a letter: ";
cin >> guess;
cout << "\n";
bool flag = false;
for (int i = 0; i < selected.size(); i++) {
if (selected[i] == guess) {
display.replace(i*2, 1, 1, guess);
flag = true;
}
}
if (!flag) {
cout << "\nNay!\n";
cout << "\n";
} else {
cout << display;
}
}