Counting words that start with Capital Letters C++ [Help] - c++

Hey everyone I'm a newbie to C++ and could use some help.
I'm trying to code a program which counts only the words that start with Capital Letters.
int countLegalWords(char str[])
int counter = 0; // counts the legal words
for (int i = 0; i < MAXSIZE; i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
if (str[i + 1] >= 'a' && str[i + 1] <= 'z')
{
counter++;
}
else if (str[i] == ' ')
i++;
}
}
return counter;
Example:
Input:
I liKE Ice Cream H
Output:
4 words with capital letters at the beginning of the word.

There are several problems with your code
In C++, std::string is used for strings. Things like ´char*´ or ´char[]´ are not used in C++ They are used in C. But C and C++ are 2 different languages
You use a C-Style array (char str[]). In C++, C-Style arrays are not used
There is a magic constant MAXSIZE, which has nothing to do with the length of the string. If MAXSIZE is 100 but the your string is smaller, then you compare out of bounds values in the for loop. This is a severe bug.
You need to understand that C-style strings are 0-terminated. The last charcter is a '\0'. You must not operate past the terminating 0.
Your logic in detecting words and word begin is wrong. You check any character for uppercase and then the next for lowercase. But this can happen also within a word. See your sentence with "liKe" in it.
You do not want to switch to C++. You have written in the comment that you want to use strcmp and such, which is a C-function
If you would write comments and use meaningful variable names, then you would find all errors by yourself.
OK, that were the problems. Now a possible solution, using your programming style.
#include <iostream>
int countLegalWords(char myString[]) {
// Here we will store the number of words which start with a capital letter
int countOfLegalWords = 0;
// We will iterate over the complete string and check all characters
unsigned int indexInString = 0;
// Check all characters of the string until we hit the terminating 0
while (myString[indexInString] != '\0') {
// Search for the begin of a word. This is the first non-space character
while (myString[indexInString] == ' ')
++indexInString;
// OK, Now we found the begin of a word. Check, if the first character is upper case
if ((myString[indexInString] >= 'A') and (myString[indexInString] <= 'Z')) {
// Yes, uppercase, count up
++countOfLegalWords;
}
// Now search for the end of the word or for the end of the complete string
while ((myString[indexInString] != '\0') and (myString[indexInString] != ' '))
++indexInString;
}
// And return the count of legal words to ther calling program
return countOfLegalWords;
}
int main() {
char myString[] = "I liKE Ice Cream H";
std::cout << "\nCount of legal words: " << countLegalWords(myString) << '\n';
}
in C++ all this would be done with a one liner:
#include <iostream>
#include <string>
#include <iterator>
#include <regex>
// Regex for a word starting with a capital letter
const std::regex re{ R"(\b[A-Z]\w*)" };
// Main program
int main() {
std::string myString{ "I liKE Ice Cream H" };
std::cout << "\nCount of legal words: " << std::distance(std::sregex_token_iterator(myString.begin(), myString.end(),re), {}) << '\n';
}

Related

How to read spaces, words, and letters line-by-line from a file in a function using Loops (C++)

so I am having a problem with getting my program to increment values properly.
My program needs to take a file in main(), and then pass that to a function-set to print that is called in main.
The key thing is that I need to use loops within the functions to get Letter Count, Space-Count, and Word Count.
I have the output configured right
cout << line_number << ": " << line << " [" << letter_count << " letters, " << space_count << " spaces, " << word_count << " words]" << endl;
Which results for example
0: Words go here. [# letters, # spaces, # words.]
But with my current functions for Letters and spaces, it doesn't work.
My non-space function for example
int count_non_space(string line) {
int non_space = 0;
for (int i = 0; i < line.length(); i++) {
if (line.c_str() != " ") {
non_space++;
}
}
return non_space;
It counts all of the characters in the line instead and the counterpart (space_count) counts nothing.
And that's not to mention that I don't know how to count the words in the line.
Any advice as to what is going on? as I am certain that count_space and count_non_space should be inverses of each other (count_space being the same function but with == instead of !=)
EDIT: Got the Letter and Space count correct.
Now, how would I get the word count from that sort of method?
EDIT 2: Okay so letter count is off.
It is counting puncutation-characters (commas, periods, dashes, hiphons.etc) as leters.
I have managed to redact periods, dashes.etc from the code manually with a reduction if statement in the count_non_characters function.
But I can't add ' to it as it already uses '' to catch the char comparison
Is there catch-all term for punctuation characters in C++ that I can use for
if (line[i] == "Puncutation") {
non_space--;
}
?
As UnholySheep said, when you compare a c string (char *) you can't use standard logical operators. You will need to use strcmp(). However, if you use a c++ std::string then you can use compare() or logical operators.
As for finding words in a string. Here are a few resources.
c++ counting how many words in line
C++ function to count all the words in a string
C++ Program to find number of Digits and White Spaces in a String
Count words in a given string
For further help. Google: "Get word count per line c++"
Reminder, these two are different data types and have different library support:
std::string myStr
myStr.c_str()
If the goal is to count characters in a string that are not spaces, then there is a way to do this using the STL and lambdas that is much cleaner than writing a bunch of loops and worrying about updating variables.
int count_non_space(std::string line) {
return std::count_if(line.begin(), line.end(),
[](auto ch) {
return ch != ' ';
});
}
This also makes is very straightforward to accommodate for things like spaces and tabs.
int count_non_space(std::string line) {
return std::count_if(line.begin(), line.end(),
[](auto ch) {
return ch != ' ' && ch != '\t';
});
}
To count the opposite (just the spaces) we simply need to change the condition in the lambda.
int space_count(std::string line) {
return std::count_if(line.begin(), line.end(),
[](auto ch) {
return ch == ' ' || ch == '\t';
});
}
As Remy Lebeau helpfully points out, we don't even have to write the lambda. We can simply use the std::isspace function directly instead of the lambda.
int space_count(std::string line) {
return std::count_if(line.begin(), line.end(), std::isspace);
}
Documentation on std::count_if.
Here's how I would revise the function you gave:
int count_non_space(string line) {
int non_space = 0;
for (int i = 0; i < line.length(); i++) {
if (line[i] != ' ') {
non_space++;
}
}
return non_space;
}
Notes:
I changed line.c_str() to line[i] in order to access the ith character of line
I changed " " to ' ' so that it's comparing against the space char, not a string which only contains the space. The comparison would fail if we were comparing the ith char to a string
As for this:
And that's not to mention that I don't know how to count the words in the line.
I don't know how your requirements define a word, but if we assume a word is any contiguous clump of non-space characters, you could use this logic:
initialize bool in_word to false
initialize int word_count to 0
for each char in the string:
if in_word is false and the current char is not a space, then set in_word to be true and increase word_count by 1
if in_word is true and the current char is a space, then set in_word to be false
return word_count

Using find_first_of with a string instead of a set of predefined characters in c++

I want to take in a code, for example ABC and check whether the characters in the code appear in that exact order in a string, for example with the code ABC, and the string HAPPYBIRTHDAYCACEY, which meets the criteria. The string TRAGICBIRTHDAYCACEY with the code ABC however does not pass, because there's a "c" before the "b" after the "a". I want to use the find_first_of function to search through my string, but i want to check for any of the characters in "code", without knowing what characters are in "code" beforehand. Here is my program so far:
#include <iostream>
#include <string>
using namespace std;
int main() {
string code, str, temp;
int k = 0;
int pos = 0;
cin >> code >> str;
while (k < code.size()) {
pos = str.find_first_of(code,pos);
temp[k] = str[pos];
++k;
++pos;
}
cout << temp << endl; // debug. This is just outputs a newline when i
//run the program
if (temp == code) {
cout << "PASS" << endl;
}
else {
cout << "FAIL" << endl;
}
return 0;
}
I think your best bet is to find just the first character, once found, find the next in the remainder of the string, repeat until end of string or all characters found (and return false or true, respectively).
I don't think there's anything builtin for this. If the characters would need to appear directly after each other, you could use std::string::find() which searches for a substring, but that is not what you want.

I am writing a code to convert lowercase letters to uppercase letters using arrays

I have the code but it prints the letters in uppercase but also prints some weird characters afterwards. I just wanted to know how to just get the letters.
the program executing picture.
using namespace std;
int main()
{
const int SIZE = 81; // Constant for size of an array
const int MIN_LOWERCASE = 97; // Start of lowercase letters in ASCII
const int MAX_LOWERCASE = 122; // End of lowercase letters in ASCII
char line[SIZE]; // Initializing character line for input
cout << "Enter a string of 80 or fewer characters:\n";
cin.getline(line,SIZE); // Getting input from the user.
for (int count = 0; count < SIZE; count++)
{
if (line[count] >= MIN_LOWERCASE && line[count] <= MAX_LOWERCASE) // Checking whether the selected letter is in the reange of lowercase letters.
{
line[count] - 32;
cout << static_cast<char>(line[count] - 32); // converting and displaying lowercase letters to uppercase letters.
}
else
{
cout << static_cast<char>(line[count]);//Displaying the same character if it is in uppercase.
}
}
cout << endl;
system("pause");
return 0;
}
You need to use the actual size of the text that you read. Else you will print extra characters.
for (int count = 0; count < strlen(line); count++)
You might need #include <cstring> to use strlen().
cout << "Enter a string of 80 or fewer characters:\n";
cin.getline(line,SIZE); // Getting input from the user.
int strLen=strlen(line)
for (int count = 0; count < strLen; count++)
{
if (line[count] >= MIN_LOWERCASE && line[count] <= MAX_LOWERCASE) // Checking whether the selected letter is in the reange of lowercase letters.
{
line[count] - 32;
cout << static_cast<char>(line[count] - 32); // converting and displaying lowercase letters to uppercase letters.
}
else
{
cout << static_cast<char>(line[count]);//Displaying the same character if it is in uppercase.
}
}
Ypur loop is running 80 times no matter what is the size of string.
Actually, getline / cin / scanf etc. functions for char[] is explained following example:
The string is initialized for char c[10];. The input is "abcd".
First, c[i] is initialized unknown value, because it is local variable (If it is a global variable, you can assume that c[i] = 0)
Second, If you input, the value of c[i] only changed where 0<=i<=4 because the length of input is 4.
In this case, currently c = { 'a', 'b', 'c', 'd', '\0', ?, ?, ?, ?, ?}. (? denotes unknown value)
Third, you are looping i for 0 to size_of_array_c, so your output will be "abcd?????" (I don't know the value of ?).
So, you can fix the bug if you only loop while c[i] != '\0'.
The idiomatic way of doing this in C++ is
#include <string>
#include <locale>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
std::locale loc(""); //< the current system locale
std::string line; //< will contain the input line
std::cout << "Enter a string of 80 or fewer characters:\n";
std::getline(std::cin,line);
std::string lower; //< will contain the output
// This is the "key" of everything
std::transform(line.begin(),line.end(), // transform the entire input...
std::back_inserter(lower), // by writing into the back of the output string ...
[&loc](auto c){ return std::tolower(c,loc); }); // the result of std::tolower applied to all character, using the system locale
std::cout << "The transformed string is:\n" << lower << std::endl;
return 0;
}
// look ma! No pointers, array sizes, overflows and explicit memory management.
// And works consistently with the language your computer is set up.

While loop not seeing or finding terminating null character

I am trying to iterate through a char array using a while loop using '\0' as the terminating condition, but my problem is that its not finding the '\0' until index position 481, the array is declared as 200 long and I cant see what I am doing wrong!! I cannot use strings or any form of string functions for this before anyone asks. Can anyone help??
#include <iostream>
using namespace std;
int main()
{
char fullString[200]={'\0'}; // Declare char string of 200, containing null characters
int alphaCount = 0;
int charCount = 0;
int wordCount = 0;
cin.getline(fullString,200); //
cout << "\n\n" << fullString;
cout << "\n\n\n";
int i=0;
int i2 = 0;
while(fullString[i]!='\0'){ //iterate through array until NULL character is found
cout << "\n\nIndex pos : " << fullString[i]; //Output char at 'i' position
while(fullString[i2]!= ' '){ //while 'i' is not equal to SPACE, iterate4 through array
if(isalpha(fullString[i2])){
alphaCount++; // count if alpha character at 'i'
}
charCount++; // count all chars at 'i'
i2++;
}
if(charCount == alphaCount){ // if charCount and alphaCount are equal, word is valid
wordCount++;
}
charCount = 0; // zero charCount and alphaCount
alphaCount = 0;
i=i2;// Assign the position of 'i2' to 'i'
while(fullString[i] == 32){ //if spaces are present, iterate past them
i++;
cout << "\n\ntest1";
}
i2 = i; // assign value of 'i' to 'i2' which is the next position of a character in the array
if(fullString[i] == '\0')
{
cout << "\n\nNull Character " << endl;
cout << "found at pos: " << i << endl;
}
}
cout << "\n\ni" << i;
cout << "\n\nWord" << wordCount;
return 0;
}
As others have pointed out, your problem is with the inner loop. You test for a space character but not for NULL, so it's iterating past the end of the last word because there is no space character after the last word.
This is easily fixed by changing your while condition from this:
while(fullString[i2]!= ' ')
... to this:
while(fullString[i2] && fullString[i2]!= ' ')
This will change your inner while loop to first test for non-NULL, and then test for non-space.
I'm not correcting the rest of your code because I presume this is a class project (it looks like one) so I'm limiting my answer to the scope of your question.
You do not check in the inner loop
while(fullString[i2]!= ' '){ //while 'i' is not equal to SPACE, iterate4 through array
if(isalpha(fullString[i2])){
alphaCount++; // count if alpha character at 'i'
}
charCount++; // count all chars at 'i'
i2++;
}
...
i=i2;// Assign the position of 'i2' to 'i'
whether the next character is equal to '\0'
It's because the inner loops don't check for the termination, they just continue looping even past the end of the string.
By the way, if you want to count the number of words, spaces and non-space characters, there are easier ways in C++. See e.g. std::count and std::count_if for the spaces and characters. For example:
std::string input = "Some string\twith multiple\nspaces in it.";
int num_spaces = std::count_if(std::begin(input), std::end(input),
[](const char& ch){ return std::isspace(ch); });
For counting words, you can use std::istringstream, std::vector, std::copy, std::istream_iterator and std::back_inserter:
std::istringstream iss(input);
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(words));
After the code above, the size of the words vector is the number of words.
If you use e.g. std::copy_if then you can use the above code for the other cases as well (but std::count_if is better for single character classes).

Counting the Number of Palindromes in a Sentence

Good day, everyone! Below is a program which asks a user for a sentence and outputs the number of palindromes in it.
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
bool isPalindrome (const std::string& s) {
for (int i = 0; i < (s.length())/2; ++i) {
if (s[i] != s[s.length()-1 - i])
return false;
else
return true;
}
}
int main() {
string sentence;
int counter=0;
cout << "Please input a sentence." << endl;
getline(cin, sentence);
stringstream processtokens(sentence);
for(string word; processtokens >> word;)
if(isPalindrome(word))
++counter;
cout << "Number of Palindromes are : " << counter << endl;
}
It works just fine. But for example, when I input "The quick brown gag has a blue eye.", the number of palindromes the program displays is just 1 but in reality, the sentence has 2 palindromes: gag and eye. The problem is that the word "eye" has a period. So how can the program ignore the period and other punctuation marks like comma when, for instance, the user entered "I love noon, evening, and midnight". Noon is a palindrome but the program doesn't recognize it because of the comma.
Another problem is the capitalization. I want this program to work (and ignore ASCII equivalents) when the user entered "Madam, my work is done." I know it has something to do with tolower.
To summarize, I want this program to have a function which a) ignores punctuations marks and b) capitalization.
And oh, what is the alternative for " stringstream processtokens(sentence);... "? Rather that, I need this program to use substring (substr) and find.
Please guide me, guys! Thank you and any kind of help is very appreciated. Thanks again and have a nice day!
You can use ispunct and ignore any characters where ispunct returns true. You should also wrap your character comparisons in calls tolower()
Maybe this little exercise can be used to introduce some nice C++ features such as iterators:
inline bool is_letter(char c)
{ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); }
bool is_palindrome(const std::string & s)
{
std::string::const_iterator it = s.begin();
std::string::const_reverse_iterator rt = s.rbegin();
while (it != s.end() && rt != s.rend() && std::distance(it, rt.base()) > 0)
{
// Skip non-letters
while (it != s.end() && !is_letter(*it)) { ++it; }
while (rt != s.rend() && !is_letter(*rt)) { ++rt; }
if (it == s.end() || rt == s.rend()) { break; }
// Check palindromy
if (std::tolower(*it) != std::tolower(*rt)) { return false; }
// Move on
++it;
++rt;
}
return true;
}
The trick is to attack the string from both ends. For this, we have an ordinary iterator, it, coming from the beginning of the string, and a reverse iterator, rt, coming from the end of the string.
The heart of the code is the check for palindromy (case insensitively, by comparing downcased characters), and immediate return false in the even of failure; otherwise the two iterators are advanced by one.
Finally, the beginning of the loop gobbles up non-letter characters from the string, so those are flat-out ignored. We check again whether we reached the end of the string after gobbling; you must make sure that you only dereference an iterator to a valid element!
The loop stops when the forward-moving iterator has gone past the backward-moving one. This is the content of the condition distance(it, rt.base()) > 0: the "base" of the reverse iterator is actually an ordinary iterator to the element after the reverse-iterator's element. So it hasn't crossed over rt as long as the distance from it to the base of rt is strictly greater than zero. (The distance is precisely 1 when it and rt refer to the same element.)
I think there is a function to check for punctuation. You might want to try ispunct