Ignore tabs and line breaks in user input using getline - c++

I'm writing a program that takes user input using getline(I must use getline) and spits it back out to the screen. It is also supposed to ask again if the input was blank. I'm having trouble with handling input that has multiple line breaks and tabs.
I've gotten it to almost work but it's looping through a few times and I can't figure out how to fix it/do it better. Here's the code:
string name;
while(true)
{
cout << "What is your name?" << endl;
getline(cin, name, '\n');
if (!name.empty())
{
break;
}
}
cout << "Hello " << name << "!" << endl;
return 0;
Here's the input:
\n
\n
John\n
Doe\n
The output I want is supposed to look like this:
What is your name?
Hello John Doe!
My output looks like this:
What is your name?
What is your name?
What is your name?
Hello John!

It's possible I don't understand your requirements, but if all you want to do is to collect a first and last name from the user on separate lines (while ignoring any tabs), you can do it like this.
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string first;
std::string last;
std::cout << "What is your name?\n";
while (first.empty())
{
std::getline(std::cin, first);
// remove all tabs from input
first.erase(std::remove(first.begin(), first.end(), '\t'), first.end());
}
while (last.empty())
{
std::getline(std::cin, last);
// remove all tabs from input
last.erase(std::remove(last.begin(), last.end(), '\t'), last.end());
}
std::string name = first + " " + last;
std::cout << "Hello, " << name << "!\n";
return 0;
}
Your user will be allowed to hit return/enter and tab until they are delirious. Until std::getline() gets some non-tabbed input it doesn't matter how many newlines or tabs happen. From your question this seems like what you want. You can find more information on the STL algorithm that I used to remove tabs with std::remove here.

Related

there's an extra newline before text ofstream c++

I'm trying to copy user input text into a file and its doing that its just also adding a newline before the text starts any ideas how to make it not do that?
getline(cin, userInput);
while (userInput != endWrite) {
storyTime << userInput << endl;
getline(cin, userInput);
}
storyTime.close();
return 0;
}
Your code is incomplete, so it's impossible to be absolutely certain what may be going on--at first glance, my immediate guess would be that what you're seeing may result from some code you didn't quote. For one obvious possibility you might be asking the user for the name of the file where you're going to write the output:
std::string outputName;
std::cout << "Enter output file name: ";
std::cin >> outputName;
std::ofstream storyTime(outputName);
//...
In this case, the std::cin >> outputName; reads the filename--but you had to press the enter key to get it to read that, and that press of the enter key will leave a new-line in the input, so when you start the loop afterwards, it'll be read as a newline preceding the text the user enters afterwards.
Aside
Other than that, I'd normally try to keep the code somewhat simpler:
while (std::getline(std::cin, userInput)) {
storytime << userInput << '\n';
}
As a really general rule of thumb, I'd advise that a formatted read from a text file (using either std::getline or some operator>>) be as the condition of an if, while, or whatever. Doing so habitually makes it much easier to write input loops that process files correctly.
Demo
Just for what it's worth, here's some working code that doesn't insert an extra new-line:
#include <iostream>
#include <string>
#include <fstream>
int main() {
std::string userInput;
std::string filename;
std::cout << "Please enter file name: ";
std::getline(std::cin, filename);
std::ofstream output{filename};
while (std::getline(std::cin, userInput)) {
output << userInput << '\n';
}
}

reading multiple lines of text until blank line

I'm working on a program that gets the user to enter text until the program reads a blank line. So far, I have this:
#include <iostream>
#include <cstring>
int main() {
string text;
cout << "Enter Your Text: " << endl;
getline(cin,text);
cout << "Text" << endl;
return 0;
}
But, this only outputs my text as a line and not individual lines, like I would like it to. And then there is the part when it reads a blank line that signifies the end of the user input.
I read that getline() gets all user input, but how do I display it as individual lines?
I read that I may have to use a tokenizer, but I am confused as to how they work, and how you actually write one. I was thinking of using a vector, or some kind of array, but vectors are the only ones I am sort of familiar with.
And I'm not quite sure how to get the program to stop at a blank line. I was thinking maybe a while loop, but what would go in the parenthesis, and how would that be combined with getting the user input?
What I'm basically trying to figure out is how to modify my code to output the user input as lines rather than one whole statement, and to stop getting user input when the user enters a blank line.
Try something like this:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> text;
std::string line;
std::cout << "Enter Your Text: " << std::endl;
while (std::getline(std::cin, line) && !line.empty())
text.push_back(line);
std::cout << "You entered: " << std::endl;
for (auto &s : text)
std::cout << s << std::endl;
return 0;
}

How to read all of the text on a line starting on that line?

I am trying to read someone's full name in C++, and obviously that would have spaces (like "John Doe"). The easiest way I can do this (since cin by default breaks at whitespace) is with getline(cin, str) where "str" is the variable.
However, when doing this, it starts reading text on the next line. Instead of this:
Please enter your full name > John Doe
You get
Please enter your full name >
John Doe
Here's the code that produces the result:
string fullName;
cout << "Please enter your full name >";
getline(cin, fullName);
Is there any way I can read the full line and still keep it on the same line?
Without a Minimal, Complete, Verifiable Example, it is difficult to diagnose the issue you're having. However, I am able to produce code that reads a line of input from the user without breaking the previous "Enter your name>" line:
#include <iostream>
#include <string>
int main()
{
std::string str;
std::cout << "Please enter your full name > ";
std::getline(std::cin, str);
std::cout << "Hello " << str << std::endl;
return 0;
}
If you've gotten into the habit of appending all std::cout lines with std::endl, you may have neglected to omit it that time.

Multiset: Problem with multiset adding more than one version of a word and cannot handle large amounts of text

Update and fixed: I have fixed the problem causing the error message- Huge thanks to user PaulMcKenzie for helping me understand what the error message was telling me!- When my program encountered a letter with a mark above it (diacritical marks I think they are called), it crashed. I have adjusted my code to account for these and now it doesn't crash at all! Another huge thanks to user ihavenoidea for helping me understand multisets! My program is now working the way it's supposed to!
Original post:
****I am VERY new to C++ so any and all help is appreciated!****
Ok, so I'm trying to use multiset to sort words so I can see how many times a word appears in a text. First, my program accepts a file, then it reads the words and takes out any punctuation, then it puts it into a multiset. After this, it is supposed to put the results into a text file the user names themselves.
My first issue is that the multiset seems to be creating more than one element for the same word (For example: in one of my tests I saw a(4) listed in the text document 3 times in a row instead of one time).
My Second issue is that when I try to read in large text documents (I'm using John Colliers story "Bottle Party" http://ciscohouston.com/docs/docs/greats/bottle_party.html to test it) my program completely crashes but doesn't crash when I test it with a smaller text document (small being with say about 5-10 lines of text). I'm using Visual Studios and (once again I'm new to Visual Studios also) I don't know what the error message is trying to tell me but it says:
After selecting retry:
As always, any and all help is greatly appreciated.
Code here:
#include <iostream>
#include <string> //for strings
#include <fstream> //for files
#include <set> //for use of multiset
using namespace std;
string cleanUpPunc(string);
//Global variables
multiset <string> words; //will change back to local variable later
int main() {
//Starting variables
string fileName1 = "", fileName2 = "", input = "", input2 = ""; //To hold the input file and the file we wish to print data to if desired
ifstream fileStream; //gets infor from file
//Program start
cout << "Welcome to Bags Program by Rachel Woods!" << endl;
cout << "Please enter the name of the file you wish to input data from: ";
getline(cin, fileName1);
//Trys to open file
try {
fileStream.open(fileName1);
if (!fileStream) {
cerr << "Unable to open file, please check file name and try again." << endl;
system("PAUSE");
exit(1);
}
while (fileStream >> input) {
input2 = cleanUpPunc(input); //sends the input word to check for punctation
words.insert(input2); //puts the 'cleaned up' word into the multiset for counting
}
fileStream.close();
//Sends it to a text document
cout << "Please name the file you would like to put the results into: ";
getline(cin, fileName2);
ofstream toFile; //writes info to a file
//Code to put info into text file
toFile.open(fileName2);
if (toFile.is_open()) {
multiset<string>::iterator pos;
for (pos = words.begin(); pos != words.end(); pos++) {
toFile << *pos << " " << words.count(*pos) << endl;
}
toFile.close();
cout << "Results written to file!" << endl;
}
else {
cout << "Could not create file, please try again." << endl;
}
}catch (exception e) {
cout << "Stop that. ";
cout << e.what();
}
cout << "Thanks for using this program!" << endl;
system("PAUSE");
return 0;
}
string cleanUpPunc(string maybe) {
//Takes out puncuation from string
//Variables
string takeOut = maybe;
//Method
for (int i = 0, len = maybe.size(); i < len; i++) {
if (ispunct(takeOut[i])) {
takeOut.erase(i--, 1);
len = takeOut.size();
}
}
return takeOut;
}

Having trouble with spaces while reading in sentences from separate text file

While reading in data from a separate text file, it doesn't keep the spaces and instead looks comes out looking like :
Todayyouareyouerthanyou,thatistruerthantrue
When it should have the spaces and say:
Today you are youer than you, that is truer than true
Here is my code that I have so far:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
std::ifstream inFile;
inFile.open("Rhymes.txt", std::ios::in);
if (inFile.is_open())
{
string word;
unsigned long wordCount = 0;
while (!inFile.eo())
{
cout << word;
inFile >> word;
if (word.length() > 0)
{
wordCount++;
}
}
cout << "The file had " << wordCount << " word(s) in it." << endl;
}
system("PAUSE");
return 0;
}
The "Rhymes.txt" has many phrases such as the one above and I'll just add 2 more so it's not a lot on here. Here they are:
Today you are You, that is truer than true. There is no one alive who is Youer than You.
The more that you read, the more things you will know. The more that you learn, the more places you'll go.
How did it get so late so soon? Its night before its afternoon.
Any help or advice would be greatly appreciated!! Also I am a beginner so if this turns out to be something really obvious, sorry!
How about inserting the spaces back to your output, so instead of this
cout << word;
You put this:
cout << word << " ";
Another option would be to read whole lines from your input file and then split them to words.
Issues that I see:
You are writing out word before the first read.
Reading the words using inFile >> word skips the white spaces. You need to add code to write the white spaces.
I am not sure what you were thinking with the following block of code. But, it is not necessary.
if (word.length() > 0)
{
wordCount++;
}
You can simplify your while loop to:
while (inFile >> word)
{
cout << word << " ";
wordCount++;
}
This will print an extra white space at the end. If that is objectionable, you can add more logic to fix that.
Let's fix the typo: inFile.eo() -> inFile.eof() and include stdlib.h for system(). Now you can put the spaces back by writing cout << word << " ";
But your program seems to be out by 1. Linux wc says 53 words but your program says 54. So I fixed your loop like this:
while (true)
{
inFile >> word;
if (inFile.eof())
break;
if (word.length() > 0)
{
wordCount++;
cout << word << " ";
}
}
Now it agrees with wc.