How to count words in a file? - c++

I'm creating a program that counts how many words there are in a input file. I can't seem to figure out how to make it define a word with either whitespace, a period, a comma, or the beginning or end of a line.
Contents of input file:
hello world ALL is great. HELLO WORLD ALL IS GREAT. hellO worlD alL iS great.
Output should be 15 words meanwhile my output is 14
I've tried adding or's that include periods, commas etc. but it just counts those on top of the spaces as well.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
//Function Declarations
void findFrequency(int A[], string &x);
void findWords(int A[], string &x);
//Function Definitions
void findFrequency(int A[], string &x)
{
//Counts the number of occurences in the string
for (int i = 0; x[i] != '\0'; i++)
{
if (x[i] >= 'A' && x[i] <= 'Z')
A[toascii(x[i]) - 64]++;
else if (x[i] >= 'a' && x[i] <= 'z')
A[toascii(x[i]) - 96]++;
}
//Displaying the results
char ch = 'a';
for (int count = 1; count < 27; count++)
{
if (A[count] > 0)
{
cout << A[count] << " : " << ch << endl;
}
ch++;
}
}
void findWords(int A[], string &x)
{
int wordcount = 0;
for (int count = 0; x[count] != '\0'; count++)
{
if (x[count] == ' ')
{
wordcount++;
A[0] = wordcount;
}
}
cout << A[0] << " Words " << endl;
}
int main()
{
string x;
int A[27] = { 0 }; //Array assigned all elements to zero
ifstream in; //declaring an input file stream
in.open("mytext.dat");
if (in.fail())
{
cout << "Input file did not open correctly" << endl;
}
getline(in,x);
findWords(A, x);
findFrequency(A, x);
in.close();
system("pause");
return 0;
}
The output should be 15 when the result I am getting is 14.

Perhaps this is what you need?
size_t count_words(std::istream& is) {
size_t co = 0;
std::string word;
while(is >> word) { // read a whitespace separated chunk
for(char ch : word) { // step through its characters
if(std::isalpha(ch)) {
// it contains at least one alphabetic character so
// count it as a word and move on
++co;
break;
}
}
}
return co;
}

Here is an approach with a few test cases as well.
The test cases are a series of char arrays with particular strings to test the findNextWord() method of the RetVal struct/class.
char line1[] = "this is1 a line. \t of text \n "; // multiple white spaces
char line2[] = "another line"; // string that ends with zero terminator, no newline
char line3[] = "\n"; // line with newline only
char line4[] = ""; // empty string with no text
And here is the actual source code.
#include <iostream>
#include <cstring>
#include <cstring>
struct RetVal {
RetVal(char *p1, char *p2) : pFirst(p1), pLast(p2) {}
RetVal(char *p2 = nullptr) : pFirst(nullptr), pLast(p2) {}
char *pFirst;
char *pLast;
bool findNextWord()
{
if (pLast && *pLast) {
pFirst = pLast;
// scan the input line looking for the first non-space character.
// the isspace() function indicates true for any of the following
// characters: space, newline, tab, carriage return, etc.
while (*pFirst && isspace(*pFirst)) pFirst++;
if (pFirst && *pFirst) {
// we have found a non-space character so now we look
// for a space character or the end of string.
pLast = pFirst;
while (*pLast && ! isspace(*pLast)) pLast++;
}
else {
// indicate we are done with this string.
pFirst = pLast = nullptr;
}
}
else {
pFirst = nullptr;
}
// return value indicates if we are still processing, true, or if we are done, false.
return pFirst != nullptr;
}
};
void printWords(RetVal &x)
{
int iCount = 0;
while (x.findNextWord()) {
char xWord[128] = { 0 };
strncpy(xWord, x.pFirst, x.pLast - x.pFirst);
iCount++;
std::cout << "word " << iCount << " is \"" << xWord << "\"" << std::endl;
}
std::cout << "total word count is " << iCount << std::endl;
}
int main()
{
char line1[] = "this is1 a line. \t of text \n ";
char line2[] = "another line";
char line3[] = "\n";
char line4[] = "";
std::cout << "Process line1[] \"" << line1 << "\"" << std::endl;
RetVal x (line1);
printWords(x);
std::cout << std::endl << "Process line2[] \"" << line2 << "\"" << std::endl;
RetVal x2 (line2);
printWords(x2);
std::cout << std::endl << "Process line3[] \"" << line3 << "\"" << std::endl;
RetVal x3 (line3);
printWords(x3);
std::cout << std::endl << "Process line4[] \"" << line4 << "\"" << std::endl;
RetVal x4(line4);
printWords(x4);
return 0;
}
And here is the output from this program. In some cases the line to be processed has a new line in it which affects the output by performing a new line when printed to the console.
Process line1[] "this is1 a line. of text
"
word 1 is "this"
word 2 is "is1"
word 3 is "a"
word 4 is "line."
word 5 is "of"
word 6 is "text"
total word count is 6
Process line2[] "another line"
word 1 is "another"
word 2 is "line"
total word count is 2
Process line3[] "
"
total word count is 0
Process line4[] ""
total word count is 0
If you need to treat punctuation similar to white space, as something to be ignored, then you can modify the findNextWord() method to include the ispunct() test of characters in the loops as in:
bool findNextWord()
{
if (pLast && *pLast) {
pFirst = pLast;
// scan the input line looking for the first non-space character.
// the isspace() function indicates true for any of the following
// characters: space, newline, tab, carriage return, etc.
while (*pFirst && (isspace(*pFirst) || ispunct(*pFirst))) pFirst++;
if (pFirst && *pFirst) {
// we have found a non-space character so now we look
// for a space character or the end of string.
pLast = pFirst;
while (*pLast && ! (isspace(*pLast) || ispunct (*pLast))) pLast++;
}
else {
// indicate we are done with this string.
pFirst = pLast = nullptr;
}
}
else {
pFirst = nullptr;
}
// return value indicates if we are still processing, true, or if we are done, false.
return pFirst != nullptr;
}
In general if you need to refine the filters for the beginning and ending of words, you can modify those two places with some other function that looks at a character and classifies it as either a valid character for a word or not.

Related

Unexpected Values Being Read Into Memory with getline() - C++

I wrote this program for an intro to C++ course. My issue is that unexpected values are being stored in memory. I assume it has to do with input.getline() or the way certain characters are stored, but I don't know enough about what is happening "under the hood" to fix it.
Specifically, certain characters like apostrophes and quotation marks appear to not read as their hex ASCII counterparts.
I'm pretty certain the issue lies in the lines
input.getline(raw_paragraph, MAX_PARAGRAPH_CHARS);
charCount = strlen(raw_paragraph);
Below I've included the complete code, a screenshot of the Memory from Visual Studio 2022, the test case, and the program output .
Thank you in advance!
#pragma warning(disable : 4996) //DEV
/**************************************************************************************
Header Content
**************************************************************************************/
// Includes and namespaces ------------------------------------------------------------
#include <cstdlib> // Defines functions such as exit().
#include <cstring> // Defines functions such as strcmp, etc.
#include <fstream> // Supports file I/O
#include <iostream> // Supports terminal I/O
using namespace std;
// Constants Declared -----------------------------------------------------------------
// Maximum allowable space for input / Defines space for memory allocation
const int MAX_WORD_CHARS = 50; // Longest word = 50 chars
const int MAX_WORDS = 1000; // Longest paragraph = 1000 words
const int MAX_PARAGRAPH_CHARS = 50000; // 50 * 1000
// "to be" Semantics
const char TO[] = "to";
const char BE[] = "be";
const int NUM_TO_BE_VERBS = 5; // Qty of "to be verbs below
const char TO_BE_VERBS[NUM_TO_BE_VERBS][MAX_WORD_CHARS] =
{ "am", "are", "is", "was", "were" };
// Conjunctions
const int NUM_CONJUNCTIONS = 7; // Qty objects in CONJUNCTIONS below.
const char CONJUNCTIONS[NUM_CONJUNCTIONS][MAX_WORD_CHARS] =
{ "for", "and", "nor", "but", "or", "yet", "so" };
// Punctuation
const int NUM_PUNCTUATIONS = 4;
const char PUNCTUATIONS[NUM_PUNCTUATIONS] = { '.', ',', '?', '!' };
// Functions Declared -----------------------------------------------------------------
int countComplex(char a[][MAX_WORD_CHARS], int b);
int countSentences(char a[], int b);
int count_to_be_verbs(char a[][MAX_WORD_CHARS], int wc);
void init_array(char* a);
void modify_tokens(char a[][MAX_WORD_CHARS], int wc);
int tokenizeParagraph(char p[], char tp[][MAX_WORD_CHARS]);
/**************************************************************************************
Begin Main
**************************************************************************************/
int main()
{
// Format Output
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(1);
// Create input space for user's file request
char filename[256]; // Stores the user defined filename containing plaintext
init_array(filename);
char raw_paragraph[MAX_PARAGRAPH_CHARS]; // Stores plaintext from filename
init_array(raw_paragraph);
// Declare Variables
int charCount = 0; // Number of chars contained in input file except eof.
int complex_count; // Number of complex sentences
int sentenceCount = 0; // Total number of sentences in input
int simpleSent = 0; // Number of simple sentences in input
int to_be_count; // Number of instances of "to be" verbs in input.
int wordCount = 0; // Number of words in input
double averageWordsPerSentence;
// Asks the user for the name of an input file which contains a paragraph
cout << "Enter a filename: ";
cin.getline(filename, 256);
// Try to load the file in filename:
ifstream input;
input.open(filename);
// If file does not exist, cout error then exit(1)
if (input.fail())
{
cout << "Input file " << filename << " does not exist." << endl;
cout << "Thank you for using the English Analyzer." << endl;
exit(1);
}
// If file is empty, cout "Input file _____ is empty." Then exit(1)
char c;
input.get(c);
if (input.eof())
{
cout << "File " << filename << " is empty." << endl;
cout << "Thank you for using the English Analyzer." << endl;
exit(1);
}
else
input.putback(c);
// Store plaintext from file to raw_paragraph
input.getline(raw_paragraph, MAX_PARAGRAPH_CHARS);
// Close ifstream input, will not need it again.
input.close();
// Allocate memory for the output of tokenizeParagraph
char tkn_para[MAX_WORDS][MAX_WORD_CHARS];
// Count chars
charCount = strlen(raw_paragraph);
// Tokenize paragraph, count words
wordCount = tokenizeParagraph(raw_paragraph, tkn_para);
// Count Sentences
sentenceCount = countSentences(raw_paragraph, charCount);
// Average words per sentence
averageWordsPerSentence = double(wordCount) / double(sentenceCount);
// Count Complex Sentences
complex_count = countComplex(tkn_para, wordCount);
// Calculate Simple Sentences
simpleSent = sentenceCount - complex_count;
// Count "to be" verbs
modify_tokens(tkn_para, wordCount);
to_be_count = count_to_be_verbs(tkn_para, wordCount);
// Cout results
cout << "Number of Characters: " << charCount << endl;
cout << "Number of words: " << wordCount << endl;
cout << "Number of sentences: " << sentenceCount << endl;
cout << "Average number words in a sentence: " << averageWordsPerSentence << endl;
cout << "Number of simple sentences: " << simpleSent << endl;
cout << "Number of \"to be\" verbs: " << to_be_count << endl;
}
/**************************************************************************************
Function Definitions
**************************************************************************************/
int countComplex(char a[][MAX_WORD_CHARS], int b)
{
// counter will keep the number of complex sentences found.
int counter = 0;
// For each word in tkn_para,
for (int i = 0; i < b; i++)
{
// If a comma is at the end of tkn_m,
int s = strlen(a[i]) -1;
if (a[i][s] == ',')
{
// For each word in CONJUNCTIONS
for (int x = 0; x < NUM_CONJUNCTIONS; x++)
{
// If the words match,
if (strcmp(a[i + 1], CONJUNCTIONS[x]) == 0)
{
// Increment counter
counter++;
// If a word from a has already been matched, there
// is no reason to try to compare it to more items
// from CONJUNCTIONS. Therefore,
break;
}
}
}
}
// After all iteration has been completed:
return(counter);
}
int countSentences(char a[], int b)
{
int counter = 0;
// For each char in a[]
for (int i = 0; i < b; i++)
{
// If a[i] is an end of sentence punctuation,
if (a[i] == '.' || a[i] == '?' || a[i] == '!')
// Increment counter
counter++;
}
return counter;
}
int count_to_be_verbs(char a[][MAX_WORD_CHARS], int wc)
{
int counter = 0;
// For each word in a:
for (int i = 0; i < wc; i++)
// For each word in TO_BE_VERBS:
for (int y = 0; y < NUM_TO_BE_VERBS; y++)
{
// If words match:
if (strcmp(a[i], TO_BE_VERBS[y]) == 0)
counter++;
}
// For loop checks for "to" token followed by "be"
for (int i = 0; i < wc; i++)
if (strcmp(a[i], TO) == 0 && strcmp(a[i + 1], BE) == 0)
counter++;
return(counter);
}
void init_array(char* a)
{
// For every char in a:
for (int i = 0; i < strlen(a); i++)
// Set the value of a[i] to NULL
a[i] = NULL;
}
void modify_tokens(char a[][MAX_WORD_CHARS], int wc)
{
// For each word in a:
for (int i = 0; i < wc; i++)
{
// Does the computation once instead of 4 times below.
int s = strlen(a[i]) -1;
// Converts first char if uppercase, into lowercase
if (int('#') < a[i][0] && a[i][0] < int('['))
a[i][0] = a[i][0] + 32;
// Convert last char, if punctuation mark, into NULL
if (a[i][s] == ',' || a[i][s] == '!' || a[i][s] == '?' || a[i][s] == '.')
a[i][s] = NULL;
}
}
int tokenizeParagraph(char p[], char tp[][MAX_WORD_CHARS])
{
int i = 0;
char* cPtr;
cPtr = strtok(p, " \n\t");
while (cPtr != NULL)
{
strcpy(tp[i], cPtr);
i++;
cPtr = strtok(NULL, " \n\t");
}
return(i);
}
Turns out that the issue has to do with copying the test case into MS Word or another like application. There are character equivalents to apostrophes and quotation marks that "lean" left or right. Those characters are actually distinct and are responsible for the memory values I've been encountering. It suggests to me that a future iteration of the code would have to parse the raw input for those types of characters and replace them.

Find subword included input symbol c++

I want to print a subword, after inputting my symbol.
For example like this.
I want input abcdefghijk d
And get efghijk
This is my code body without condition.
#include <iostream>
int main(){
const int n = 21;
char word[n];
std::cin>>word;
char symbol;
std::cin>>symbol;
int i = 0;
char*p = word;
while(word[i]!='\0' && word[i]!=symbol){
// what condition I need to write here?
i++;
std::cout << p <<std::endl;
}
return 0;
}
Thanks for helping))
You need to move your pointer p to the right while the splitting character is not met.
char*p = word;
while(word[i]!='\0' && word[i]!=symbol){
p++;
i++;
}
p++;
std::cout << p << std::endl;
On the first line, your pointer p points to the begining of the word (i.e. on the first char).
Then the while loop tests every char until we find the splitting char. Everytime a character does not match you splitting character, you increase p and make it point to the next character.
However, you would need to increase it one final time after the loop to point after the splitting char.
Note that a shorter way to do is:
char*p = word;
while(word[i]!='\0' && word[i]!=symbol){
i++;
}
p = p + i + 1;
std::cout << p << std::endl;
You could try something like this:
int main()
{
std::string text;
std::cout << "Enter sentence: ";
std::getline(std::cin, text);
char split_char;
std::cout << "Enter subword / split character: ";
std::cin >> split_char;
std::string::size_type split_position = text.find(split_char);
std::string::size_type word_end_position = text.find_first_of(" \t", split_position);
if (word_end_position == std::string::npos)
{
word_end_position = text.length();
}
std::string split_text = text.substr(split_position, word_end_position, split_position);
std::cout << split_text << "\n";
return 0;
}

c++ count words in array

I need to write a function that gets a string and count how many words there are in the string and how many letters. And then calculate the average of it.
A word in a string is a sequence of letters and numbers separated by one or more spaces.
First of all I have to check if the string is correct. The string must contain only lowercase letters, uppercase letters, and numbers only.
i didnt menage to count all sort of words correctly and also my function doesnt count the last letter.
#include <iostream>
using namespace std;
#include <string.h>
#define SIZE 50
float checkString(char string[]) {
float wordCounter = 0;
float letterCounter = 0;
bool isLegit = true;
int i = 0;
while (isLegit) {
if (((string[i] >= 48 && string[i] <= 57) ||
(string[i] >= 65 && string[i] <= 90) ||
(string[i] >= 97 && string[i] <= 122 ))) {
for (int j = 0; j <= strlen(string); j++) {
if ((string[j - 1] != ' ' && string[j] == ' ' &&
string[i + 1] != ' ')
|| j == (strlen(string) - 1)) {
wordCounter++;
}
else if (string[j] != ' ') {
letterCounter++;
cout << string[j];
}
}
cout << " The avareage is : " << (letterCounter /
wordCounter) << endl;
isLegit = false;
}
else {
return -1;
isLegit = false;
}
}
cout << "Number of words " << wordCounter << endl;
cout << "Number of letters " <<letterCounter << endl;
}
int main() {
char string[SIZE];
cout << "please enter a sentence " << endl;
cin.getline(string, SIZE);
checkString(string);
}
Instead of using char[] for strings, I suggest that you use std::string which can grow and shrink dynamically. It's one of the most common types to use in the standard C++ library. You can also make use of stringstreams which lets you put a string inside it and then you can extract the contents of the stringstream using >>, just like when reading from std::cin.
Example with comments in the code:
#include <iostream>
#include <sstream> // std::stringstream
#include <string> // std::string
// use std::string instead of a char[]
float checkString(const std::string& string) {
// put the string in a stringstream to extract word-by-word
std::istringstream is(string);
unsigned words = 0;
unsigned letters = 0;
std::string word;
// extract one word at a time from the stringstream:
while(is >> word) {
// erase invalid characters:
for(auto it = word.begin(); it != word.end();) {
// Don't use magic numbers. Put the character literals in the code so
// everyone can see what you mean
if((*it>='0' && *it<='9')||(*it>='A' && *it<='Z')||(*it>='a' && *it<='z')) {
// it was a valid char
++it;
} else {
// it was an invalid char, erase it
it = word.erase(it);
}
}
// if the word still has some characters in it, make it count:
if(word.size()) {
++words;
letters += word.size();
std::cout << '\'' << word << "'\n"; // for debugging
}
}
std::cout << "Number of words " << words << "\n";
std::cout << "Number of letters " << letters << "\n";
std::cout << "The average number of letters per word is "
<< static_cast<float>(letters) / words << '\n';
return 0.f; // not sure what you are supposed to return, but since the function
// signature says that you should return a float, you must return a float.
}
int main() {
checkString(" Hello !!! World, now let's see if it works. ");
}
I would like to add an additional answer. This answer is based on "more-modern" C++ and the usage of algorithms. You want to solve 3 tasks:
Check, if string is OK and matched to your expectations
Count the number of words in the given string
Count the number of letters
Calculate the ratio of words/letters
For all this you may use existings algorithms from the C++ standard library. In the attached example code, you will see a one-liner for each task.
The statements are somehow very simple, so that I will not explain much more. If there should be a question, I am happy to answer.
Please see here one possible example code:
#include <iostream>
#include <string>
#include <iterator>
#include <regex>
#include <algorithm>
#include <tuple>
#include <cctype>
std::regex re("\\w+");
std::tuple<bool, int, int, double> checkString(const std::string& str) {
// Check if string consists only of allowed values, spaces or alpha numerical
bool stringOK{ std::all_of(str.begin(), str.end(), [](const char c) { return std::isalnum(c) || std::isspace(c); }) };
// Count the number of words
int numberOfWords{ std::distance(std::sregex_token_iterator(str.begin(),str.end(), re, 1), {}) };
// Count the number of letters
int numberOfLetters{ std::count_if(str.begin(), str.end(), isalnum) };
// Return all calculated values
return std::make_tuple(stringOK, numberOfWords, numberOfLetters, static_cast<double>(numberOfWords)/ numberOfLetters);
}
int main() {
// Ask user to input string
std::cout << "Please enter a sentence:\n";
// Get string from user
if (std::string str{}; std::getline(std::cin, str)) {
// Analyze string
auto [stringOk, numberOfWords, numberOfLetters, ratio] = checkString(str);
// SHow result
std::cout << "\nString content check: " << (stringOk ? "OK" : "NOK") << "\nNumber of words: "
<< numberOfWords << "\nNumber of letters: " << numberOfLetters << "\nRatio: " << ratio << "\n";
}
return 0;
}
Of course there are many more other possible solutions. But, because of the simplicity of this solution, I showed this variant.

Program Won't Continue to Run When Testing for Palindromes (C++)

I'm a beginner in coding with C++. I'm trying to make a program that completes a specific set of tasks:
opens a data file,
takes each line of the file,
processes each line by removing all whitespace and punctuation,
converts the string into all lowercase,
uses a recursive method to test if the string is a palindrome,
finds a position within the string where characters can be added to make it a palindrome if it isn't already,
then adds the characters needed to make it a palindrome in the position specified in (6).
I'm only allowed to use 4 user-defined functions with specific parameters. So far I've got about 80% of the program to work, but there's an error when it detects a non-palindrome. I'm hoping someone can find out why. Here's my code:
// Read file data, check for palindromes, and process strings to palindromes.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
string process(string);
bool is_palindrome(string);
int palindrome_fix_location(string);
string palindrome_addition(string, int);
int main()
{
ifstream inFile;
inFile.open("data");
string preString;
int palinLoc = 0;
while(getline(inFile, preString))
{
cout << "\nOriginal line: " << preString << endl;
cout << "Processed line: " << process(preString) << endl;
if (is_palindrome(preString) == true)
cout << "Line is palindrome." << endl;
else
cout << "Line is NOT a palindrome." << endl;
palindrome_fix_location(preString);
palindrome_addition(preString, palinLoc);
}
inFile.close();
return 0;
}
// Return a string that is lowercase with no punctuation or spacing.
string process(string preString)
{
string procString;
for (size_t i = 0; i < preString.length(); i++)
{
if (isalnum(preString[i]))
procString += tolower(preString[i]);
}
return procString;
}
// Uses a recursive method to determine if the processed string is a palindrome.
bool is_palindrome(string procString)
{
string temp = process(procString);
int length = temp.length();
string firstChar = temp.substr(0, 1);
string lastChar = temp.substr((length - 1), 1);
if (firstChar == lastChar)
{
temp = temp.substr((0 + 1), (length - 2));
if (temp.length() <= 1) // Base case.
return true;
return is_palindrome(temp); // Recursion.
}
else
return false;
}
// Return a location where text can be added to the non-palindrome to make it a palindrome.
int palindrome_fix_location(string procString)
{
string temp = process(procString);
if (is_palindrome(temp) == false)
{
int palinLoc;
int firstChar = 0, lastChar = temp.length() - 1;
while (firstChar < lastChar)
{
if (temp[firstChar] != temp[lastChar])
{
palinLoc = firstChar;
cout << "Characters to insert at location "
<< palinLoc << " are ";
return palinLoc;
}
}
}
return 0;
}
// Return the text that needs to be added at the "palinLoc" location.
string palindrome_addition(string procString, int palinLoc)
{
string temp = process(procString);
string addedChars;
string finalString;
if (is_palindrome(temp) == false)
{
int firstChar = 0, lastChar = temp.length() - 1;
while (firstChar < lastChar)
{
do {
addedChars += temp[lastChar];
} while (temp[firstChar] != temp[lastChar]);
firstChar++;
lastChar--;
}
finalString = temp.insert(palinLoc, addedChars);
cout << addedChars << endl;
cout << "Final word: " << finalString << endl;
return finalString;
}
else
return finalString;
}
And here's the output I get:
Original line: lappal
Processed line: lappal
Line is palindrome.
-
Original line: lapal
Processed line: lapal
Line is palindrome.
-
Original line: A man, a plan, a canal, Panama!
Processed line: amanaplanacanalpanama
Line is palindrome.
-
Original line: lap
Processed line: lap
Line is NOT a palindrome.
Right there when it says "Line is NOT a palindrome," it's supposed to follow up with something that looks like this:
Characters to insert at location 0 are pa
Final line: palap
It just stops at "Line is NOT a palindrome." Can anyone see where I went wrong with this?
Any help would be greatly appreciated.
your loop here (in palindrome addition) is bugged
do {
addedChars += temp[lastChar];
} while (temp[firstChar] != temp[lastChar]);
it never ends
so you should move either lastchar or firstchar change inside, like this for example
while (firstChar < lastChar)
{
do {
addedChars += temp[lastChar];
lastChar--;
} while (temp[firstChar] != temp[lastChar])
firstChar++;
}
some run here
Original line: lap
Processed line: lap
Line is NOT a palindrome.
start palindrom fix
Characters to insert at location 0 are
start palidrome addition
pa
Final word: palap
Original line: lapin
Processed line: lapin
Line is NOT a palindrome.
start palindrom fix
Characters to insert at location 0 are
start palidrome addition
nipa
Final word: nipalapin
Original line: lapal
Processed line: lapal
Line is palindrome.

Counting individual word lengths in a string

#include <iostream>
#include <string>
#include <cctype>
size_t countwords(const char *);
using namespace std;
int main()
{
char a[] = "Four score and seven years ago";
float sum = 0.0;
char j[10];
string s;
int size = sizeof(a)/sizeof(char);
for(int i = 0; i < size; i++){
if(!isspace(a[i])){
s += a[i];
}
if(isspace(a[i]) and !isspace(a[i + 1])){
cout << s << " " << s.length() << endl;
sum += s.length();
s = "";
}
}
cout << countwords(a);
return 0;
}
size_t countwords( const char *s )
{
size_t count = 0;
while ( *s )
{
while ( isspace( *s )) ++s;
if ( *s ) ++count;
while ( isalnum( *s )) ++s;
}
return ( count );
}
In the main function, I am able to print each word and it's word length. such as four 4, score 5 etc. I am having trouble handling the last word "ago." I don't know how to account for that. Any help would be appreciated.
Output:
Four 4
score 5
and 3
seven 5
years 5
▼ 2
6
and yeah, don't know why that black triangle is in the output but this is the exact output.
The terminating NULL character is not considered whitespace, so your second if condition returns false when it encounters the end of the string.
Seems to me the statements within the for statement can be simplified to
if(!isspace(a[i]) && a[i]){
s += a[i];
} else {
cout << s << " " << s.length() << endl;
sum += s.length();
s = "";
}
Also, breaking the string apart at whitespace can be done easily using an istringstream
char a[] = "Four score and seven years ago";
std::istringstream ss(a);
std::string s;
while(ss >> s) {
std::cout << s << ' ' << s.length() << '\n';
}
The string you try to inspect is one character longer than you expect:
int size = sizeof(a)/sizeof(char);
This size includes the terminating null character. If I were to deal with the assignment I would either operator on char const* and use the C convention of checking against a terminating null character or I would convert the array into a std::string and deal with iterator and check against the end iterator. I also think that the logic you have to check against the end of a word assumes that words are separated by exactly one space.
Your countwords() function seems to deal with the C convention. Your main() function should check against a[i] being null before using !isspace(static_cast<unsigned char>(a[0])): the countwords() works because isspace(0) and isalnum(0) are false. However, just because 0 isn't a space it means it is part of a word. You should also consider the terminating null character a word separator, i.e., the condition to report the length of a word should be
if(!a[i] || isspace(static_cast<unsigned char>(a[i])))
std::string word;
std::istringstream str(a);
while (str >> word) {
sum += str.length();
std::cout << word << ' ' << word.length << '\n';
}