Print backwards in c++ - c++

Here is a program where I enter a sentence and print it backward...
#include<iostream>
#include<string>
using namespace std;
int main(int argc, char* argv[]) {
string scrambleWords;
cout << "Please enter a sentence to scramble: ";
getline(cin, scrambleWords);
for (int print = scrambleWords.length() - 1; print >= 0; print--)
{
if (isspace(scrambleWords[print]))
{
for (unsigned int printIt = print + 1;
printIt < scrambleWords.length(); printIt++)
{
cout << scrambleWords[printIt];
if (isspace(scrambleWords[printIt]))
break;
}
}
}
for (unsigned int gotIt = 0; gotIt < scrambleWords.length(); gotIt++)
{
cout << scrambleWords[gotIt];
if (isspace(scrambleWords[gotIt]))
break;
}
cout << endl;
}
// OUTPUT
// Please enter a sentence: birds and bees
// beesand birds
// Press any key to continue . . .
As you can see there was no space between bees & birds, so how can I add the space in there?

The cleanest and easiest solution is to rely on the standard libraray:
// 1. Get your input string like you did
// 2. Save the sentence as vector of words:
stringstream sentence {scrambleWords};
vector<string> words;
copy(istream_iterator<string>{sentence},istream_iterator<string>{},
back_inserter(words));
// 3 a) Output the vector in reverse order
for (auto i = words.rbegin(); i != words.rend(); ++i)
cout << *i << " ";
// 3 b) or reverse the vector, then print it
reverse(words.begin(),words.end());
for (const auto& x : words)
cout << x << " ";

You may use something like (C++11 for auto): (http://ideone.com/mxOCM1)
void print_reverse(std::string s)
{
std::reverse(s.begin(), s.end());
for (auto it = s.begin(); it != s.end(); ) {
auto it2 = std::find(it, s.end(), ' ');
std::reverse(it, it2);
it = it2;
if (it != s.end()) {
++it;
}
}
std::cout << s << std::endl;
}

Add a space when you reached the end of the original input line:
if printIt == scrambleWords.length()-1
cout << " ";
Put this code in the inner for loop, after
if (isspace(scrambleWords[printIt]))
break;
Note that breaking out of a for loop is not going to win you any programming beauty contests.

Related

How to print `[` and `,` and `]` in streams that extract from keyboard by `cin`

I'm new in c++. I want to print [ at the beginning and ] at the end of stream when i print some string by keyboard. also it must be print , between each of string. notice number of strings is unknown. for example if i print in screen: ggg hhh jj klk the result of program must be: [ggg,hhh,jj,klk]. I've tried this:
string cur = "";
while (cin >> cur)
{
cout << "[" << cur << ",";
}
but this wrong!
Edit: by #NadavS 'sanswer we have this:
by #asmmo 's answer we have this:
but my expectation is:
sss ddd fff ggg
[sss,ddd,fff,ggg]
ddf hjh lk iop
[ddf,hjh,lk,iop]
If your compiler supports it, std::experimental::ostream_joiner does this.
#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
int main()
{
std::cout << "[";
std::copy(std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
std::experimental::make_ostream_joiner(std::cout, ","));
std::cout << "]";
}
Outputs [ggg,hhh,jj,klk] from ggg hhh jj klk
I always program these loops with some code duplication. There are other solutions, but the general concept is separating the first case from the others.
string cur = "";
cout << '[';
if (cin >> cur) {
cout << cur;
while (cin >> cur) {
cout << ',' << cur;
}
}
cout << ']';
Demo
edit: Despite the fact this solution works, the question asker views his "stdin" and "stdout" in "the same window", so the output doesn't look pretty, and the solution should be to store a list of strings from cin and only then start printing.
string cur = "";
std::vector<string> all_strings;
while (cin >> cur) {
all_strings.push_back(cur);
}
cout << '[';
bool first = true;
for (auto& a : all_strings) {
if (first) {
first = false;
} else {
cout << ", ";
}
cout << a;
}
cout << ']';
You must make the loop stop at some point but you didn't. So you can send an EOF at the end of your inputs to make it stops (using ctrl+z on windows and ctrl+D on other OSs). And to get the wanted format change your loop to
int main()
{
string cur = "";
cout << "[ ";
if( cin >> cur) cout << cur;
while (true)
{
cin >> cur;
if( !cin )
{
cout << "]" ;
break;
}
cout << "," << cur;
}
}
If you want to separate the inputs and outputs, you can do the following
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> vec;
std::string temp{};
while(std::cin >> temp) vec.push_back(temp);
std::cout << "\n[ " << vec[0];
for(int i {1}; i < vec.size(); i++) std::cout << ", " << vec[i];
std::cout << "]";
}
To make cin stop inputting on pressing Enter, use std::cin.peek() which can know the next character without taking it from the stream, as follows
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> vec;
std::string temp{};
while(std::cin >> temp && !(std::cin.peek() == '\n')) vec.push_back(temp);
std::cout << "\n[" << vec[0];
for(int i {1}; i < vec.size(); i++) std::cout << ", " << vec[i];
std::cout << "]";
}

Find words beginning with 's' using set/multiset

The issue I'm having with this code stems from the last block of code for the get_words_beginning_s function.
/*
Name: xx
Date: xx
Purpose:Read text from file, count number of words, unique words, word frequency, & number of words that begin with letter 's'
*/
#include <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;
multiset<string> display_and_load_words(string filename);
set<string> get_unique_words(multiset<string>& words);
set<string> get_words_beginning_s(multiset<string>& words);
int main() {
cout << "The Word Counter program\n\n";
string filename = "dickens.txt";
cout << "FILE TEXT: ";
//display_text(filename);
auto words = display_and_load_words(filename);
cout << "WORD COUNT: " << words.size() << endl << endl;
auto unique_words = get_unique_words(words);
auto words_beginning_s = get_words_beginning_s(words);
cout << unique_words.size() << " UNIQUE WORDS: ";
for (string word : unique_words) {
cout << word << ' ';
}
cout << endl << endl;
cout << "COUNT PER WORD: ";
for (string word : unique_words) {
cout << word << '=' << words.count(word) << ' ';
}
cout << endl << endl;
cout << "WORDS THAT BEGIN WITH 'S': ";
for (string word : words_beginning_s) {
cout << word << ' ';
}
cout << endl << endl;
}
multiset<string> display_and_load_words(string filename) {
multiset<string> words;
ifstream infile(filename);
if (infile) {
string word;
while (infile >> word) {
cout << word << ' ';
string new_word = "";
for (char c : word) {
if (c == '.' || c == ',') {
continue; // remove punctuation
}
else if (isupper(c)) {
new_word += tolower(c); // convert to lowercase
}
else {
new_word += c;
}
}
words.insert(new_word); // add word
}
cout << endl << endl;
infile.close();
}
return words;
}
set<string> get_unique_words(multiset<string>& words) {
set<string> unique_words;
for (string word : words) {
auto search = unique_words.find(word);
if (search == unique_words.end()) {
unique_words.insert(word);
}
}
return unique_words;
}
set<string> get_words_beginning_s(multiset<string>& words) {
set<string> words_beginning_s;
for (string word : words) {
auto search = words_beginning_s.find(word);
if (search == words_beginning_s.end()) {
for (int i = 0; i < words_beginning_s.size(); ++i) {
if (words_beginning_s[0] == 's') {
words_beginning_s.insert(word);
}
}
}
}
return words_beginning_s;
}
If working with set/multiset, how does one compare positional values within each separate word itself, rather the entire words? Example string in text file - "John goes to the store": Whereas normally a simple for loop can be used with the initial position to compare values and count number of times it appears (something like)-
for (int i = 0; i < words_beginning_s.length(); ++i) {
if (words_beginning_s[0] == 's') {
++s_word;
}
This does not work when using set/multiset. Pretty new to this, so sorry if this question seems dumb.
You can use the multisets member function lower_bound to get iterators to a range and then create a set from that range.
Example:
#include <iostream>
#include <set>
#include <string>
std::set<std::string> get_words_beginning_s(const std::multiset<std::string>& words) {
// create a set from the iterators you get from lower_bound("s") and lower_bound("t"):
return {words.lower_bound("s"), words.lower_bound("t")};
}
int main() {
std::multiset<std::string> words{
"foo", "slayer", "bar", "sepultura", "tesseract", "skinny puppy", "yello"
};
for(const std::string& word : get_words_beginning_s(words)) {
std::cout << word << '\n';
}
}
Output:
sepultura
skinny puppy
slayer

Vector of strings comparison C++

I am writing a code about input strings, then compare them with other elements in the vector and, if there's a positive match, don't put them into. I wrote this:
// NamePair.cpp : definisce il punto di ingresso dell'applicazione console.
//
#include "stdafx.h"
#include "std_lib_facilities.h"
#include <vector>
int _tmain(int argc, _TCHAR* argv[])
{
vector<string> names;
vector<int> scores;
string name = "0";
int score = 0;
int error = 0;
int n = 0;
cout << "Type a name and a score: " << endl;
while (cin >> name >> score) {
++n;
cout << "This is # " << n << " name you typed." << endl;
if (n >= 2) {
for (int i : scores) {
if (names[i] == name) {
cout << "You have already typed this name dude!" << endl;
}
else if (name != "NoName") {
names.push_back(name);
scores.push_back(score);
}
else {
break;
}
}
}
}
for (int i = 0; i < scores.size(); ++i) {
cout << names[i] << "\t" << scores[i] << endl;
}
keep_window_open();
return 0;
}
The issue is that when I am trying to run the program it works but it seems to be stuck at a point where I continuously add names and scores but it doesn't do anything apparently (neither shows a warning message nor stops if "NoName" string is typed). I can't figure out why! I have tried to re-write it all but with the same result...
Thanks for help!
Your checking whether name exists in vector is wrong. Change
if (names[i] == name) {
to
if ((std::find(names.begin(), names.end(), name) != names.end()) {
Also, it looks like the for (int i : scores) loop is unnecessary here.
An std::map would be best suitable here. This code snippet will help you
#include <bits/stdc++.h>
using namespace std;
int main() {
map<string, int> data;
string name;
int score;
for (int n = 0; cin >> name >> score; ++n) {
if (name != "NoName" || !data.count(name))
data[name] = score;
}
for (auto & i : data)
cout << i.first << " " << i.second << endl;
return 0;
}
See http://ideone.com/j3Gkiw
Your issue is in your for loop.
You try to push new elements into your vector inside the loop that iterates the vector. The vector starts out empty, so the program will never enter the loop and you will never actually push any elements into the vectors.

How to count unique words in string and output line where they occur? C++

So I'm working on this homework assignment and I'm really having trouble. I'm supposed to count the number of words more than two characters(have to contain one letter), unique words, and the number of times each unique word appears in the Programming Execution Environment. I'm also supposed to get input to search for in the PEE and output the number of times it appears and the line where it appears. I have some of it working, but I'm really struggling with counting how many times each word appears. I know my code is really bad right now, but that's why I'm here. I'm really struggling with these string functions for some reason. Any help is really appreciated!
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
//PEE string
string envstr("");
bool checkChar(unsigned c)
{
return (ispunct(c) || isspace(c) || isblank(c) || isdigit(c) || c == '\n');
}
void searchWord(unsigned c, size_t length)
{
multiset<string> words;
vector<string> vwrds; //this was something i was trying out
string tempword;
while (!checkChar(envstr[c]) && c < length)
{
tempword = tempword + envstr[c]; //problem here
c++;
}
tempword = tempword + " ";
vwrds.push_back(tempword);
words.insert(tempword); //this is just a bunch of random letters
tempword.clear();
//for (multiset<string>::const_iterator i(words.begin()), end(words.end()); i != end; i++)
//cout << *i;
}
bool checkIfWord(char c)
{
bool valid = false;
int i;
for (i = c; i > c - 2; i--)
{
if (!checkChar(envstr[i]))
valid = true;
}
if (valid)
searchWord(i, envstr.length());
return valid;
}
int main()
{
//this code given by my instructor
extern char **environ; // needed to access your execution environment
int k = 0;
size_t wordCount = 0;
while (environ[k] != NULL)
{
cout << environ[k] << endl;
string str(environ[k]);
envstr = envstr + str;
k++;
}
//iterator to count words
wordCount = count_if(envstr.begin(), envstr.end(), checkIfWord);
cout << "\nThe PEE contains " << wordCount << " words. \n";
//transform environment string to lowercase
transform(envstr.begin(), envstr.end(), envstr.begin(), tolower);
string input;
do
{
cout << "Enter your search item: \n";
cin >> input;
//string can only be forty characters
if (input.length() > 40 || input == "\n")
{
cout << "That search query is too long. \n";
continue;
}
//change the search string to lowercase, like the envstr
transform(input.begin(), input.end(), input.begin(), tolower);
int j = 0;
int searchCount = 0;
vector<size_t> positions;
size_t pos = envstr.find(input, 0);
//search for that string
while (pos != string::npos)
{
positions.push_back(pos);
pos = envstr.find(input, pos + 1);
searchCount++;
}
cout << "\nThat phrase occurs a total of " << searchCount << " times.\n";
cout << "It occurs in the following lines: \n";
//output where that string occurs
for (vector<size_t>::iterator it = positions.begin(); it != positions.end(); ++it)
{
for (int i = *it; i < envstr.length() - 1 && checkChar(envstr[i]); i++)
{
cout << envstr[i];
}
cout << endl;
}
positions.clear();
} while (input != "END");
cin.get();
return 0;
}
First, your function checkChar() returns false when the parameter is a char, so if you want to print where that string occurs, it should be:
for (int i = *it; (i < envstr.length() - 1) && !checkChar(envstr[i]); i++)
{
cout << envstr[i];
}
Second, the code for counting words makes no sense and there is a potential out-of-bounds here: if (!checkChar(envstr[i])), I would suggest you to split the string using delimter '\', then do something.

How to remove punctuation characters from a char array?

My program prompts a user for a phrase to check if its a palindrome, then it's supposed to print out the phrase without capitalization or special characters like " ' , ? etc. My problem is erasing those characters. I've gotten my program to ignore them I'm asking how should I erase them? I made a comment where I think the statement should go. Example output should be: "Madam I'm Adam" to "madamimadam"
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
//Variables and arrays
int const index = 80;
char Phrase[index];
char NewPhrase[index];
int i, j, k, l;
bool test = true;
//Prompt user for the phrase/word
cout << "Please enter a sentence to be tested as a palindrome: ";
cin.getline(Phrase, 80);
//Make everything lowercase, delete spaces, and copy that to a new array 'NewPhrase'
for(k = 0, l = 0; k <= strlen(Phrase); k++)
{
if(Phrase[k] != ' ')
{
NewPhrase[l] = tolower(Phrase[k]);
l++;
}
}
//cout << "The Phrase without punctuation/extra characters: " << newPhrase[l];
int length = strlen(NewPhrase); //Get the length of the phrase
for(i = 0, j = length-1; i < j; i++, j--)
{
if(test) //Test to see if the phrase is a palindrome
{
if(NewPhrase[i] == NewPhrase[j])
{;}
else
{
test = false;
}
}
else
break;
}
if(test)
{
cout << endl << "Phrase/Word is a Palindrome." << endl << endl;
cout << "The Palindrome is: " << NewPhrase << endl << endl;
}
else
cout << endl << "Phrase/Word is not a Palindrome." << endl << endl;
system("Pause");
return 0;
}
Modify this line:
if(Phrase[k] != ' ')
To be:
if((phrase[k] != ' ') && (ispunct(phrase[k]) == false))
This means that we check for spaces and punctuation at the same time.
Also, consider rewriting this:
if(NewPhrase[i] == NewPhrase[j])
{;}
else
{
test = false;
}
As this:
if(NewPhrase[i] != NewPhrase[j])
test = false;
Here's suggestion:
Use an std::string
Use std::ispunct to determine whether a character in the string is a punctuation mark
Use the erase-remove idiom to remove punctuation
That is one line of code (plus one extra line for a convenience lambda):
std::string phrase = .....;
auto isPunct = [](char c) { return std::ispunct(static_cast<unsigned char>(c)); }
phrase.erase(std::remove_if(phrase.begin(), phrase.end(), isPunct),
phrase.end());
Next, for turning into lower case, from my answer to this recent question, another one-liner:
std::transform(phrase.begin(), phrase.end(), phrase.begin(),
[](char c)
{ return std::tolower(static_cast<unsigned char>(c));});