stop getline from discarding newline character
Solution 1
getline( the_stream, the_string );
the_string += '\n';
Solution 2
I know this is an old question but I think I can improve a little on @Benjamin Lindley's answer above. Forcing a newline at the end of every call to getline()
will, as @David L. mentions, "possibly not reflect the real input for the very last line."
Instead, you can call std::istream::peek()
after reading the line to see if there are more characters. It's safe to add a newline only if peek()
doesn't return EOF
. Sample code below...
std::string s;
while (std::getline(std::cin, s)) {
std::cout << s;
if (std::cin.peek() != EOF) {
std::cout << std::endl;
}
}
Update: It looks like the above code worked because of a bug in the standard library that I was using. According to the std::getline spec...
1) ...
2) ...
b) the next available input character is delim, as tested by
Traits::eq(c, delim), in which case the delimiter character
is extracted from input, but is not appended to str.
So on a conformant standard library, the code should be as follows.
std::string s;
while (std::getline(std::cin, s)) {
std::cout << s;
if (std::cin.good()) {
std::cout << std::endl;
}
}
Bryan S.
Updated on June 05, 2022Comments
-
Bryan S. almost 2 years
if I have a text file like this :
this is line one This is line two this is line three
How would I use getline to read each into a stringstream, then print the stream into a new string while preserving the newline character? I am on a mac using Xcode 4. Here is my code: I am having trouble because the text it prints out only prints on one line.
#include <iostream> #include <fstream> #include <string> #include <vector> #include <sstream> #include <cctype> using namespace std; string getInput (); ifstream * openInFile (); int getShiftValue (); void cypherMenu (); void menu (); string shiftCharacters (int shiftNum, ifstream * inFile); string getOutput (); ofstream * openOutFile (); void printSentence (string outData, ofstream * outFile); void notOption (string optionString); string capitalize (string choice); string option (); int main() { ifstream * inFile; ofstream * outFile; string inFileName, outFileName, outData, optionString, capOptionString; int shiftNum = 0; bool isOption = false; while (capOptionString.compare("2") != 0 || capOptionString.compare("QUIT") != 0) { do { menu(); optionString = option(); capOptionString = capitalize(optionString); if (capOptionString.compare("1") == 0 || capOptionString.compare("CAESAR") == 0) { isOption = true; } else if (capOptionString.compare("2") == 0 || capOptionString.compare("QUIT") == 0) { isOption = false; return 0; } else { notOption(optionString); } } while (!isOption); cypherMenu(); inFile = openInFile(); shiftNum = getShiftValue(); outData = shiftCharacters(shiftNum, inFile); inFile->clear(); inFile->close(); outFile = openOutFile(); printSentence(outData, outFile); outFile->clear(); outFile->close(); } return 0; } // Input Functions string getInput () { cout << "Enter an input file name: "; string inFileName; getline(cin, inFileName); return inFileName; } string getOutput () { string outFileName; cout << "Enter an output file name: "; getline(cin, outFileName); cout << endl; return outFileName; } ifstream * openInFile () { ifstream * inFile; bool isGood = false; string inFileName; inFile = new ifstream; do { inFileName = getInput(); inFile->open(inFileName.c_str()); if (inFile->fail()) { cout << "Couldn't open file" << endl; } else { isGood = true; } } while (!isGood); return inFile; } ofstream * openOutFile () { ifstream testStream; ofstream * outFile; bool isUnique = false; string fileName; do { fileName = getOutput(); testStream.clear(); testStream.open(fileName.c_str(), ios_base::in); if (testStream.good()) { cout << "The file already exists, please choose another" << endl; testStream.clear(); testStream.close(); } else { isUnique = true; testStream.clear(); testStream.close(); } } while (!isUnique); outFile = new ofstream; outFile->open(fileName.c_str()); return outFile; } int getShiftValue () { int shiftNum; string trash; cout << "Please enter shift value: "; cin >> shiftNum; getline(cin, trash); return shiftNum; } string option () { string optionString; getline(cin, optionString); cout << endl; return optionString; } // Data manipulation functions **string shiftCharacters (int shiftNum, ifstream * inFile){ string inData, outData, trash; char outChar; int idx = 0, length = 0; stringstream outSentence; do { while (getline(* inFile, inData, '\n')) { getline(* inFile, trash); for (idx = 0; idx <= inData.length() - 1; idx++) { if (inData[idx] >= 'a' && inData[idx] <= 'z') { outChar = (((inData[idx] - 'a') + shiftNum) % 26) + 'a'; outSentence << outChar; length += 1; } else if (inData[idx] >= 'A' && inData[idx] <= 'Z') { outChar = (((inData[idx] - 'A') + shiftNum) % 26) + 'A'; outSentence << outChar; length += 1; } else { outChar = inData[idx]; outSentence << outChar; length += 1; } } outSentence << trash; } } while (!(inFile->eof())); outData.resize(length); while (!(outSentence).eof()) { // outSentence >> noskipws >> outData; getline(outSentence, outData); } return outData; }** string capitalize (string choice) { string outString; outString.resize(choice.length()); transform(choice.begin(), choice.end(), outString.begin(), ::toupper); return outString; } // Output funcitons void cypherMenu () { cout << "C A E S A R C Y P H E R P R O G R A M" << endl << "========================================" << endl; return; } void printSentence (string outData, ofstream * outFile) { int idx = 0; char outChar; stringstream outString; outString << outData; for (idx = 0; idx <= outData.length() - 1; idx++) { outChar = outString.get(); outFile->put(outChar); } } void menu () { cout << "Available Options: " << endl << "1. CAESAR - encrypt a file using Caesar Cypher" << endl << "2. QUIT - exit the program" << endl << endl << "Enter a keyword or option index: "; return; } void notOption (string optionString) { cout << optionString << " is an unrecognized option, try again" << endl << endl; return; }
The Problem lies within the function shiftCharacters. I am not sure how to get it to preserve the new line character please help?? The code is compilable.
-
chris about 12 yearsWouldn't
getline (the_stream, the_string, CHAR_EOF);
work better (where CHAR_EOF is the end of file character) if you know what the expected EOF is? -
Benjamin Lindley about 12 years@chris: Work better for what? That would read until the end of the file, and that's not what the OP asked for.
-
chris about 12 yearsMy mistake, I misunderstood the intent.
-
David L. almost 10 yearsAdding the '\n' in this way will possibly not reflect the real input for the very last line.
-
Admin about 5 yearsDoesn't this still not do quite the right thing if the last line in the file ends with a newline?
-
v1bri about 5 yearsLooks like I was testing on a standard library that doesn't follow the spec. Updated my answer. Thanks!