Counting the number of letters/digits - c++

My goal is to write a C++ program that can read a text file and:
Count the average number of letters/sentence.
Count the total amount of digits.
The text file would be read with command "./a.out < textfile"
What I've tried so far is to have the program check each character at a time with "cin >> current". I have a while loop. If current hits a punctuation mark, it should increase linecount by 1. It should also be reading for alpha characters, but I'm not sure how to make it count those.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cctype>
using namespace std;
int main()
{
int letters; //Total number of letters per sentence
int digits; //Total number of digits
int sentencecount; //Number of sentences
float averageletters; //Average number of letters per sentence
int linecount ; //Count of lines
char current; //Current character
cin >> current;
digits = 0;
letters = 0;
while (cin)
{
if (current == '.' == '!' == '?')
linecount++;
//calcuate averages and other sentence data
//reset sentence data
if (isalpha(current))//repeat for digits
letters++;
cout << "line #" << letters << endl;
cin >> current;
}
return 0;
}

if (current == '.' == '!' == '?')
The line above doesn't do what it think you does. Suppose current is a exclamation point. Then this evaluates to:
if (false == '!' == '?') // The character is NOT a '.'
Then:
if (false == '?') // '!''s value is > 0, so the condition checks if true == false
And finally:
if (false) // For the same reasons as above
To fix your condition, use:
if (current == '.' || current == '!' || current == '?')
This uses the boolean OR operator to check if any of the conditions inside the statement are true, under which case to go inside the if statement. You can also add parentheses to the condition to increase readability.

if (current == '.' == '!' == '?')
probably won't evaluate they way you intend. You might want to read up on c++ operator precendence.
You could try-
if ((current == '.') || (current == '!') || (current == '?'))

Related

Counting syllables in a word C++

I have created a program to count the syllables in a word inputted by the user. The user is to enter any amount of words followed by the enter key until the (#) key is entered, then the program is to display the words in a table followed by the syllable count for each word.
I am having issues with the "silent e" portion of my program.
if (word_length - 1 == 'e')
{
vowels = vowels - 1;
It seems as though it is not able to pick up the last letter in the string of words. I have tried to move some of the if statements around to see if that helps and to better identify where the problem lies, and from what I have noticed, as stated earlier i believe it to be with the silent e portion of the code.
It is difficult to find even the smallest errors in my code, so I am asking for another set of eyes to gaze over my code.
Any help will be greatly appreciated.
Also, I have yet to complete the formatting of my results table, so please over look that.
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
string word_1 = "create list";
int vowels = 0;
int word_length; // better to set .length() into variable to eliminate warnings
int words_to_print = 0; // this will count how many words to print to use in for loop later
/*
vector <variable type> name_of_vector[size of vector];
creating vectors
leaving them empty for now
*/
vector <string> words_saved;
vector <int> number_of_syllables_saved;
cout << "Enter 4 words from the English dictionary, to determine the amount of syllables each word has." << endl;
cout << "Please enter [#] when finished, to create a list." << endl;
cin >> word_1;
while (word_1 != "#") // as long as user doesnt enter # you can enter a word and
{ // have it run thru the syllable logic
word_length = word_1.length();
words_to_print++;
words_saved.push_back(word_1);
// ^ this saves the word into the next availabe index of vector for strings.
for (int i = 0; i < word_length ; i++) // length is a variable now instead of function syntax this
{ // eliminates the <: signed/usnsigned mismatch warning below
if ((word_1[i] == 'a') || (word_1[i] == 'e') || (word_1[i] == 'i') || (word_1[i] == 'o') || (word_1[i] == 'u') || (word_1[i] == 'y'))
{
vowels = vowels + 1;
if ((word_1[i + 1] == 'a') || (word_1[i + 1] == 'e') || (word_1[i + 1] == 'i') || (word_1[i + 1] == 'o') || (word_1[i + 1] == 'u') || (word_1[i + 1] == 'y'))
{
vowels = vowels - 1;
if (word_length - 1 == 'e')
{
vowels = vowels - 1;
if (vowels == 0)
{
vowels = vowels + 1;
}
}
}
}
}
number_of_syllables_saved.push_back(vowels);
//^ this puts number of syllables into vector of ints
vowels = 0; // this resets the amounts so it can count vowels of next word and not stack from previous word
cin >> word_1; // this will reset the word and controls loop to print out chart if # is entered
}
// use a for loop to print out all the words
cout << endl << endl << endl;
cout << "Word: " << setw(30) << "Syllables: " << endl;
for (int x = 0; x < words_to_print; x++)
{
cout << words_saved[x] << setw(20) << number_of_syllables_saved[x] << endl;
}
//system("pause");
return 0;
}
You are comparing the character 'e' to the integer word_length - 1 instead of comparing it to the last character of your string as you intended.
You should replace if (word_length - 1 == 'e') with if (word_1[word_length - 1] == 'e').
Your nested if-statements don't get evaluated at the anticipated index.
Say the input is "state".
At i = 0, word_1[i] = 's', doesn't pass the first if statement.
At i = 1, word_1[i] = 't', doesn't pass the first if statement.
At i = 2, word_1[i] = 'a', vowels becomes 1. The program does not proceed further down the nested if statements since word_1[i+1] is 't'.
At i = 3, word_1[i] = 't', doesn't pass the first if statement.
At i = 4, word_1[i] = 'e', vowels becomes 2. The program does not proceed further down the nested if statements since word_1[i+1] is garbage value.
As you can see, it never reaches the nested if-statements as you intended

Input validation using character array in C++

I am creating a C++ program to validate book name using a function in c++. The function must return 1 if the input is valid and 0 if the input is invalid. Book name can only contain upper case, lower case characters, color(:), comma(,) and space (there should be no consecutive spaces, commas, and colons). And the maximum characters in a character array is 60.
I tried the following way but I am not getting the desired answer.
const int MAX_BOOK_NAME = 60;
bool isValidBookName(char bookName[MAX_BOOK_NAME])
{
int length = strlen(bookName);
if (length > 59)
{
return false;
}
for (int i = 0; i < 59; i++)
{
if (bookName[i] < 'A' || bookName[i] > 'Z' || bookName[i] < 'a' || bookName[i] > 'z' || bookName[i] != ' ' || bookName[i] != ':' || bookName[i] != ',')
{
return false;
}
}
return true;
}
int main()
{
char arr[60];
cout << "Please Enter Your Book Id : ";
cin.getline(arr, 60);
cout << "Your Entered Name is " << isValidBookName(arr) << endl;
}
bookName[i] < 'A' || bookName[i] > 'Z' || bookName[i] < 'a' || bookName[i] > 'z'
These checks match every character because for example (assuming ASCII or compatible encoding) all capital letters match the condition bookName[i] < 'a' and all smaller case letters match bookName[i] > 'Z'. Since these checks are used to match an invalid character, the check is wrong.
std::isalpha can simplify your program greatly, as pointed out in comments.
The logic of your character check is flawed.
The requirement in your question is that each character must be a letter, or a comma, or a colon, or ... etc. The reverse of that is not "not a letter or not a comma or not a colon or ... etc." The reverse is "not a letter and not a comma and not a colon and ... etc."

Program for getting amount of words that start with Vowels and Consenants is returning wrong answers

Im writing a program for class and so far i have the word counter working fine and the vowel part working fine but Consonants and non alpha digits return wrong answers by 1(in certain cases). i think the problem lies in the testing of the characters them selves but i cant seem to find a way around it.
using namespace std;
int main()
{
char ch;
int count = 0;
int vowel = 0;
int cons = 0;
int noalph = 0;
bool inword = 1;
bool space = 0;
while (cin.get(ch)) {
if (ch != ' ') {
inword = 1;
}
if (isspace(ch)) {
space = 1;
}
else if (space && inword) {
count++;
space = 0;
inword = 0;
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||
ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' ||
ch == 'y' || ch == 'Y') {
vowel++;
}
if (ch != 'a' && ch != 'e' && ch != 'i' && ch != 'o' && ch != 'u' &&
ch != 'A' && ch != 'E' && ch != 'I' && ch != 'O' && ch != 'U' &&
ch != 'y' && ch != 'Y'
&& isalpha(ch)) {
cons++;
}
if (ispunct(ch) || isdigit(ch)) {
noalph++;
}
}
}
if (count > 0) {
count++;
}
//--------------------------------------------
cout << "Total Number of Words = " << count << endl;
cout << "Number of Words Beginning with a Vowel = " << vowel << endl;
cout << "Number of Words Beginning with a Consonant = " << cons << endl;
cout << "Number of Words Beginning with a Non-Alpha = " << noalph << endl;
return 0;
}
Example 1(
Input:--------------------------------------------------------------------
supercalifragilisticexpialidocious
A nonsense-word used esp. by children, now chiefly expressing excited
approbation: fantastic, fabulous.
Made popular by the Walt Disney film "Mary Poppins" in 1964. The
song containing the word was the subject of a copyright infringement
suit brought in 1965 against the makers of the film by Life Music
Co. and two song-writers: cf. quots. 1949, 1951. In view of earlier
oral uses of the word sworn to in affidavits and dissimilarity between
the songs the judge ruled against the plaintiffs.
Taken from the OED.
Output:--------------------------------------------------------------------
Total Number of Words = 86
Number of Words Beginning with a Vowel = 25
Number of Words Beginning with a Consonant = 55
Number of Words Beginning with a Non-Alpha = 5
Expected:------------------------------------------------------------------
Total Number of Words = 86
Number of Words Beginning with a Vowel = 25
Number of Words Beginning with a Consonant = 56
Number of Words Beginning with a Non-Alpha = 5
)
Example 2(
Input:--------------------------------------------------------------------
1996
bottle
12345
radar
a Toyota
Madam, I'm Adam
Was it a rat I saw?
Norma is as selfless as I am, Ron.
A man, a plan, a canal--Panama!
Tarzan raised Desi Arnaz' rat.
Hannah
Lewd did I live, & evil I did dwel.
Excerpts from "The Zen of Programming"
Mary said, "I like the STL."
Output:--------------------------------------------------------------------
Total Number of Words = 56
Number of Words Beginning with a Vowel = 20
Number of Words Beginning with a Consonant = 31
Number of Words Beginning with a Non-Alpha = 4
Expected:------------------------------------------------------------------
Total Number of Words = 56
Number of Words Beginning with a Vowel = 20
Number of Words Beginning with a Consonant = 31
Number of Words Beginning with a Non-Alpha = 5
)
As you can see it breaks at different points, maybe its something simple maybe it not, i would just like some help understanding what is going on, Thank You!
OK, you didn't followed advices in comments, so let do it explicitly.
You are skipping the first word.
Cause of the initialization in this line:
bool space = 0;
you should initialize it as true
bool space = true;
(yes, use true and false for boolean).
you should see that cause you added this lines
if (count > 0) {
count++;
}
to cover this problem. So, remove them.
You also skipped the #include <iostream> directive.

Putting ORs into if statement results in ISO C++ forbids comparison between pointer and integer (f-permissive)

I don't understand why it's reporting this error.
The error is ISO C++ forbids comparison between pointer and integer (f-permissive).
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cctype>
using namespace std;
int main()
{
int letters; //Total number of letters
int digits; //Total number of digits
int sentencecount; //Number of sentences
float averageletters; //Average number of letters per sentence
int linecount=0; //Count of lines
char current; //Current character
sentencecount = letters/linecount;
cin.get(current);
while (cin) //while receiving input
{
digits = 0;
letters = 0;
linecount++;
if (current == "." || current == "!" || current == "?") //checks each line
{
if (isalpha(current))//counts alphabet characters
letters++;
if (isdigit(current))//counts digits
digits++;
cin.get (current);
}
sentencecount = letters/linecount;
cout << "avg number of letters" << sentencecount << "digits" << digits << endl;
cin.get (current);
}
return 0;
}
On this line:
if (current == "." || current == "!" || current == "?")
You are using string literals or to phrase it correctly character arrays. Which translates to a pointer to that array. i think you meant to use single quotation the mark it as a single character with '. That way you are value comparing it.

How can I clean this program efficiently and still detect when the file input is not a letter?

Here is my whole program, I am supposed to calculate the average number of letters in words from an input file called hw4pr11input.txt. I have only been programming for a couple of weeks so I would appreciate simple answers that I could possibly implement with my small amount of knowledge. I do not know what arrays are yet, the chapter I am doing the homework for is on file io.
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
//function declaration
void average_letters(ifstream& fin);
//Precondition: there is a input file with text ready to be read
//postcondition: Text from the input file is read then the average length of
//words is calculated and output to the screen
//start main program
int main()
{
ifstream fin;
fin.open("hw4pr11input.txt"); //opening input file
if (fin.fail()) //checking for input file opening failure
{
cout << "Input file open fail";
exit(1); //terminating program if check fails
}
cout << "File Open\n";
average_letters(fin); //calling function to remove spaces
system("pause");
return 0;
}
//function definition, uses iostream and fstream
void average_letters(ifstream& fin)
{
char next, last_char = 0;
double letter_count = 0, word_count = 0;
double average = 0;
while(!(fin.eof()))
{
fin.get(next);
if(!(next == ' ' || next == ',' || next == '.' || next == '/'
|| next =='(' || next == ')'))
{
letter_count++;
}
else
{
if((next == ' ' || next == ',' || next == '.' || next == '/'
|| next =='(' || next == ')') && (last_char == ' ' || next == ','
|| next == '.' || next == '/' || next =='(' || next == ')' ))
{
continue;
}
else
{
word_count++;
}
}
last_char = next; //stores previous value of loop for comparison
}
average = letter_count/word_count;
cout << "The average length of the words in the file is:" << " " <<average;
cout << endl;
}
I believe this program works to accomplish the assignment, but my main concern is with the part of function average_letters that checks to see if it is a letter or a symbol. I chose this symbol list by looking at the .txt file. I deleted comments because they make copy and pasting here difficult I apologize if that makes my logic more difficult to understand.
Thanks for your help. Go easy on me :).
You can use a std::bitset<255> using the character converted to an unsigned integer and preset only those characters to true that are word characters. In your loop, you just lookup if its a valid word.
Note, this presupposes a char being 255 bits instead of unicode. You can up-size your bit set accordingly.
This allows you a very fast check of whether the character is a word character and allows you to define which characters you want to include (if the requirement changes suddenly to include '-', for example.
you could beautify this code by storing those groups of characters in strings. Then you could write a function which takes a char and a string and checks if the char is equal to any char in the given string. But that would require that you learn how to use arrays, because strings i C are arrays of chars.