vector loop not reaching all elements - c++

I have the following piece of code that takes in some words, stores them into a vector, sorts them, then counts how many times each word appears and outputs it:
typedef vector<double>::size_type vec_sz;
vector<string> words;
string c;
cout << "Enter some words!" << endl << endl;
while (cin >> c) {
words.push_back(c);
}
vec_sz size = words.size();
sort(words.begin(), words.end());
string current_word = words[0];
int count = 1;
for (int i = 1; i < size; i++) {
if (words[i] == current_word) {
count++;
}
else {
cout << "The word " + current_word + " appears " << count << " times." << endl;
current_word = words[i];
count = 1;
}
}
I enter some words:
word
word
lol
hello
lol
word
hello
^Z
I then get the following output:
The word hello appears 2 times.
The word lol appears 2 times.
But it never reaches the final set of words. I changed my loop to just print out each element in the vector and it does print out all of them. But for some reason this loop does not want to reach the final set of words. What is going wrong?

The last word is being reached, here:
else {
// Previous word printed
cout << "The word " + current_word + " appears " << count << " times." << endl;
// current_word set to last word
current_word = words[i];
count = 1;
}
And then the loop exits. So, you would need a final line outside the loop to print the last word and its count.

The count message is only printed when a different word is found. When the last word is found, a different word is not encountered so a message is not printed. You need a piece of code after the for to print out the count for last word.
There are other ways to achieve this, using a std::map<std::string, unsigned int> for example:
map<string, unsigned int> word_counts;
string c;
cout << "Enter some words!" << endl << endl;
while (cin >> c) {
word_counts[c]++;
}
for (map<string, unsigned int>::iterator wci = word_counts.begin();
wci != word_counts.end();
wci++)
{
cout << "The word " << wci->first << " appears " << wci->second << "times.";
}

Related

C++ how to split string with alphabets and numbers

I have a need to split the following string into their corresponding alpahbets and numbers
CH1000003
ABC000123
WXYZ10001
Results I want are
st1: CH
st2: 1000003
st1: ABC
st2: 000123
st1: WXYZ
st2: 10001
Now I do have a working code but the amount of code I have written seems a bit too much. There has to be an easy way. Perhaps somehow use regex in C++? Suggestions?
My code:
std::string idToCheckStr="CH1000003";
//find length of string
int strLength = idToCheckStr.length();
cout << "idToCheckStr: " << idToCheckStr <<endl;
cout << "strLength : " << strLength <<endl;
string::iterator it;
int index = 0;
for ( it = idToCheckStr.begin() ; it < idToCheckStr.end(); it++ ,index++)
{
//check where the numbers start in the string
if (std::isdigit(*it) != 0)
{
cout<< "FOUND NUMBER!" <<endl;
cout<< index << ": " << *it <<endl;
break;
}
cout<< index << ": " << *it <<endl;
}
std::string firstPartStr = idToCheckStr.substr (0,index);
cout << "firstPartStr: " << firstPartStr <<endl;
std::string secondPartStr = idToCheckStr.substr (index,strLength);
cout << "secondPartStr: " << secondPartStr <<endl;
OUTPUT:
idToCheckStr: CH1000003
strLength : 9
0: C
1: H
FOUND NUMBER!
2: 1
firstPartStr: CH
secondPartStr: 1000003
Thanks to igor.
size_t first_digit = idToCheckStr.find_first_of("0123456789");
cout << "first_digit: " << first_digit <<endl;
std::string str1 = idToCheckStr.substr (0,first_digit);
cout << "str1: " << str1 <<endl;
std::string str2 = idToCheckStr.substr (first_digit,idToCheckStr.length());
cout << "str2: " << str2 <<endl;
OUTPUT:
first_digit: 2
str1: CH
str2: 1000003
Here is one of the simple ways to handle your problem.
I find this more understandable for you.
string s = "CH1000003";
// cin >> s; if you waant to read the input
string st1 = "", st2 = "";
for(auto ch : s) {
if(isdigit(ch)) st2 += ch;
else if(isalpha(ch)) st1 += ch;
else {} // if you want something else
}
cout << "st1: " << st1 << endl;
cout << "st2: " << st2 << endl;
You could indeed use regular expressions for this:
The pattern would be ([A-Z]+)([0-9]+), i.e. any combination of 1 or more uppercase letters followed by any combination of 1 or more numbers. The parentheses allow you to capture those 2 groups to be able to access them later on.
std::regex_match(line, matches, pattern) takes an input line, and tries to match it against a pattern. If it can, stores the matches in a std::smatch array; where the first entry is always the whole match, and the successive ones are for each capturing group. If it can't, it just returns false.
Should you need to relax the regular expression, e.g. allowing white spaces before, after, or in the middle of the input string, you could do it easily just changing the pattern: \s*([A-Z]+)\s*([0-9]+)\s*.
[Demo]
#include <fmt/core.h>
#include <iostream> // cout
#include <regex> // regex_match, smatch
#include <string>
int main() {
std::string line{};
std::regex pattern{R"(([A-Z]+)([0-9]+))"};
while (std::getline(std::cin, line)) {
std::smatch matches{};
if (std::regex_match(line, matches, pattern)) {
std::cout << fmt::format("line = '{}', alphabets = '{}', numbers = '{}'\n",
matches[0].str(), matches[1].str(), matches[2].str());
}
}
}
// Outputs:
//
// line = 'CH1000003', alphabets = 'CH', numbers = '1000003'
// line = 'ABC000123', alphabets = 'ABC', numbers = '000123'
// line = 'WXYZ10001', alphabets = 'WXYZ', numbers = '10001'

Can't exit for-loop, seemingly stuck

I recently picked up coding C++ and I was learning using Bjarne Stroustrup's introductory book, and I was presented with this code:
// simple dictionary: list of sorted words
int main() {
vector<string> words;
for(string temp; cin>>temp;) // read whitespace-separated words
words.push_back(temp); // put into vector
cout << "Number of words: " << words.size() << '\n';
sort(words); // sort the words
for (int i = 0; i < words.size(); ++i)
if (i == 0 || words[i–1] != words[i]) // is this a new word?
cout << words[i] << '\n';
}
That I replicated myself:
int main() {
//variables.
vector<string> dictionary;
//prompts user to input words.
cout << "input words in the dictionary:" << endl;
while (dictionary.size() < 10) {
for (string word; cin >> word;) {
dictionary.push_back(word);
}
}
//prints out number of words in the dictionary.
cout << "number of words in the dictionary:" << dictionary.size() << endl;
//sort the words and prints them out one by one, checking for repetitions.
sort(dictionary.begin(), dictionary.end());
for (int i = 0; i < dictionary.size(); ++i)
if ((i == 0) || (dictionary[i-1] != dictionary[i]))
cout << dictionary[i] << '\t';
return 0;
}
But here's the problem, I can't exit the initial loop of inserting words inside the dictionary (the while loop I added was to try to fix it, but it seemingly doesn't work either).
Thank you for your time :).
The inner for loop will run until cin >> word is false which might not be the case if you keep adding valid strings. Moreover you do not need an extra while wrapping the for-loop. You can just do something like below or add a break statement when necessary.
for (string word; cin >> word && dictionary.size() <10;) {
dictionary.push_back(word);
}

Outputting vowels and consonants from strings in c++

This is the question I have to answer:
Write a program that declares two strings: s1 and s2.
Initialize both of them using getline(cin, string) function.
a) Output the length of each string
b) Output the first appearance of a letter a in the first string
c) Output the first appearance of a letter b in the second string
d) Output the first word of each string
e) Output the last word of each string
f) Output first sentence reversed
g) Output second sentence with the words reversed ( the last word goes first, second last second, and so on)
h) Output the total number of vowels in the first sentence
i) Output the total number of consonants in the second sentence
This is what I have so far:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1,s2,s3;
int blank = 0;
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int s2temp = 0;
cout << "enter two sentences" <<endl;
getline (cin, s1);
getline (cin, s2);
s3=s2;
// a
cout << "the length of the first string is " << s1.length() << endl;
cout << "the length of the second string is " << s2.length() << endl;
// b
cout<<"the first appearance of the letter 'A' in the first string is ";
cout << s1.find("a");
cout <<endl;
// c
cout<<"the first appearance of the letter 'B' in the second string is ";
cout << s2.find("b");
cout <<endl;
// d
int s1_first = s1.find(" ");
int s2_first = s2.find(" ");
cout << "the first word in the first string is " << s1.substr(0,s1_first) <<endl;
cout << "the first word in the second string is " << s2.substr(0,s2_first) <<endl;
// e
cout << "the last word in the first string is " << s1.substr(s1.find_last_of(" "), s1.length()-1) <<endl;
cout << "the last word in the second string is " << s2.substr(s2.find_last_of(" "), s2.length()-1) <<endl;
// f
for(int i = s1.length()-1; i >= 0; i--)
cout <<s1.substr (i,1)<<endl;
// g
return 0;
}
I’ve tried a few different things for g, h, and i, but none have worked, so I thought I’d ask for help.
One method for counting vowels is to make a string containing vowels:
static const std::string vowels = "aeiouAEIOU";
Next, for each character in your string, search for it in the vowels string:
unsigned int vowel_count = 0;
const size_t length = text.length();
for (unsigned int i = 0; i < length; ++i)
{
const char c = text[i];
if (vowels.find(c) != std::string::npos)
{
++vowel_count;
}
}
This can be applied to consonants as well.
The code can be modified for those who are not allowed to use std::string.
Another method is to use std::map.

How do I print the number of words that begin with a certain character?

This is for an intro c++ class, the prompt reads:
Print the number of words that begin with a certain character. Let the user enter that character.
Although, I'm not sure how to do this.
Do I use parsing strings? I tried this because they inspect string data type but I kept getting errors so I took it out and changed it to characters. I want to learn how to do the "total_num" (total number of words that start with the letter the user chooses) and I also need some help with my for loop.
Example of desired output
user types in: a
outputs: "Found 1270 words that begin with a"
user types in: E
outputs: "Found 16 words that begin with E"
user types in: #
outputs: "Found 0 words that begin with #"
(I think I got this part down for non-alphabetical)
The data is from a file called dict.txt, it's a list of many words.
Here's a small sample of what it contains:
D
d
D.A.
dab
dabble
dachshund
dad
daddy
daffodil
dagger
daily
daintily
dainty
dairy
dairy cattle
dairy farm
daisy
dally
Dalmatian
dam
damage
damages
damaging
dame
My program:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
const int NUM_WORD = 21880;//amount of words in file
struct dictionary { string word; };
void load_file(dictionary blank_array[])
{
ifstream data_store;
data_store.open("dict.txt");
if (!data_store)
{
cout << "could not open file" << endl;
exit(0);
}
}
int main()
{
dictionary file_array[NUM_WORD];
char user_input;
int total_num = 0;
load_file(file_array);
cout << "Enter a character" << endl;
cin >> user_input;
if (!isalpha(user_input))
{
cout << "Found 0 that begin with " << user_input << endl;
return 0;
}
for (int counter = 0; counter< NUM_WORD; counter++)
{
if (toupper(user_input) == toupper(file_array[counter].word[0]));
//toupper is used to make a case insensitive search
{
cout << "Found " << total_num << " that begin with " << user_input << endl;
//total_num needs to be the total number of words that start with that letter
}
}
}
There are a few things you can do to make your life simpler e.g. using a vector as the comment suggested.
Let's look at your for loop. There are some obvious syntax problems.
int main()
{
dictionary file_array[NUM_WORD];
char user_input;
int total_num = 0;
load_file(file_array);
cout << "Enter a character" << endl;
cin>>user_input;
if(!isalpha(user_input))
{
cout << "Found 0 that begin with " << user_input << endl;
return 0;
}
for(int counter = 0;counter< NUM_WORD; counter++)
{
if (toupper(user_input) == toupper(file_array[counter].word[0]));
// ^no semi-colon here!
//toupper is used to make a case insensitive search
{
cout<< "Found " << total_num << " that begin with "<<
user_input << endl;
//total_num needs to be the total number of words that start with that letter
}
}//<<< needed to end the for loop
}
Let's get the for loop right. You want to count the matches in a loop and then report when you have finished the loop.
int total_num = 0;
//get character and file
for(int counter = 0;counter< NUM_WORD; counter++)
{
if (toupper(user_input) == toupper(file_array[counter].word[0]))
^^^no semi-colon here!
{
++total_num;
}
}
cout<< "Found " << total_num << " that begin with "<< user_input << endl;

Strings and unordered_map running slow

Here is 2 functions in my code that are running REALLY SLOW.
Basically i read in a document name, open the document, then process it one word at a time. I need to split up the document into sentences, and give each sentence a hash table that represents the number of times the word appears in the sentence. I also need to keep track of all the new words, and a hash table for the total document.
When i run my code now on 10 documents, that have a total of 8000word, and 2100 uniq words it takes about 8000+ seconds to run... almost 1 second per word.
can you tell me how long if(istream.good()) should take?
Or, if you can tell when what is delaying my code. Please let me know if a section is not clear, i will help.
P.S. You can see in the code where i have a start = clock() and end = clock() commented it constantly returns < 1ms. And that is mind-boggleing
void DocProcess::indexString(string sentenceString, hash * sent){
stringstream iss;
string word;
iss.clear();
iss << sentenceString;
while(iss.good())
{
iss >> word;
word = formatWord(word);
std::unordered_map<std::string,int>::const_iterator IsNewWord = words.find(word);
if(IsNewWord == words.end())
{
std::pair<std::string,int> newWordPair (word,0);
std::pair<std::string,int> newWordPairPlusOne (word,1);
words.insert(newWordPair);
sent->insert(newWordPairPlusOne);
}
else
{
std::pair<std::string,int> newWordPairPlusOne (word,1);
sent->insert(newWordPairPlusOne);
}
}
}
void DocProcess::indexFile(string iFileName){
hash newDocHash;
hash newSentHash;
scoreAndInfo sentenceScore;
scoreAndInfo dummy;
fstream iFile;
fstream dFile;
string word;
string newDoc;
string fullDoc;
int minSentenceLength = 5;
int docNumber = 1;
int runningLength = 0;
int ProcessedWords = 0;
stringstream iss;
iFile.open(iFileName.c_str());
if(iFile.is_open())
{
while(iFile.good())
{
iFile >> newDoc;
dFile.open(newDoc.c_str());
DocNames.push_back(newDoc);
if(dFile.is_open())
{
scoreAndInfo documentScore;
//iss << dFile.rdbuf();
while(dFile.good())
{
//start = clock();
dFile >> word;
++ProcessedWords;
std::unordered_map<std::string,int>::const_iterator IsStopWord = stopWords.find(word);
if(runningLength >= minSentenceLength && IsStopWord != stopWords.end() || word[word.length()-1] == '.')
{
/* word is in the stop list, process the string*/
documentScore.second.second.append(" "+word);
sentenceScore.second.second.append(" "+word);
indexString(sentenceScore.second.second, &sentenceScore.second.first);
sentenceScore.first=0.0;
SentList.push_back(sentenceScore);
sentenceScore.second.first.clear(); //Clear hash
sentenceScore.second.second.clear(); // clear string
//sentenceScore = dummy;
runningLength = 0;
}
else
{
++runningLength;
sentenceScore.second.second.append(" "+word);
documentScore.second.second.append(" "+word);
}
//end = clock();
system("cls");
cout << "Processing doc number: " << docNumber << endl
<< "New Word count: " << words.size() << endl
<< "Total words: " << ProcessedWords << endl;
//<< "Last process time****: " << double(diffclock(end,start)) << " ms"<< endl;
}
indexString(documentScore.second.second, &documentScore.second.first);
documentScore.first=0.0;
DocList.push_back(documentScore);
dFile.close();
//iss.clear();
//documentScore = dummy;
++docNumber;
//end = clock();
system("cls");
cout << "Processing doc number: " << docNumber << endl
<< "Word count: " << words.size();
//<< "Last process time: " << double(diffclock(end,start)) << " ms"<< endl;
}
}
iFile.close();
}
else{ cout << "Unable to open index file: "<<endl <<iFileName << endl;}
}
`
Can you try it without
system("cls");
in any of the loops? That surely isn't helping, it's an expensive call.
To clear the screen quickly, instead of system("cls");, try cout << '\f';.