Counting # of words in a line [duplicate] - c++

This question already has answers here:
C++ function to count all the words in a string
(10 answers)
Closed 9 years ago.
This is what I am trying to do, this is not nearly the entire program I am making just a small portion. This part is counting the # of words of what I enter.
string s;
getline(cin, s);
for (unsigned int i = 0; i < s.length(); i++)
{
if (s[i] == ' ' || s[i] == '.')
{
numWords++;
}
}
This obviously works if someone enters a correct line with a period at the end. I can't think of how to get it to recognize the end of line character though, incase they don't put a period.

Why not just start the numWords counter on 1 and only count the spaces?

You can simply count the number of " " in your line and add that to 1. That's all.

bool previousSpace = false;
for (unsigned int i = 0; i < s.length(); i++)
{
if (isspace(s[i]) || s[i] == '.')
{
if (previousSpace == false)
{
numWords++;
previousSpace = true;
}
}
else
{
previousSpace = false;
}
}
cout << numWords + (previousSpace ? 0 : 1) << endl;
This considers more than one consecutive spaces. The key here is to use isspace function.

Could this be the same that you are after? Count the number of times each word occurs in a file or this already duplicate one Word count program in C++ duplicate?

Related

What is wrong with my program to find the longest word in a sentence?

#include <iostream>
using namespace std;
int main() {
char a[101]{0};
cin>>a;
cin.getline(a,101);
cin.ignore();
int currLen{0};
int maxLen{0};
int startInd{-1};
int endInd{-1};
for(int i=0; i<101; i++) {
if(a[i]!=' ' ) {
++currLen;
} else if(a[i]==' '||a[i]=='\0') {
if(currLen>maxLen) {
maxLen=currLen;
startInd=i-currLen;
endInd=i-1;
}
if(a[i]=='\0')
break;
currLen=0;
}
}
cout<<maxLen<<endl;
if(startInd==-1)
cout<<-1;
else
for(int i=startInd; i<=endInd; i++)
cout<<a[i];
return 0;
}
If I take an input here, for example, "My name is Manav Kampani"
It will output 5
Manav instead of 7
Kampani
But if I write "My name is Manav Kampani ", with space after the last word
than it is considering Kampani too printing Kampani.
Also when I input "Kampani Manav is my name" then too it's displaying the wrong output. That means it is not considering the first word of the sentence.
if(a[i]!=' ' )
{
++currLen;
}
else if(a[i]==' '||a[i]=='\0')
{
....
}
Consider the case of a[i] == 0. Which of these if-statements will apply.
Answer: the first one. Which means you'll never look at the final word in the string. You also don't exit at the end of the string, but instead loop through whatever is in your string all the way out to character 101.
As a general structure, be very, very careful with this:
if (condition)
else if (condition)
// without a final else section
If you do that, you need to think about what you're doing. In this particular case, you can have:
if (a[i] != 0 && a[i] != ' ')
else
It may not solve all your issues, but it should solve some.
A nice sliding window pattern implementation.
You have 3 problems in your code
You must not write cin >> a;
You must not write cin.ignore();
You need to modify your if statement like so: if (a[i] != ' ' && a[i] != '\0') Otherwise you will not detect the last word.
Your complete working code with that minor fixes will lokk like that.
int main()
{
char a[101]{ 0 };
//cin >> a;
cin.getline(a, 101);
//cin.ignore();
int currLen{ 0 };
int maxLen{ 0 };
int startInd{ -1 };
int endInd{ -1 };
for (int i = 0; i < 101; i++)
{
if (a[i] != ' ' && a[i] != '\0')// Add comparison
{
++currLen;
}
else if (a[i] == ' ' || a[i] == '\0')
{
if (currLen > maxLen)
{
maxLen = currLen;
startInd = i - currLen;
endInd = i - 1;
}
if (a[i] == '\0')
break;
currLen = 0;
}
}
cout << maxLen << endl;
if (startInd == -1)
cout << -1;
else
for (int i = startInd; i <= endInd; i++)
cout << a[i];
return 0;
}
Additionally. You should not use C-Style arrays in C++. And please use std::string
There is a couple of things here:
1- You don't need to do a cin>>a this is actually consuming the first word, and afterwards the content is overrided by cin.getline(). So removing the firsst cin>>ayou'll be fine.
2- The last word is not read because there isn't any if condition that matches the condition aka.
if(a[i]!=' ' ) case of not a space
//not end of word
else if(a[i]==' '||a[i]=='\0') case of space or null
//end of word
So your last character is not a space nor null, that means you don't detect the last word.

Problem with boolean variable in email validation program [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 3 years ago.
I am trying to create an email validation program without using the regex library. In one of my functions, I want to return a Boolean to check if there is an # sign in the email address and also if it is in a valid position (the # sign cannot be one of the first three characters of the string). However I am having problems with it because every time I run the program by entering in an email address with the # sign in an invalid position, it keeps telling me that the email is valid. Please help!
valid = checkEmail(email); //function call
if(valid == true)
cout << "Your email is valid!" << endl;
else
cout << "Your email is invalid!" << endl;
bool checkEmail(string email)
{
int counter;
int length;
bool firstThree; //checks to make sure # is not in the first three chars
counter = 0;
length = email.length();
firstThree = false;
for(int i = 0; i < length; i++)
{
if(email[i] == '#')
counter++;
}
for(int y = 0; y < length; y++)
{
if(email[0] == '#' || email[1] == '#' || email[2] == '#')
firstThree = true;
else
firstThree = false;
}
cout << "\n" << counter << endl; //check to see if counter works
if(counter != 1 && firstThree == true)
return false;
else
return true;
}
I guess you need to define the function bool checkEmail(string email) at the begining of the program. Basically flip if else and the function definition.
bool checkEmail(string email)
{
int counter;
int length;
bool firstThree; //checks to make sure # is not in the first three chars
counter = 0;
length = email.length();
firstThree = false;
for(int i = 0; i < length; i++)
{
if(email[i] == '#')
counter++;
}
for(int y = 0; y < length; y++)
{
if(email[0] == '#' || email[1] == '#' || email[2] == '#')
firstThree = true;
else
firstThree = false;
}
valid = checkEmail(email); //function call
if(valid == true)
cout << "Your email is valid!" << endl;
else
cout << "Your email is invalid!" << endl;
There seem to be a lot of beginner mistakes here, so I suggest learning the basics of programming and c++ first and like others suggested, use a debugger. Here are some of the mistakes:
Function definition
c++ is not like other common languages in the sense that functions need to be defined before they can be used. This means that you either need to move your checkEmail function above the function call, or create a separate definition above the function call like:
bool checkemail(string email);
as an exmaple.
Incorrect if-statement logic; Unnecessary for loop:
I'm assuming that based on how emails are formatted, you want the checkEmail function to return false if it doesn't match the correct formatting, and based on what your function currently does, that means that it will return false if the first three characters are # or if there isn't exactly one # symbol in the email. However, you used a && operator, which signifies and, meaning it will return true even when you don't want it to (much like how #Yastanub stated in his first comment). Better yet, that entire logic and if statement can be simplified greatly using std::string::find with a while loop and a vector (similar to this method):
vector<size_t> posVec;
size_t pos = email.find('#', 0); //note that this can be an int instead of size_t, but it can cause stack overflow with bigger numbers
while(pos != string::npos){
posVec.push_back(pos);
pos = email.find('#', pos+1);
}
switch(posVec.size()){
//if there is only one # symbol found
case 1:
bool firstThree = false;
for(int i = 0; i <= 2; i++)
//if there is only one # but it's in the first 3 positions, the email isn't valid
if(posVec[0] == i)
firstThree = true;
return !firstThree;
//otherwise the email doesn't work
default:
return false;
}
Remember to include the required libraries in order for this part to work:
#include <string>
#include <vector>
This also eliminates the second for loop in your function that is useless because the variable y is not being used, and the counter that was being used for testing
Another note
Using if (valid == true) is unnecessary as well. You can just use if (valid) because of how booleans work with if-statements.

C++ find words ending with "ing" and are less than or equal to 10 characters

As the title suggests I want to find all the words in my vector that meet this rule.
My current code is:
void Dictionary::endingIng() {
string findIng;
string foundIng;
int sevenLetters = 7;
for (Word findIng : deffinitions)
if (findIng.getWord().find("ing") <= sevenLetters) {
foundIng = findIng.getWord();
cout << foundIng << endl;
}
However, it also returns words that either contain "ing" somewhere in the middle and words longer then 10 characters, some examples being:
accordingly
barringout
bingo
commandingly
Thanks for the help.
Perhaps this can help.
Adding a case to skip words more than 10 letters.
Also checking the position of "ing" for words <= 10 letters.
Uses rfind for edge case like "inginging"
for (Word findIng : deffinitions) {
std::string word = findIng.getWord();
if (word.length() > 10) {
// skip this - word is more than 10 letters including "ing"
continue;
}
size_t pos = word.rfind("ing");
if (pos == word.length() - 3) {
// we got a match "ing" as suffix of this word
// do something with `word`
}
}
Why don't you (using your current solution) check the length, then get the last 3 values and check if they match.
Or you can go
CString findString = "ing";
int maxLetters = findString.GetLength() + 7; //magic number
foreach(CString s in dictionary)
{
bool b_SmallEnough = (s.Find(findString) <= maxLetters );
bool b_EndsIn = (s.ReverseFind(findString) == (s.GetLength() - findString.GetLength()); //reverse find so it doesn't get the first "ing in bringing and return false because 2 != 5
if(b_SmallEnough && b_EndsIn)
{
std::wcout << s << std::endl;
}
}
Alternatively, bool b_EndsIn could be:
bool b_EndsIn = (s.MakeReverse.Find(findString.MakeReverse()) == 0);
This will mean that your're checking the end first, and always getting the last match

c++ getting weird crashes in my program [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
#include <iostream>
using namespace std;
int main()
{
int a = 0, skrb = 0, j = 0;
char b, simboliai[2000];
char zodis[50][20];
char check[1][20] = {'f'};
cout << "Prasome irasykite sakini: ";
cin.getline(simboliai,sizeof(simboliai));
//----------------- Zodziu skaidymas ----------------------------------------------------------------------------------------------------------
a = 0;
for (int i = 0; i > -1; i++)
{
if ((simboliai[i] == 's' && simboliai[i++] == ' ') || (simboliai[i] == 's' && simboliai[i++] == '\n'))
{
check[0][a] = 't';
}
if (simboliai[i] == ' ')
{
a++;
}
else
{
zodis[i][a] = simboliai[i];
}
if (simboliai[i] == '\n')
{
break;
}
}
a = 0;
while (1)
{
if (simboliai[a] == '.' || simboliai[a] == ',' || simboliai[a] == '!' || simboliai[a] == '?')
{
skrb++;
}
a++;
if (simboliai[a] == '\n')
{
break;
}
}
a = 0;
cout << "Jus ivedete tokius zodius kurie baigiasi raide 's'" << endl;
while(1)
{
if (zodis[j][a] == 'Ì')
{
cout << '\n';
a++;
}
if (check[0][a] == 't')
{
cout << zodis[j][a];
}
if (zodis[0][a] == 'Ì')
{
break;
}
}
cout << "Pas jus yra (.','!'?) simboliu: " << skrb << endl;
cin.ignore();
cin.get();
}
Basically this program would work but that for part just ruins everything. It doesn't put characters one by one. And when I debug it shows that program have put symbol in its place but then there is Ì.
So it looks just like so
input: word word
zodis[0][0] goes like wÌÌÌÌÌÌÌÌÌÌ zodis [1][0] goes oÌÌÌÌÌÌÌÌÌÌ and so on and it breaks. Thank you in advance.
If you are saying the for loop wouldn't put characters 1 by 1, it was in your "simboliai[i++] == ' '" logic. integer 'i' been incremented twice each loop when current character is 's' which mean it will be incremented from i=2 to i=4 if simboliai[i] = 's'. Use i+1 instead for your checking.
for (int i = 0; i > -1; i++)
{
...
}
is the main problem. There might be others but I don't look too closely for them.
The values of i will be 0, 1, 2. etc.
All of them are greater than -1.
The loop will go on until the value i reaches INT_MAX. (Not sure what happens when i is incremented at that time).
That is way larger than the size of the array simboliai anyway. Your program will access the array simboliai beyond valid limits and cause undefined behavior.
I think what you need is:
size_t len = strlen(simboliai);
for (size_t i = 0; i < len; i++)
{
...
}
Other Problems
Some of the errors result from the assumption that there is a newline character in simboliai. That assumption is not correct. std::istream::getline reads and discards the newline character.
If Google Translate is correct, zodis is supposed to contain a list of words. When you are iterating over the characters of simboliai, you need three counters.
One to iterate over the characters of simboliai.
One to keep track of the number words.
One to keep track of the number of characters in the current word.
Your for loop is not doing that.
When you are trying to access the contents of an array, you need to always write defensive code and make sure that you never access the array using out of bounds indices. In the last while loop, you are not doing that.
In the last while loop, you are incrementing a only in the first if block. If the conditional of that if statement evaluates to false, a never gets incremented and you get stuck in an infinite loop.
In the last loop you use j as an index but its value is initialized to 0 at the start of the function and never gets updated. It's not clear what the intent of the last while loop is. Hence, I can't say whether it's a bug but it sounds like it could be.
Here's a cleaned up version of your posted code with still a few unknowns.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int a = 0, skrb = 0, j = 0;
char b, simboliai[2000];
char zodis[50][20];
char check[1][20] = {'f'};
cout << "Prasome irasykite sakini: ";
cin.getline(simboliai,sizeof(simboliai));
//----------------- Zodziu skaidymas ----------------------------------------------------------------------------------------------------------
int word_counter = 0;
a = 0;
size_t len = std::strlen(simboliai);
for (size_t i = 0; i < len; i++)
{
if ((simboliai[i] == 's' && simboliai[i+1] == ' ') || (simboliai[i] == 's' && simboliai[i+1] == '\0'))
{
check[0][a] = 't';
}
if (simboliai[i] == ' ')
{
zodis[word_counter][a] = '\0';
a = 0;
++word_counter;
}
else
{
zodis[word_counter][a] = simboliai[i];
++a;
}
}
a = 0;
while ( simboliai[a] != '\0' )
{
if (simboliai[a] == '.' || simboliai[a] == ',' || simboliai[a] == '!' || simboliai[a] == '?')
{
skrb++;
}
a++;
}
a = 0;
cout << "Jus ivedete tokius zodius kurie baigiasi raide 's'" << endl;
while( j < 50 && a < 20 )
{
if (zodis[j][a] == 'Ì')
{
cout << '\n';
}
if (check[0][a] == 't')
{
cout << zodis[j][a];
}
if (zodis[0][a] == 'Ì')
{
break;
}
a++;
}
cout << "Pas jus yra (.','!'?) simboliu: " << skrb << endl;
cin.ignore();
cin.get();
}

I'm having trouble with finding unique words, how to improve code? [duplicate]

This question already has an answer here:
How to improve my code to correctly count unique lines?
(1 answer)
Closed 9 years ago.
I need to count the number of unique words and with my code below, it doesn't seem to be counting correctly. I am not sure what else I can do to make it work and would really appreciate any suggestions.
#include <iostream>
#include <string>
#include <set>
using std::string;
using std::set;
unsigned long countUWords(const string& s)
{
set<string> uw;
string word = "";
for(size_t i = 0; i < s.size(); i++){
bool words = (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z');
if(words){
word += s[i];
}
else if(!words && word != ""){
uw.insert(word);
word = "";
}
}
if (word != "")
uw.insert(word);
return uw.size();
}
int main ()
{
string s;
unsigned long UWords = 0;
while(getline(cin, s)){
UWords += countUWords(s);
}
cout << UWords << endl;
return 0;
}
At the end of the for loop you need to check if word is empty. If not you need to push the content of word inside the set.
After the end bracket of the for loop, add:
if (word != "")
uw.insert(word);
As you can see it works just fine after that edit.