c++ - string confrontation issue - c++

I have to create a little program in C++, expecting a string in input and outputting its content in letters (How many As it's got, and so on).
I'm doing this by creating an integer array of 26 blocks, and confronting with a for cycle my string with the string "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and the lower-case one. If a correspondence is found with index i, the i-th array block's value is incremented by one, and the for cycle is broken.
However, I have a little problem: if a character not present in the alphabet string is inserted (like a whitespace, or an apostrophe), it is counted as a correspondence for i=0 (letter A). However, if I include that character too in my alphabet string, and cycle through it with my for, the problem does not occur.
This is my .cc file (functions implementation)
#include "08.Count.h"
#include <string>
#include <iostream>
using namespace std;
int chartoint (char a) {
//Converts an alphabetic character to its corresponding position in the alphabet (as an integer)
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string alphabet2 = "abcdefghijklmnopqrstuvwxyz";
for (int i=0; i<26; i++)
if ((a==alphabet[i])||(a==alphabet2[i])) {
//check if the char corresponds to the upper-case OR lower-case i-th letter of the alphabet
return i;
//when we find a correspondence, we output the point at where we've found it
break;
//waste of time continuing cycling if the correspondence is already found
}
}
void list (string word) {
//Outputs the alphabetic distribution of the input string
int array[26];
//array to store the correspondence data for each alphabet letter
for (int i=0; i<26; i++)
array[i]=0; //Initialize
for (int i=0; word[i]!='\0'; i++)
array[chartoint(word[i])]++;
//chartoint(word[i]) outputs the position of the alphabet the i-th character of the string word corresponds. We increment the value of that position in the array by one
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i=0; i<26; i++)
if (array[i]!=0)
cout << array[i] << " " << alphabet [i] << ", ";
//we output the distribution in letters, but only for the letters that are found at least one time
}
And this is my main program
#include <iostream>
#include <string>
#include "08.Count.h"
using namespace std;
int main()
{
string word;
cout << "Insert phrase" << endl;
getline(cin, word);
//To avoid the input string being terminated by a whitespace
cout << "The phrase " << word << " contains:" << endl;
list (word);
cout << endl;
}

In your chartoint function there is only one return inside loop. There are no measures to handle when a character is not an alphabet. So in that case the return value is undefined(for you it is returned as 0)
So change the function chartoint as
int chartoint (char a) {
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string alphabet2 = "abcdefghijklmnopqrstuvwxyz";
for (int i=0; i<26; i++)
if ((a==alphabet[i])||(a==alphabet2[i])) {
return i;
}
return -1; // <------ indicates a is not an alphabet
}
Change the function list as
void list (string word) {
int array[26],index;
for (int i=0; i<26; i++)
array[i]=0; //Initialize
for (int i=0; word[i]!='\0'; i++)
{
index = chartoint(word[i]);
if(index!=-1) // <--- Check returned index
array[index]++;
}
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i=0; i<26; i++)
if (array[i]!=0)
cout << array[i] << " " << alphabet [i] << ", ";
}
So if returned index is not -1 increment the corresponding character count by 1. Else ignore it because it is not an alphabet.

Related

How to count the number of times a letter shows up in a randomized string of alphabetical letters

I am trying to find the number of times each letter of the alphabet shows up in a randomized string that the user creates. I have all the code, minus the portion that would count each time a character is found. I have tried to use a couple of for...else loops to figure this out, but maybe I am just not learned to do it correctly, I keep either getting errors or a blank space under the rest of the output.
What I want is for the output to look like this:
A B C D E F G...
1 2 5 7 0 9 2...
Here is my code and my output so far:
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <map>
using namespace std;
int main() {
int i=0, n;
char alphabet[26];
char c;
char RandomStringArray [100];
srand(time(0));
cout <<"How many letters do you want in your random string (no less than 0, no more than 100): ";
cin >> n;
for (int i=0; i<=25; i++)
alphabet[i] = 'a' + i;
while(i<n) {
int temp = rand() % 26;
RandomStringArray[i] = alphabet[temp];
i++;
}
for(i=0; i<n; i++)
cout<<RandomStringArray[i];
cout<<"\n\n";
/*for(c = 'A'; c <= 'Z'; ++c)
cout<<" "<<c;
cout<<"\n";
*/
map<char,size_t> char_counts;
for (int i = 0; i < n; ++i) ++char_counts[RandomStringArray[i]];{
for (char ch :: alphabet) std::cout << ch << ' ';{
std::cout << '\n';
}
for (char ch :: alphabet) std::cout << char_counts[ch] <<'';{
std::cout << '\n';
}
}
}
std::unordered_map is good for this sort of thing. It's similar to the array approach of holding counts for each character but is more convenient to use, especially when the character ranges you're interested in are non-contiguous.
When you index a std::unordered_map the mapped value will be returned by reference, so you just increment it. If it doesn't exist it's created and default initialized (zero initialized for integer types).
So all you need to do is:
std::unordered_map<char, std::size_t> char_counts;
for (int i = 0; i < n; ++i) ++char_counts[RandomStringArray[i]];
After this, char_counts holds the total occurrence counts for all characters in the string. e.g. char_counts['a'] is the number of occurrences of 'a'.
Then to print them all out you could do:
for (char ch : alphabet) std::cout << ch << ' ';
std::cout << '\n';
for (char ch : alphabet) std::cout << char_counts[ch] << ' ';
std::cout << '\n';

I need to return number of words in c sting after taking user input

I need to make a program that takes input from the user and then return the number of words entered to the string. I store user input in array char words[256]; I have a function called countWords. It loops though the array and if it encounters a space he counter is increased. if(words[i] == '\0') if the null character is reached the counter is stopped. It then return nSpaces + 1 to account for the first word.
But my output seems to produce the number of characters in the string instead. How can this be fixed.
#include <iostream>
#include <cstdlib>
using namespace std;
//Function Prototype
int countWords(char words[]);
int main(){
char words[256];
cout << "Enter a sentence: ";
cin.getline(words, 256);
int word_num = countWords(words);
cout << "The number of words in a string is: " << word_num << endl;
system("PAUSE");
return 0;
}
int countWords(char words[]){
int nSpaces = 0;
//unsigned int i = 0;
/*while(isspace(words[i])){
i++;
}*/
for (int i=0; i<256; i++){
if(isspace(words[i])){
nSpaces++;
// Skip over duplicate spaces & if a NULL character is found, we're at the end of the string
//while(isspace(words[i++]))
if(words[i] == '\0')
nSpaces--;
}
}
// The number of words = the number of spaces + 1
return nSpaces + 1;
}
The Output is:
Enter a sentence: Yury Stanev
The number of words in a string is: 7
You're not stopping the loop when you get to the null character. You're only testing for the null character inside the if(isspace(words[i])) block, but if the character is a space then it can't also be the null terminator. As a result, you're reading past the end of the input, and counting the spaces in the uninitialized part of the string.
int countWords(char words[]){
int nSpaces = 0;
for (int i=0; i<256 && words[i] != '\0'; i++){
if(isspace(words[i])){
nSpaces++;
}
}
// The number of words = the number of spaces + 1
return nSpaces + 1;
}
isspace counts new lines (\n), tabs (\t), \v, \f and \r.
Probably you want only white-spaces? Check for " " and "\t" only.

Permutation Issue

So I have a program here that is supposed to print to the screen permutations of a user input word that can be 4 to 10 characters long and there are supposed to be as many permutations as there are letters in the word. I almost have complete success, but there is one issue. When it prints the permutations, after the first about 2 permutations, it starts to not use all the letters and/or the same letter twice.
For example, if the user input word is "bill", the output is as follows:
llib illb ibll lbii
The fourth is is obviously not correct. The problem is more apparent with words that have more letters. I need it to only use the letters it has once. How do I go about fixing this in my code? Here is my code.
int main(void)
{
string word;
string randword;
string reverse;
int length;
int i = 0;
int j = 0;
string randCH;
cout << "Enter any word 4 to 10 letters in length: ";
cin >> word;
//Checks if word is less than 4 or greater than 10
while (1)
{
/*The code here is in the final program and I know it works. The problem is not here*/
}
length = word.length();
//Uses reverse function
reverse = reverseit(word);
/*reverseit is a function outside of main that makes the word backwards*/
//Prints all permutations
cout << endl << reverse << " ";
for (i = 0; i < word.length() - 1; i++)
{
for (j = 0; j < word.length(); j++)
{
randCH = word.substr(rand() % length, 1);
cout << randCH;
}
cout << " ";
cout << endl;
you can use std::next_permutation which is already built to achieve this:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string word;
cin >> word;
sort(word.begin(),word.end());
do {
cout << word <<endl;
} while(next_permutation(word.begin(),word.end()));
}

Store a word into a dynamically created array when first encountered

Here is the assignment:
Write a program that reads in a text file one word at a time. Store a word into a dynamically created array when it is first encountered. Create a paralle integer array to hold a count of the number of times that each particular word appears in the text file. If the word appears in the text file multiple times, do not add it into your dynamic array, but make sure to increment the corresponding word frequency counter in the parallel integer array. Remove any trailing punctuation from all words before doing any comparisons.
Create and use the following text file containing a quote from Bill Cosby to test your program.
I don't know the key to success, but the key to failure is trying to please everybody.
At the end of your program, generate a report that prints the contents of your two arrays in a format similar to the following:
Word Frequency Analysis
I 1
don't 1
know 1
the 2
key 2
...
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int readInFile (string tempArray [], string file, int arraySize);
int main()
{
ifstream inputFile;
string *readInArray = 0,
*compareArray = 0,
filename,
word;
int wordCount = 0;
int encountered = 0;
int j = 0,
*wordFrequency = 0;
cout << "Enter the filename you wish to read in: ";
getline(cin, filename);
inputFile.open(filename.c_str());
if (inputFile)
{
while (inputFile >> word)
{
wordCount++;
}
inputFile.close();
readInArray = new string[wordCount];
readInFile(readInArray, filename, wordCount);
}
else
{
cout << "Could not open file, ending program";
return 0;
}
compareArray = new string[wordCount];
wordFrequency = new int[wordCount];
for (int count = 0; count < wordCount; count++)
wordFrequency[count] = 0;
for(int i = 0; i < wordCount; ++i)
{
j = 0;
encountered = 0;
do
{
if (readInArray[i] == compareArray[j])
encountered = 1;
++j;
} while (j < wordCount);
if (encountered == 0)
{
compareArray[i]=readInArray[i];
wordFrequency[i] += 1;
}
}
for(int k=0; k < wordCount; ++k)
{
cout << "\n" << compareArray[k] << " ";
}
for(int l=0; l < wordCount; ++l)
{
cout << "\n" << wordFrequency[l] << " ";
}
return 0;
}
int readInFile (string tempArray [], string file, int arraySize)
{
ifstream inputFile;
inputFile.open(file.c_str());
if (inputFile)
{
cout << "\nHere is the text file:\n\n";
for(int i=0; i < arraySize; ++i)
{
inputFile >> tempArray[i];
cout << tempArray[i] << " ";
}
inputFile.close();
}
}
Here is my question:
How do you store a word into a dynamically created array when it is first encountered? As you can see from my code made a string array with some of the elements empty. I believe it is suppose to be done using pointers.
Also how do I get rid of the punctuation in the string array? Should it be converted to a c-string first? But then how would I compare the words without converting back to a string array?
Here is a link to a java program that does something similar:
http://math.hws.edu/eck/cs124/javanotes3/c10/ex-10-1-answer.html
Thank you for any help you can offer!!
As to the first part of your question, you are not using a dynamically created array. You are using a regular array. C++ provides implementations of dymnamic arrays, like the vector class http://www.cplusplus.com/reference/vector/vector/
As to the second part of your question, I see no reason to convert it to a c string. The string class in c++ provides functionality for removing and searching for characters. http://www.cplusplus.com/reference/string/string/
The string::erase function can be used to erase punctuation characters found with string::find.
Note: There are other ways of doing this assignment that may be easier (like having an array of structs containing a string and an int, or using a map) but that may defeat the purpose of the assignment.

Consonant counting program not returning number of consonants

This program is supposed to compare the list of consonants to a user input list of letters and print out the number of consonants in the user's input. However, it just prints 0. I'm very new to C++ and am not experienced in finding logic errors.
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
int counter(char *, char);
int main()
{
const int size = 51;
char input[size];
const char consonants[22] = "bcdfghjklmnpqrstvwxyz";
cout << "Enter your letters." << endl;
cin >> input;
cout << consonants << "appears";
cout << counter(input, consonants[22]) << "times" << endl;
}
int counter(char *strPtr, char ch)
{
int times = 0;
while (*strPtr != '\0')
{
if (*strPtr == ch)
times++;
strPtr++;
}
return times;
}
I'm aware you're new to C++, and this looks like some kind of exercise you are doing in order to learn, but I will post this answer so you can see how get this done using some of the C++ standar functions.
Using find function from algorithm
string test = "Hello world";
string vowels("aeiuo"); // Its much easier to define vowels than consonants.
int consonants_count = test.length(); // Assume all letters are consonants.
for (auto &c : test) // for each character in test
{
if (find(vowels.begin(), vowels.end(), c) != vowels.end()) // If c is founded inside vowels ...
{
consonants_count--; // Decrement the number of consonants.
}
}
Using regular expressions
#include <regex>
string test = "Hello world"; // A test string.
regex re("a|e|i|o|u"); // Regular expression that match any vowel.
string result = regex_replace(test, re, ""); // "Delete" vowels.
cout << result.length() << endl; // Count remaining letters.
Three problems:
You are not passing an array of consonants, you are passing a single character
You are passing an invalid character (one past the end of the consonant array)
You are counting how many times that invalid character is present.
To fix this problem, make sure that you pass an array as the second parameter, and add a nested loop to iterate that array.
your function counter if checking the input char by char and compare it to a single char(ch).
you need to run your counter function on all the chars in consonants array, or change the counter function:
int count = 0
for(int i = 0; i < 22 ; i ++)
{
count += counter(input, consonants[i])
}
now an even better way will be to count the non consonants characters and then do length-count
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
int counter(char *, char);
int main()
{
const int size = 51;
char input[size];
cout << "Enter your letters." << endl;
cin >> input;
cout << consonants << "appears";
cout << counter(input) << "times" << endl;
}
int counter(char *strPtr)
{
int times = 0;
int length = 0;
const char consonants[5] = "aeoui";
while (*strPtr != '\0')
{
for(int i = 0; i < 5 ; i ++)
{
if (*strPtr == consonants[i])
times++;
strPtr++;
length++;
}
}
return length-times;
}