阻止 getline 丢弃换行符

Bry*_* S. 5 c++ newline getline

如果我有一个像这样的文本文件:

this is line one
This is line two
this is line three
Run Code Online (Sandbox Code Playgroud)

我将如何使用 getline 将每个读入字符串流,然后将流打印到新字符串中,同时保留换行符?我在一台使用 Xcode 4 的 Mac 上。这是我的代码: 我遇到了麻烦,因为它打印出来的文本只打印在一行上。

#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;
    }
Run Code Online (Sandbox Code Playgroud)

问题出在函数shiftCharacters 中。我不知道如何让它保留新行字符请帮助?代码是可以编译的。

v1b*_*bri 6

我知道这是一个老问题,但我认为我可以对上面@Benjamin Lindley的答案进行一些改进。getline()正如@David L.提到的,在每次调用 will 的末尾强制换行,“可能无法反映最后一行的真实输入”。

相反,您可以std::istream::peek()在读取该行后调用以查看是否还有更多字符。peek()不返回时添加换行符才是安全的EOF。下面的示例代码...

std::string s;
while (std::getline(std::cin, s)) {
    std::cout << s;
    if (std::cin.peek() != EOF) {
        std::cout << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:看起来上面的代码之所以有效,是因为我正在使用的标准库中存在错误。根据std::getline 规范...

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.
Run Code Online (Sandbox Code Playgroud)

所以在一个符合标准的库上,代码应该如下。

std::string s;
while (std::getline(std::cin, s)) {
    std::cout << s;
    if (std::cin.peek() != EOF) {
        std::cout << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

在线运行示例


Ben*_*ley -1

getline( the_stream, the_string );
the_string += '\n';
Run Code Online (Sandbox Code Playgroud)

  • 以这种方式添加 '\n' 可能不会反映最后一行的实际输入。 (18认同)