stop getline from discarding newline character

11,074

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;
    }
}

Online runnable example

Share:
11,074
Bryan S.
Author by

Bryan S.

Updated on June 05, 2022

Comments

  • Bryan S.
    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
    chris about 12 years
    Wouldn'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
    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
    chris about 12 years
    My mistake, I misunderstood the intent.
  • David L.
    David L. almost 10 years
    Adding the '\n' in this way will possibly not reflect the real input for the very last line.
  • Admin
    Admin about 5 years
    Doesn't this still not do quite the right thing if the last line in the file ends with a newline?
  • v1bri
    v1bri about 5 years
    Looks like I was testing on a standard library that doesn't follow the spec. Updated my answer. Thanks!