I am rather new to c++ and I am taking my first course on it. I need to make a program that accepts input from the user like so "HelloHowAreYouToday" and at each capital letter turn it into a lower case letter and split apart the c string to look like this "Hello how are you today". Here is my code so far.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
using namespace std;
int main()
{
char sentence[100];
int size;
cout << "Enter a sentence with no spaces, make first letter in each word an upper case: ";
cin.getline(sentence, 100);
size = strlen(sentence);
char * manipSent = new char[size + 1];
for (int i = 1; i < size + 1; i++)
{
if (sentence[i] >= 'A' && sentence[i] <= 'Z')
{
manipSent[i] = ' ';
manipSent[i] = tolower(sentence[i]);
}
else;
manipSent[i] = tolower(sentence[i]);
}
manipSent[0] = sentence[0];
manipSent[size] = NULL;
cout << endl;
cout << "Original Sentence: " << sentence << endl;
cout << endl;
cout << "Altered Sentence: " << manipSent << endl;
delete[] manipSent;
return 0;
}
The issue I am having is splitting the words up, the out put looks like "Hellohowareyoutoday" but when I try to add a space in between the words the first letter in each word gets erased. Any input would be appreciated.
This is because whenever you put a space in your string, you immediately overwrite it by the lowercase version of the letter. If you write multiple values to one space, only the last value remains. This is why you don't have any spaces in your resulting string.
manipSent[i] = ' '; /* manipSent is now a space */
manipSent[i] = tolower(sentence[i]); /* overwrite manipSent[i] */
In order to do what you are trying to do, you need another variable besides i to keep track of where you are writing into manipSent. Look at the code below - I've created a new variable j that keeps up with i when you're copying characters, but if you add a space, it gets incremented again to deal with the fact that the new string is going to be larger than the old one.
for (int i = 1, j = 1; i < size + 1; i++, j++)
{
if (sentence[i] >= 'A' && sentence[i] <= 'Z')
{
manipSent[j] = ' ';
j++;
manipSent[j] = tolower(sentence[i]);
}
else;
manipSent[j] = tolower(sentence[i]);
}
It is important to remember that manipSent will be longer than sentence - in fact, it will be up to twice as long, so make sure you make manipSent bigger before you try adding spaces to it.
Related
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 recently have been building a program where:
A user is asked to enter a number that will represent the size of a character array.
Then they are asked whether they will want the program to fill the values automatically, or they could press M so they could enter the values manually. They may only enter a-zA-Z values, or they will see an error.
At the end of the program, I am required to count every duplicate value and display it, for example:
An array of 5 characters consists of A;A;A;F;G;
The output should be something like:
A - 3
F - 1
G - 1
I could do this easily, however, the teacher said I may not use an additional array, but I could make a good use of a few more variables and I also can't use a switch element. I'm totally lost and I can't find a solution. I've added the code down below. I have done everything, but the counting part.
#pragma hdrstop
#pragma argsused
#include <tchar.h>
#include <iostream.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
void main() {
int n, i = 0;
char masiva_izvele, array[100], masiva_burts;
cout << "Enter array size: ";
cin >> n;
clrscr();
cout << "You chose an array of size " << n << endl;
cout << "\nPress M to enter array values manually\nPress A so the program could do it for you.\n\n";
cout << "Your choice (M/A): ";
cin >> masiva_izvele;
if (masiva_izvele == 'M' || masiva_izvele == 'm') {
clrscr();
for (i = 0; i < n; i++) {
do {
cout << "Enter " << i + 1 << " array element: ";
flushall();
cin >> masiva_burts;
cout << endl << int(masiva_burts);
if (isalpha(masiva_burts)) {
clrscr();
array[i] = masiva_burts;
}
else {
clrscr();
cout << "Unacceptable value, please enter a value from the alphabet!\n\n";
}
}
while (!isalpha(masiva_burts));
}
}
else if (masiva_izvele == 'A' || masiva_izvele == 'a') {
clrscr();
for (i = 0; i < n; i++) {
array[i] = rand() % 25 + 65;
}
}
clrscr();
cout << "Masivs ir izveidots! \nArray size is " << n <<
"\nArray consists of following elements:\n\n";
for (i = 0; i < n; i++) {
cout << array[i] << "\t";
}
cout << "\n\nPress any key to view the amount of every element in array.";
//The whole thing I miss goes here, teacher said I would need two for loops but I can't seem to find the solution.
getch();
}
I would be very thankful for a solution so I could move on and forgive my C++ amateur-ness as I've picked this language up just a few days ago.
Thanks.
EDIT: Edited title to suit the actual problem, as suggested in comments.
One possible way is to sort the array, and then iterate over it counting the current letter. When the letter changes (for example from 'A' to 'F' as in your example) print the letter and the count. Reset the counter and continue counting the next character.
The main loop should run foreach character in your string.
The secondary loop should run each time the main "passes by" to check if the current letter is in array. If it's there, then ++.
Add the array char chars[52] and count chars in this array. Then print out chars corresponding to the array, which count is more than 1.
std::unordered_map<char, int> chars;
...
char c = ...;
if ('A' <= c && c <= 'Z')
++chars[c];
else if ('a' <= c && c <= 'z')
++chars[c];
else
// unexpected char
...
for (const auto p : chars)
std::cout << p.first << ": " << p.second << " ";
Assuming upper and lower case letters are considered to be equal (otherwise, you need an array twice the size as the one proposed:
std::array<unsigned int, 26> counts; //!!!
// get number of characters to read
for(unsigned int i = 0; i < charactersToRead; ++i)
{
char c; // get a random value or read from console
// range check, calculate value in range [0; 25] from letter...
// now the trick: just do not store the value in an array,
// evaluate it d i r e c t l y instead:
++counts[c];
}
// no a d d i t i o n a l array so far...
char c = 'a';
for(auto n : counts)
{
if(n > 0) // this can happen now...
{
// output c and n appropriately!
}
++c; // only works on character sets without gaps in between [a; z]!
// special handling required if upper and lower case not considered equal!
}
Side note: (see CiaPan's comment to the question): If only true duplicates to be counted, must be if(n > 1) within last loop!
For my code, I am trying to create a class with two functions that:
Display a cstring where each word is reversed
Display an entire cstring reversed
My two test sentences are "Hi There" and "To Be", so the output is:
erehT iH
eB oT
iH erehT
oT eB
Here is my code:
#include <iostream>
#include <cstring>
using namespace std;
class cStringType {
public:
char sentenceInput[80]; //Member variable
void reverse_sentence(); //Member function
void reverse_words(); //Member function
}; //Bottom of cStringType
int main()
{
cStringType sentence1, sentence2;
//Objects declared of cStringType
cout << "Please enter a sentence!\n" << endl;
cin.get(sentence1.sentenceInput, 79, '\n');
cin.ignore(80, '\n');
cout << "\nPlease enter another sentence!\n" << endl;
cin.get(sentence2.sentenceInput, 79, '\n');
cout << "\nThe first sentence reversed: ";
sentence1.reverse_sentence();
cout << endl;
cout << "The second sentence where each word is reversed: ";
sentence2.reverse_words();
cout << endl;
cout << endl;
cout << "The first sentence where each word is reversed: ";
sentence1.reverse_words();
cout << endl;
cout << "The second sentence reversed: ";
sentence2.reverse_sentence();
cout << endl;
return 0;
}
void cStringType::reverse_sentence()
{
char reverse_sentence;
//Reverse entire sentence using loop
for (int i = 0; i < strlen(sentenceInput) / 2; i++)
{
//Reverse the sentence using the length of the
//variable in the class
reverse_sentence = sentenceInput[i];
//First get the user input
//Set your variable equal to the variable in the class
sentenceInput[i] = sentenceInput[strlen(sentenceInput) - i - 1];
//Then reverse the characters and word order
//Starts from the last character in the array
//and goes backwards to 0
sentenceInput[strlen(sentenceInput) - i - 1] = reverse_sentence;
//Set the variable equal to the result
//sentenceInput is now the reverse of the user input in main
}
cout << sentenceInput << endl;
//Output of the new sentence
}
void cStringType::reverse_words()
{
int beginning, end, j = 0;
char reverse_words;
//Reverse each word separately using loop
for (int i = 0; i <= strlen(sentenceInput); i++)
//Get the length of the sentence in the class
{
if (sentenceInput[i] == ' ' || sentenceInput[i] == '\0')
//Check for spaces or null characters
//This allows only the letters of each word to be
//reversed, not the entire sentence
{
for (beginning = j, end = i - 1;
beginning < (i + j) / 2; beginning++, end--)
//j is the beginning of the array; increases
//i is the end of the array; decreases
{
reverse_words = sentenceInput[beginning];
//Set a variable equal to the first
//word in the original user input
sentenceInput[beginning] = sentenceInput[end];
//Set the first letter of a word equal to
//the last letter of a word
sentenceInput[end] = reverse_words;
//Set the result equal to the variable
//sentenceInput is now the user input where each
//word is reversed
}
}
j = i + 1;
}
cout << sentenceInput << endl;
//Output of the new sentence
}
When I try to run the code, the output becomes something like this:
Please enter a sentence!
Hi There
Please enter another sentence!
To Be
The first sentence reversed: erehT iH
The second sentence where each word is reversed: oT eB
The first sentence where each word is reversed: There Hi
The second sentence reversed: Be To
I tried fixing it, but to no avail. The output is never correct.
Is there some way to fix this issue? Or better yet, to simplify the code? I believe the issue is with the code in the function.
The main problem with your code is that it's using the same buffer for both transformations. In other words: you are reversing the words in the same string which you've already reversed entirely. So you need to have another copy of the original string to do these independently.
Regarding simplifying your code you need to define a function that would reverse a string given a pointer and size or begin and end pointers. Then you can use this function on your entire string or on every word you find while searching for a space character:
char *begin = sentenceInput; //points to the beginning of the word
char *end = sentenceInput + strlen(sentenceInput);
for (char *it = begin; it != end; ++it)
if (*it == ' ') {
reverse(begin, it);
begin = it + 1;
}
reverse(begin, end); //reverse the last word
The reverse function can be either std::reverse, which can be used in the above code and on the entire string as follows:
std::reverse(sentenceInput, sentenceInput + strlen(sentenceInput))
or you can create a similar function like this:
void reverse(char *begin, char *end)
{
--end; //point to the last character instead of one-past-last
while (begin < end)
std::swap(*begin++, *end--);
}
I would suggest using stack for it, it is a natural way of looking at it.
so
#include <stack>
and then the function would be like that
void cStringType::reverse_words()
{
int beginning, end, j = 0;
char reverse_words;
stack<char> lastWord;
//Reverse each word separately using loop
for (int i = 0; i <= strlen(sentenceInput); i++)
//Get the length of the sentence in the class
{
if (sentenceInput[i] == ' ' || sentenceInput[i] == '\0')
//Check for spaces or null characters
//This allows only the letters of each word to be
//reversed, not the entire sentence
{
//we want to print the last word that was parsed
while(!lastWord.empty())
{
//we print in the reverse order the word by taking off the stack char by char
cout<< lastWord.top();
lastWord.pop();
}
cout<<" ";
}
//if the letter is not space or end of string then push it on the stack
else
lastWord.push(sentenceInput[i]);
j = i + 1;
}
cout << sentenceInput << endl;
//Output of the new sentence
}
This is the question that needs to be implemented:
Write a C++ program that stops reading a line of text when a period is
entered and displays the sentence with correct spacing and capitalization. For this program, correct spacing means only one space between words, and all letters should be lowercase, except the first letter. For example, if the user enters the text "i am going to Go TO THe moVies.", the displayed sentence should be "I am going to go to the movies."
I have written my piece of code which looks like this:
// Processing a sentence and verifying if it is grammatically correct or not (spacing and capitalization)
//#include <stdio.h>
//#include <conio.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string sentence;
cout << "Enter the sentence: ";
getline(cin, sentence);
int len = sentence.length();
// Dealing with capitalizations
for (int j = 0; j <= len; j++)
{
if (islower(sentence[0]))
sentence[0] = toupper(sentence[0]);
if(j>0)
if(isupper(sentence[j]))
sentence[j] = tolower(sentence[j]);
}
int space = 0;
do
{
for (int k = 0; k <= len; k++)
{
if(isspace(sentence[k]))
{
cout << k << endl;
int n = k+1;
if(sentence[n] == ' ' && n <=len)
{
space++;
cout << space <<endl;
n++;
cout << n <<endl;
}
if(space!= 0)
sentence.erase(k,space);
cout << sentence <<endl;
}
}
len = sentence.length();
//cout << len <<endl;
} while (space != 0);
}
With this I was able to deal with capitalization issue but problem occurs when I try to check for more than one whitespace between two words. In the do loop I am somehow stuck in an infinite loop.
Like when I try and print the length of the string (len/len1) in the first line inside do-while loop, it keeps on running in an infinite loop. Similarly, when I try and print the value of k after the for loop, it again goes into infinite loop. I think it has to do with my use of do-while loop, but I am not able to get my head around it.
This is the output that I am receiving.
there are a few different issues with this code, but i believe that the code below addresses them. hopefully this code is readable enough that you can learn a few techniques. for example, no need to capitalize the first letter inside the loop, do it once and be done with it.
the usual problem with infinite loops is that the loop termination condition is never met--ensure that it will be met no matter what happens in the loop.
#include <iostream>
#include <string>
using namespace std;
int main() {
string sentence;
cout << "Enter the sentence: ";
getline(cin, sentence);
int len = sentence.find(".", 0) + 1; // up to and including the period
// Dealing with capitalizations
if (islower(sentence[0]))
sentence[0] = toupper(sentence[0]);
for (int j = 1; j < len; j++)
if(isupper(sentence[j]))
sentence[j] = tolower(sentence[j]);
// eliminate duplicate whitespace
for (int i = 0; i < len; i++)
if (isspace(sentence[i]))
// check length first, i + 1 as index could overflow buffer
while (i < len && isspace(sentence[i + 1])) {
sentence.erase(i + 1, 1);
len--; // ensure sentence decreases in length
}
cout << sentence.substr(0, len) << endl;
}
Here goes
std::string sentence;
std::string new_sentence;
std::cout << "Enter the sentence: ";
std::getline(std::cin, sentence);
bool do_write = false; // Looking for first non-space character
bool first_char = true;
// Loop to end of string or .
for (unsiged int i = 0; i < sentence.length() && sentence[i] != '.'; ++i) {
if (sentence[i] != ' ') { // Not space - good - write it
do_write = true;
}
if (do_write) {
new_sentence += (first_char ? toupper(sentence[i]) : tolower(sentence[i]);
first_char = false;
}
if (sentence[i] == ' ') {
do_write = false; // No more spaces please
}
}
if (i < sentence.length()) { // Add dot if required
new_sentence += '.';
}
What am I doing wrong with this small program.
I'm just starting to learn c++, and by all mean I can accept this as a moot question. I'm reading through the Prata c++ primer and it gave me a code example which takes a char array and uses strcmp() in a for loop which iterates sequentially through the ASCII code starting with '?' until a test char variable ==s a set value from another char.
Thinking I could outdo the book I tried to create a similar program which takes a char array and using a for loop will take a test char array and iterate through each value of the array until the two variables are equal.
I simplified the program to only take the first of each array in the for loop because I was experiencing a problem where the program seems to simply skip over the for loop and terminate.
Below are first the prata code snippet, followed by my piece of code. Any feedback (even abusive >_<) would be useful.
#include <iostream>
#include <cstring>
int main() {
using namespace std;
char word[5] = "?ate";
for (char ch = ‘a’; strcmp(word, "mate"); ch++) {
cout << word << endl;
word[0] = ch;
}
cout << "After loop ends, word is " << word << endl;
return 0;
}
My code (though maybe poorly done, I can accept that)
#include <iostream>
#include <cstring>
int main() {
using namespace std;
char word[5] = "word";
char test[5] = "????";
int j = 0;
int i = 0;
cout << "word is " << word << "\nTest is " << test << endl;
cout << word[0] << " " << test[0] << endl;
for (char temp = '?'; word[0] == test[0] || temp == 'z'; temp++) {
if ((word[i]) == (test[j])) {
test[j] = temp;
j++;
temp = '?';
}
test[j] = temp++;
cout << test << endl; //Added to see if the for loop runs through once,
//which is does not
}
return 0;
}
Your for loop never starts because your condition, shown here:
word[0] == test[0] || temp == 'z'
will always return false on its first pass. Since temp is initialized to '?' and word[0] (w) does not equal test[0] (?), your loop will never start.
Also, you've initialized temp to ? so, looking at an ascii chart, you'll see that there's a lot of non-alpha characters between ? and a lower case z.
Furthermore, within the for loop, you increment j (j++) but never touch i. Since you're reading chars from word with i as your index, test would end up being "wwww".
You seem to be confusing yourself so...
Lets break down what you're trying to do:
If you're iterating every character in a string, then checking each letter of the alphabet at that index, you're going to have two loops:
for(;;) {
for(;;) {
}
}
The first (iterating through each index in the string should end when the index reaches the end of the string (strings literals are terminated with a '\0'):
for(int i = 0; word[i] != '\0' && test[i] != '\0'; i++) {
for(;;) {
}
}
The second will check each letter of the alphabet (char temp = 'a' and temp++) against your given index in both word and test (word[i] != test[i];). If they're not equivalent, it will set the character of test at index i to temp until it finds the right letter. Putting it all together, you end up with this:
for(int i = 0; word[i] != '\0' && test[i] != '\0'; i++) {
for(char temp = 'a'; word[i] != test[i]; temp++) {
test[i] = temp;
}
}
Of course, if you were only going for results and not trying to teach yourself about loops and programming basics, this is all just a very roundabout way of simplay calling:
memcpy(temp, word, strlen(word));