How to reverse all words in a string? C++ [duplicate] - c++

This question already has answers here:
Reversing order of words in a sentence
(8 answers)
Closed 9 years ago.
So.. I'm sorry I doubleposted. I really didn't know how this site works. However, I'm changing my whole question here so that it's more understandable. And here it is:
char s[1002];
cin.getline(s, 1002, '\n');
int k;
int p = strlen(s);
strcat(s, " ");
for (int i = 0; i <= p; i++)
{
if (s[i] == ' ')
{
for (k = i - 1; (k != -1) && (s[k] != ' '); k--)
cout << s[k];
cout << " ";
}
}
' ' , ',' , '.' and ';' should be delimiters but I've managed to pull it to work only with ' ' (intervals).
I cannot use std::string as I'm doing this for a homework where I need to make a very specific function - char const* reverseWordsOnly(const char*).
What should the code do?
Input: Reversing the letters, is; really hard.
Output: gnisreveR eht srettel, si; yllaer drah.

While I still feel this is a duplicate, the thought process for solving this would be this:
Write a function that returns true for alphabet characters (a-z and A-Z), and false otherwise.
Start at the beginning of the string
Find the next alphabet character, note its location (start)
Find the next non-alphabet character, note its location (end)
Reverse the characters in the range [start, end)
Repeat steps 3-5 until the end of the string
All of this becomes very easy when you use std::string and algorithms like std::reverse instead of using raw arrays and custom. Since you are allowed to use std::cin and std::cout (<iostream>), the argument against using <string> is a silly one.

You can store the string in another array without the symbols first and then reverse the new array. For example if you want to ignore a comma (,) or semicolon (;) you can write something like
while(i <= p)
{
if (s[i] == ',' || s[i] == ';')
{
i++;
}
else
{
temp[j]=s[i];
j++;
i++;
}
}
Then you can reverse the temp array.

Instead of just printing the letters like this
for (k = i - 1; (k != -1) && (s[k] != ' '); k--)
cout << s[k];
cout << " ";
Check to see if you need to ignore the letter, like this
for (k = i - 1; (k != -1) && (s[k] != ' '); k--)
if((s[k] != ',') && (s[k] != ';') && ...other ignored chars...)
cout << s[k];
cout << " ";

#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
int main(){
char s[1001],ch;
int c=0; // for counting how many words are in the array
while((ch = getchar()) != '\n'){ // input string until new line
if ((ch>='a' && ch<='z') || (ch>='A' && ch<='Z')) // check if the input character is a letter or symbol
s[c++] = ch; // if its a letter then insert into the array
}
for (int i=c-1;i>=0;i--) // print the array in reverse order
cout<<s[i]<<" ";
return 0;
}

Related

Determining the amount of letters in each word of a string in C++

I'm new to c++ and coding in general and I ran into a bit of an issue in one of my assignments. I'm just looking for some input and hopefully an explanation on why my code isn't working.
I'm trying to get input from a user and use a cin.get() function to count all the characters in that string. I do this because I want to determine the letters in each word of the string. Now my issues are I can't get it to print the result correctly.
My question is: Why can't I get a result when I try to determine if my variable chr is a '\n' character? chr is the variable that hold the value of the current character being read by the cin.get() function) is a '\n'.
I want to be able to update the parameters (word1, word2.....) of my function countWordsByLegth() when the current value of chr is '\n' or in other words the end of the string.
The following code, for example, won't run and it's the only way I know how to update my parameter for a string that contains no spaces (one word strings):
if (counter == 5 && chr == '\n')
{
++word5;
counter =0;
}
Here's my code for reference. The function isWhitespace() just determines if the character is one of the following '\n' , '\r' , '\t'):
while (cin.get(chr) && chr != '\n')
{
counter++;
if (isWhitespace(chr))
{
--counter;
//test = true;
}
if (counter == 5 && chr == '\n')
{
++word5;
counter =0;
}
if (counter == 4 && chr =='\n')
{
++word4;
counter =0;
}
if (counter == 3 && chr =='\n')
{
++word3;
counter =0;
}
if (counter == 2 && chr == '\n')
{
++word2;
counter =0;
}
if (counter ==1 && chr == '\n')
{
++word1;
counter =0;
}
cout << counter << endl; // Test code {delete later}
}
cout << "This is the total of word5: " << word5 << endl;
}
You could use std::string.length() to get the amount of chars in a string.
The length() function returns the number of chars in the string.
#include <iostream>
#include <string>
int main()
{
std::string s;
s = "test";
std::cout << "The string has " << s.length() << " letters!";
}
http://www.cplusplus.com/reference/string/string/ here you can read about the different functions that you can use with strings.

debugging c++ program with <set> containers

The problem is to find all vowels all even words in a sentence share, in other words these vowels have to be met in any even word in the sentence.
But i when i enter for example: "ewedyua aiuye dswidje ieuayj eeee eeeui dajhdfjcne aodijsbfe".
I get: e i u
but "e i" is expected as the last even word doesn't contain 'u' (I use " " just for separation here in the text and don't use them in the output)
The program:
int main(){
string str;
char ch = ' ';
set<char> strSet;
set<char> resultSet;
set<char> tempSet;
int count = 1;
int i = 0;
cout << "Enter a line: ";
getline(cin, str);
str = delOverSpace(str); // delete excessive gaps<br>
do {
ch = str.at(i);
if(((count % 2) == 0) && (ch != ' ')){ // this is an even word and not a gap
if(isVowel(upperToLower(ch))) // this is a vowel
tempSet.insert(upperToLower(ch));
}
if (ch == ' ') { // if we've passed through the word add inforamtion on it
if(((count % 2) == 0) && (count / 2) == 1)
strSet.insert(tempSet.begin(), tempSet.end());
else if (((count % 2) == 0) && (count / 2) != 1){
set_intersection(
strSet.begin(),strSet.end(), tempSet.begin(), tempSet.end(),
insert_iterator<set<char> >(resultSet, resultSet.begin())
);
strSet.clear();
tempSet.clear();
strSet.insert(resultSet.begin(), resultSet.end());
resultSet.clear();
}
count++;
}
i++;
}while(ch != '.');
if (count == 2) cout << "Only one word was entered" << endl;
else if (strSet.empty()) cout << "No vowels were found" << endl;
else {
copy(strSet.begin(), strSet.end(), ostream_iterator<char>(cout, " "));
cout << endl;
}
return 0;
}
Try not to use one counter variable for multiple purposes.
For example you could use count for the current character count within the current word and words for word count.
In your example, you're making count work too hard.
Decide what you are counting. Do you want to count every character?
Or do you want to count the characters in the current word?
When incrementing a counter, try to put this next to the logic that needs it.
Eg, i++ should go right after you've used it to get the next character.
And count should be incremented in the block that handles letters (ie not space, not dot).
If the counters get too far away from what they are keeping track of, you can introduce bugs.
Move the space check up first and also check for end of sentence with .
Clear indentation helps to follow the code - I use 4 characters, but 2 or 3 is ok.
1 character indents are hard to read.
Use blank lines to separate different chunks of logic.
You might want to add logic to handle punctuation like ,, ?, ! etc.
When you're processing an input string which is separated into words, it's often easier to handle the end of input condition outside the loop.
In this case, the loop exits after it picks up the last letter.
If that is not a . then you'll have an unprocessed word sitting in tempSet.
You can try and anticipate this within the loop, but it seems more natural to exit the loop and check if there is anything left to process.
If you separate your logic into clearly separated blocks, you can set breakpoints inside each block.
You'll then know what situation you're handling. You can break inside end-of-word logic and check tempSet and count.
Are they what you expect?
And in the else part you can check ch going in and verify that it is classified as a vowel properly.
int main() {
string str;
char ch = ' ';
set<char> strSet;
set<char> tempSet;
int count = 0, words = 0, i = 0;
cout << "Enter a line: ";
getline(cin, str);
str = delOverSpace(str); // delete excessive gaps<br>
while ( i < str.size() && ch != '.' ) {
// Get next character
ch = str.at(i);
i++;
if (ch == ' ' || ch == '.' ) { // if we've passed through the word add inforamtion on it
if( count > 0 && ((count % 2) == 0)) {
strSet.insert(tempSet.begin(), tempSet.end());
words++;
}
count = 0; // reset the char counter
tempSet.clear(); // clear the temp vowel set
}
else {
// letter - not a space or a dot, increase the character count
count++;
if(isVowel(upperToLower(ch))) // this is a vowel
tempSet.insert(upperToLower(ch));
}
}
// pick up any unprocessed word if we hit end of input without seeing '.'
if (count > 0 && ((count % 2) == 0)) {
strSet.insert(tempSet.begin(), tempSet.end());
words++;
}
if (words == 0)
cout << "No words entered" << endl;
else if (words == 1)
cout << "Only one word was entered" << endl;
else if (strSet.empty())
cout << "No vowels were found" << endl;
else {
copy(strSet.begin(), strSet.end(), ostream_iterator<char>(cout, " "));
cout << endl;
}
return 0;
}

What is wrong with this Pig Latin program?

What it's supposed to do
My piglatin program is supposed to take a phrase from user input and output it into pig latin. Basically it would turn a word such as "hello" into "ellohay".
My problem
When I input hello my man the output is ellohay y man an may and when I just input hello my the output is ellohay y may. As you can see, after it translates the first word successfully, it struggles on the second word. It places a space after the y and mayI cannot figure out for the life of me why this keeps happening. The output is even stranger when I input more than two words, as shown above. What I want to happen is for it to output ellohay ymay anmay when I input hello my man. Code is below. Thanks!
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void phrase_Parser(string); // Goes through phrase and looks for ' ' to then pass to pigLatin_Translator()
void pigLatin_Translator(string);
int main()
{
string phrase; //used for user word or phrase to be translated to piglatin
cout << "Enter any word: ";
getline(cin, phrase);
phrase_Parser(phrase);
return 0;
}
void phrase_Parser(string phrase) {
int startCount = 0;
for (int i = 0; i < phrase.length(); i++) {
if (phrase[i] == ' ') {
string word = phrase.substr(startCount, i);
startCount = (i + 1); // decides where to start the word next time it is ran through
pigLatin_Translator(word); // runs word through translator
}
}
}
void pigLatin_Translator(string word) {
string partOne;
string partTwo;
for (int x = 0; x < word.length(); x++) {
if (word[0] == 'q' && word[1] == 'u') {
cout << word.substr(2, word.length()) << word.substr(0, 2) << "ay ";
break;
}
else if ((word[x] == 'a') || (word[x] == 'e') || (word[x] == 'i') || (word[x] == 'o') || (word[x] == 'u') || (word[x] == 'y')) {
partOne = word.substr(x, word.length()); //from first vowel to end of word
partTwo = word.substr(0, x); // from first letter to first vowel, not including the vowel
cout << partOne << partTwo << "ay "; // adding "ay" to the end of the word
break;
}
}
}
Your problem is in the line string word = phrase.substr(startCount, i);
You are using substr incorrectly. The second argument to substr is the length of the substring you wish to extract. Replace i with i-startCount and you should be good to go.
Alternatively, search for a nicer way to split strings. There are a number of options that are much easier than doing it manually.

C++ cin.ignore To ignore spaces, numbers, and characters to test a palindrome

I need to process a user input to see if it is a palindrome. Our professor said to use cin.ignore() to ignore spaces, numbers, and other characters so we will just compare the letter inputs.
So far I have just found code that ignores just one of these at a time and the code is more advanced than my learning so I do not know how to modify or apply it to my code.
I have the code to check the palindrome, I just do not know how to make it ignore the unwanted inputs.
Sorry this sort of question has been asked many times over but I cannot seem to figure it out.
Thanks in advance.
do
{
checkInput = false;
cout << "Enter the Palindrome: ";
getline(cin, input);
len = input.length();
if (len == 0)
{
cout << "\nNo data was entered, please enter a palindrome.\n";
checkInput = false;
}
} while (checkInput);
for (int i = 0, j = input.size() - 1; i < input.size(); i++, j--)
{
if (input[i] != input[j] && input[i] + 32 != input[j] && input[i] - 32 != input[j])
{
isPalindrome = false;
break;
}
}
if (isPalindrome)
{
cout << "This is a Palindrome!!" << endl;
}
else
{
cout << "This is not a Palindrome." << endl;
}
im assuming that input is a string. if so then what we want to do before your for loop is have another for loop to run through the string and remove anything unwanted from the string. I am going to assume that all you want to deal with are the upper and lowercase letters, as we are focusing on the ascii values between 65-90 and 97-122. source http://www.ascii-code.com/
to so do we can simply check each index in the string to see if it falls between these two ranges, and if it doesn't, then delete it.
for(unsigned int i = 0; i<input.size();i++)
{
if(input[i]< 65 || (90 <input[i] && input[i] < 97) || input[i] > 122)
{
input.erase(i,1);
i--
}
}
that should work.

confusing when concat string in c++

I just try to test how to split word in C++ but I faced with very unknown error. This problem really drives me insane, I don't know why it happens.
This is my code:
std::string key = "hello world";
std::string word = "";
for (int i = 0; i < (int)key.length(); i++)
{
if (std::isspace(key[i]) || key[i] == '\0')
{
std::cout << word << "\n";
word.clear();
}
else
word += key[i];
}
The result is just only "Hello", I tried to debug and figure out why the word stop concating after the isspace condition? So could anyone please point me the correct direction?
Thanks
Edited: Tried the following, and now its missing the letter d in the end?
if (std::isspace(key[i]) || key[i + 1] == '\0')
{
Edit 2: Solved with this:
if (std::isspace(key[i]) || key[i + 1] == '\0')
{
if (key[i + 1] == '\0')
word += key[i];
key[j] == 0 will never happen, the string length doesn't count the terminating 0, so the last word won't ever be printed out.
Remove that test, and add a second std::cout << word after the loop.
Why it is not working
Because this condition is never met:
key[i] == '\0'
Because j is always less than key.length() and (theoretically) the '\0' character is supposed to be at key[key.length()] you never reach it and thus don't print out the second word.
Of you change key to:
std::string key = "hello world again";
You will see it print
hello
world
But it will not print again.
Looking at it from a C perspective
C-String (not C++ std::string) is terminated with '\0'
So if you want to continue down the current path and look for the '\0' character you need to use C-Strings.
To do this you could change the for() so that j is <= to key.length(). But be careful C++ std::string is not like a C-String. The character at key[key.length()] is not valid and you are not allowed to access it. What you should do is convert the C++ std::string into C-String with c_str().
char tmp = key.c_str()[j];
if (std::isspace(tmp) || tmp == '\0')
Alternatively
You can just print word after the loop (if it is not empty)
std::string key = "hello world";
std::string word = "";
for (int j = 0; j < (int)key.length(); j++)
{
if (std::isspace(key[j]) || key[i] == '\0')
{
std::cout << word << "\n";
word.clear();
}
else
word += key[j];
}
if (!word.empty())
{ std::cout << word << "\n";
}