How to separate comma delimited values without using vectors in C++? - c++

I'm working on ATM machine code in C++. I know it is best to use a binary file and classes so that each account has exact same size in file even if it is empty. I'm looking for something very very simple.
I'm having problem with parsing comma delimited values in .txt file. Sometime I get values, sometime I get just the first value. I have spent days to figure out it's solution. I have searched the internet and stackoverflow almost every answer used vectors or other stuff.
I didn't use strcmp for array comparison instead created my own function to compare character to character.
From the look of the code, it seems I have done a lot just a little push is required. Kindly have a look at my code and let me know where am I wrong. I want to eliminate semantic error! And to have the following code amended for the achievement of expected results.
#include<iostream>
#include<conio.h>
#include<fstream>
#include<cstring>
#include<string>
#include<sstream>
#include<stdlib.h>
using namespace std;
void checkBalance();
void createAccount();
void deposit();
void withdraw();
void transfer();
void login();
void mainScreen();
void menuScreen();
// For file handling
void saveAccountToFile();
bool checkAccountExists(char*);
void loadAccount(char *);
void loadBeneficiary(char*);
bool compare(char *, char *);
const char * FILE_NAME = "accounts.txt";
char username[50];
char pin[5];
double balance = 0.0;
// Beneficiary Variables
char b_username[50];
char b_pin[5];
double b_balance = 0.0;
void menuScreen()
{
char opt;
do {
system("cls");
cout << "\n\n\t\t CMD - ATM";
cout << "\n\n\tMENU";
cout << "\n\n\t01. Check Balance";
cout << "\n\n\t02. Withdraw";
cout << "\n\n\t03. Deposite";
cout << "\n\n\t04. Transfer to Another account";
cout << "\n\n\t05. Logout";
opt = _getch();
switch (opt)
{
case '1':
checkBalance();
break;
case '2':
withdraw();
break;
case '3':
deposite();
break;
case '4':
transfer();
case '5':
cout << "\n\nThanks for using CMD ATM. Press any key to exit...";
_getch();
exit(1);
default:
cout << "\a\n\nIncorrect input. Press any key to try agian!";
_getch();
}
} while (opt != '5');
}
void mainScreen()
{
char opt;
do {
system("cls");
cout << "\n\n\t\t CMD - ATM";
cout << "\n\n\tMENU";
cout << "\n\n\t01. Create Account";
cout << "\n\n\t02. Login";
cout << "\n\n\t03. Exit";
opt = _getch();
switch (opt)
{
case '1':
createAccount();
break;
case '2':
login();
break;
case '3':
exit(1);
default:
cout << "\a\n\nIncorrect input. Press any key to try agian!";
_getch();
}
} while (opt != '3');
}
void saveAccountToFile() {
ofstream outFile;
outFile.open(FILE_NAME, ios::app);
if (outFile.is_open()) {
outFile << username << ',' <<
pin << ',' << balance << "\n";
}
outFile.close();
}
bool checkAccountExists(char * userName)
{
int i = 0;
char temp[50] = {'0'};
ifstream inFile;
string line;
inFile.open(FILE_NAME);
if (inFile.is_open()) {
while (getline(inFile, line)) {
stringstream ss(line);
string value;
while (getline(ss, value, ',')) {
if (i == 0) {
strcpy(temp,value.c_str());
if(compare(userName, temp)){
cout << "closing";
getchar();
inFile.close();
return true;
}
i = 1;
}
else if (i == 1) {
i = 2;
}
else if (i == 2) {
i = 0;
}
}
}
inFile.close();
}
return false;
}
void loadAccount(char * userName)
{
int i = 0;
ifstream inFile;
string line;
inFile.open(FILE_NAME);
if (inFile.is_open()) {
while (getline(inFile, line)) {
stringstream ss(line);
string value;
while (getline(ss, value, ',')) {
if (i == 0) {
strcpy(username, value.c_str());
i = 1;
}
else if (i == 1) {
strcpy(pin, value.c_str());
i = 2;
}
else if (i == 2) {
balance = atof(value.c_str());
i = 0;
}
if(compare(username,userName))
{
inFile.close();
break;
}
}
}
inFile.close();
}
}
void loadBeneficiary(char * userName)
{
int i = 0;
ifstream inFile;
string line;
inFile.open(FILE_NAME);
if (inFile.is_open()) {
while (getline(inFile, line)) {
stringstream ss(line);
string value;
while (getline(ss, value, ',')) {
if (i == 0) {
strcpy(b_username, value.c_str());
i = 1;
}
else if (i == 1) {
strcpy(b_pin, value.c_str());
i = 2;
}
else if (i == 2) {
b_balance = atof(value.c_str());
i = 0;
}
if(strcmp(b_username, userName)){
inFile.close();
break;
}
}
}
inFile.close();
}
}
void login()
{
char tempName[50];
char tempPin[5];
cout << "\n\nEnter user name: ";
cin.getline(tempName, sizeof(tempName));
if (checkAccountExists(tempName)) {
cout << "\n\nEnter user pin: ";
cin.getline(tempPin,sizeof(tempPin));
loadAccount(tempName);
if (compare(tempPin, pin)) {
cout << "\n\nLog in successfull!";
cout << "\n\nPress any key to continue...";
_getch();
menuScreen();
}else {
cout << "User name or pin incorrect!";
_getch();
}
}
else {
cout << "\n\nRecord not found. Press any key to continue...";
_getch();
}
}
void checkBalance()
{
system("cls");
cout << "\n\n\tUser name = " << username;
cout << "\n\n\tBalance = " << balance;
_getch();
}
bool compare(char * msg1, char * msg2){
int count = 0;
int size = sizeof(msg1);
if(sizeof(msg2) == size){
for(int i = 0; i < size; i++){
if(msg1[i]==msg2[i]){
count++;
}
}
if(count == size)
return true;
}
return false;
}
int main(int argc, char** argv) {
mainScreen();
getchar();
return 0;
}
TXT FILE
jhon,5155,99999.99
bot,4414,232323
theta,2111,34234

Regarding how to simplify the reading loop, how about something like
while (getline(inFile, line)) {
stringstream ss(line);
string value;
getline(ss, value, ',');
string name = value;
getline(ss, value, ',')
string pin = value;
getline(ss, value)
double balance = stod(value);
// Now use the name, pin and balance some way...
}
For when you only need the name you don't need to have the second and third getline call, just the first.
Also consider using structures to store the name, pin and balance, and then having a container (for example a vector) to stor the structures.
Also in the name of simplicity I suggest you read the file only once. Then loop over the vector to find the data you need.

Here is an alternative without using stringstream
while(getline(inFile,line,',')){
strcpy(username, line.c_str());
getline(inFile,line,',');
strcpy(pin, line.c_str());
getline(inFile,line,'\n');
balance = atof(line.c_str());
if(compare(username,userName)){
inFile.close();
break;
}else
continue;
}

Related

Why isn't my program doing anything at all?

I'm sorry for the vague title, but I don't know what else to say.
Here is my program:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
int
main (int argc, char **argv)
{
//string fin;
string ttl, dscp, ext;
string west = "w";
string east = "e";
string north = "n";
string south = "s";
int numRooms;
//string argv[1] = filename;
class Room
{
public:string title;
string description;
string exits;
int exitWest = -1;
int exitNorth = -1;
int exitEast = -1;
int exitSouth = -1;
int numExits;
};
ifstream fin;
fin.open (argv[1]);
//cin.ignore();
int t = 0;
while (fin)
{
string tilde;
string tester;
tester = "~";
cin >> tilde;
if (tilde == tester)
{
t = t + 1;
}
(numRooms = t / 3);
}
Room *roomArrayPtr = new Room[numRooms];
fin.clear ();
while (fin)
{
for (int l = 0; l < numRooms; l++)
{
getline (fin, ttl, '~');
roomArrayPtr[l].title = ttl;
getline (fin, dscp, '~');
roomArrayPtr[l].description = dscp;
getline (fin, ext, '~');
stringstream sin;
sin << ext;
string x;
int y;
while (sin >> x >> y)
{
if (x == west)
{
roomArrayPtr[l].exitWest = y;
}
if (x == south)
{
roomArrayPtr[l].exitSouth = y;
}
if (x == north)
{
roomArrayPtr[l].exitNorth = y;
}
if (x == east)
{
roomArrayPtr[l].exitEast = y;
}
}
sin.clear ();
int numext;
numext = (ext.size ()) / 3;
roomArrayPtr[l].numExits = numext;
}}
//(read in file again populate roomarrayptr w while loop and getline)
//roomArrayPtr[index].title = line;
//roomArrayPtr[index].description=line;
//close files, while loop that reads in user input from stdin, delete pointers w (delete[] roomArrayPtr;)
//if (exitsarray[i].size() > 2){
char command;
char newcommand;
cout << ">";
cin >> command;
int currentroom = 0;
int newroom;
bool keepgoing = true;
//string dir1;
while (keepgoing)
switch (command)
{
// stringstream ss;
case 'l':
cout << roomArrayPtr[currentroom].title << endl;
cout << roomArrayPtr[currentroom].description << endl;
cout << endl;
//if (roomArrayPtr[currentroom].numExits < 2) {
cout << "Exits: ";
if (roomArrayPtr[currentroom].exitWest > -1)
{
cout << "w";
}
if (roomArrayPtr[currentroom].exitNorth > -1)
{
cout << "n";
}
if (roomArrayPtr[currentroom].exitSouth > -1)
{
cout << "s";
}
if (roomArrayPtr[currentroom].exitEast > -1)
{
cout << "e";
}
/*else {
cout << "Exits: " ;
for (int k = 0; k < numExits; k++){
cout << exitdirection << " ";
}
}*/
//string newcommand;
cin >> newcommand;
//int newroom;
switch (newcommand)
{
case 'w':
if (roomArrayPtr[currentroom].exitWest == -1)
{
cout << "You can't go WEST!" << endl;
}
else
{
newroom = roomArrayPtr[currentroom].exitWest;
cout << "You moved WEST." << endl;
}
break;
case 'e':
if (roomArrayPtr[currentroom].exitEast == -1)
{
cout << "You can't go EAST!" << endl;
}
else
{
newroom = roomArrayPtr[currentroom].exitEast;
cout << "You moved EAST." << endl;
}
break;
case 'n':
if (roomArrayPtr[currentroom].exitNorth == -1)
{
cout << "You can't go NORTH!" << endl;
}
else
{
newroom = roomArrayPtr[currentroom].exitNorth;
cout << "You moved NORTH." << endl;
}
break;
case 's':
if (roomArrayPtr[currentroom].exitSouth == -1)
{
cout << "You can't go SOUTH!" << endl;
}
else
{
newroom = roomArrayPtr[currentroom].exitSouth;
cout << "You moved SOUTH." << endl;
}
break;
}
break;
case 'q':
keepgoing = false;
return 0;
break;
currentroom = newroom;
}
}
Whenever I run it, it compiles, but nothing happens. I tried putting in some random cout << "testing1" "testing2" scattered throughout, but none of those even showed up. I put it immediately after the { after int main and it still didn't show up. What's going on?
I tried putting in some random cout << "testing1" "testing2" scattered throughout, but none of those even showed up. I put it immediately after the { after int main and it still didn't show up.
you are reading the wrong file
int t = 0;
while (fin)
{
string tilde;
string tester;
tester = "~";
cin >> tilde; <<<<===== i assume you mean fin
if (tilde == tester)
{
t = t + 1;
}
(numRooms = t / 3);
}

Dealing with file io in c++

I have a program that takes input for names and outputs the last names in a string. The task I have now is to include FileIO in it. Specifically, "get user input for the filename, and then read the names from the file and form the last name string."
When I run the program, the console will show the name string from the text file. But only initially. As you keep entering names, that string disappears. Also, my user input for file name seems to be doing nothing, because I can enter anything and it still show the string of last names from the text file.
Here is what I have so far. Included all of it, just to make sure.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;
// function declerations
int Menu();
void getName(vector<string> &names, int &count);
void displayName(vector<string> &names, int count);
string getLastNames(vector<string> &names, int count);
int main()
{
vector<string> names;
int count = 0;
int choice = Menu();
ifstream File;
string line;
cout << "Enter file name: ";
getline(cin,line);
File.open("File.txt");
while(File.good()){
getline(File,line);
cout << line << endl;
}
File.close();
while (choice != 0)
{
// switch statement to call functions based on users input
switch (choice)
{
case 1: {
getName(names, count);
} break;
case 2: { displayName(names, count); } break;
case 3: {
cout << getLastNames(names, count) << endl;
} break;
case 0: {
return 0;
} break;
}
choice = Menu();
}
return 0;
}
// function definition for vector of strings
void getName(vector<string> &names, int &count)
{
string name;
// get input for name
cout << "Enter name: ";
getline(cin, name);
// find position of space in string
int pos = name.find(' ');
// reverse order of name
if(pos != -1) {
string first = name.substr(0, pos);
string last = name.substr(pos+1);
name = last + "," + first;
}
// add name to end of vector
names.push_back(name);
count++;
}
// give user option of what to do
int Menu() {
int choice;
cout << "1. Add a name" << endl;
cout << "2. Display names " << endl;
cout << "3. Show all Last Names" << endl;
cout << "0. Quit" << endl;
cout << "Enter a option: ";
cin >> choice;
// if outside of above choices, print 'choice not on list'
while (choice < 0 || choice > 3)
{
cout << "Choice not on list: ";
cin >> choice;
}
cin.ignore();
return choice;
}
// defining function that gets last names
string getLastNames(vector<string> &names, int count) {
stringstream ss;
for (int i = 0; i<count; i++)
{
int pos = names[i].find(',');
if (pos != -1) {
ss << "\"" << names[i].substr(0, pos) << "\", ";
} else {
ss << "\"" << names[i] << "\", ";
}
}
return ss.str();
}
// display the names
void displayName(vector<string> &names, int count)
{
if (count == 0)
{
cout << "No names to display" << endl;
return;
}
for (int i = 0; i<count; i++)
{
cout << names[i] << endl;
}
}

Difficulty in a menu oriented program for C++

I am having an issue when trying to use a getline command where a user can enter in a movie and then add to the collection of movies (stored in "movies.txt")
My code is compiling, but it starts out with the 3rd case automatically. When I press "q" to quit that case, it reverts to the menu, yet when I try and write out the file or print the collection, no movie titles have been saved. Where I should go from here? I feel like I'm on the cusp of understanding this.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
const int ARRAY_SIZE = 200;
string movieTitle [ARRAY_SIZE];
int loadData (string pathname);
int writeData (string pathname);
int getTitle (string movieTitle[]);
void showAll (int count);
int main()
{
loadData("movies.txt");
char userInput;
string movieTitle[ARRAY_SIZE];
int count = getTitle(movieTitle);
bool endOfProgram = false;
while (endOfProgram ==false)
{
cout << "1. Read in Collection" << endl;
cout << "2. Print Collection" << endl;
cout << "3. Add a Movie to the Collection" << endl;
cout << "4. Write out Collection" << endl;
cout << "5. Quit the Program" <<endl;
cin >> userInput;
switch(userInput)
{
case('1'):
{
loadData("movies.txt");
break;
}
case('2'):
{
showAll(loadData("movies.txt"));
break;
}
case('3'):
{
cout << getTitle(movieTitle);
break;
}
case('4'):
{
cout <<"Write out Collection" << endl;
writeData("movies.txt");
break;
case('5'):
{
endOfProgram=true;
cout << "Have a nice day" <<endl;
break;
}
}
}
}
}
int loadData (string pathname)
{
int count = 0;
ifstream inFile;
inFile.open(pathname.c_str());
if (!inFile)
return -1;
else
{
while(!inFile.eof())
{
getline(inFile, movieTitle[count]);
count++;
}
}
return count;
}
int writeData (string pathname)
{
ofstream outfile;
outfile.open("movies.txt");
if(!outfile.is_open())
{
cout << "Cannot open movies.txt" << endl;
return -1;
}
outfile.close();
return 0;
}
void showAll (int count)
{
cout << "\n";
for (int i=0; i< count; i++)
{
cout << movieTitle[i] << endl;
}
cout << "\n";
}
int getTitle (string movieTitle[])
{
string movie;
int count = 0;
while(true)
{
cout <<"Enter Movie Titles (Type 'q' to quit)" <<endl;
cin >> movie;
if (movie == "q")
{
break;
}
movieTitle [count] = movie;
count++;
}
return count;
}
I believe cin reads until eol is found, i.e. the user presses return.
So look for integer in the userInput variable, and pass that to your switch statement
int nr = atoi(userInput.c_str())
switch(nr){
case 1:
case 2: etc ...
In your codes it is not clear why it directly goes to case '3'. It should wait for a user input first. Seems like something already available in buffer. Just put one cout statement in case '3': and check what it print. If possible put break point there and run the application in debug mode and check the value. Hope this will help you.
case('3'):
{
cout<<"Value of userInput is: "<<userInput<<endl;
cout << getTitle(movieTitle);
break;
}
Alternately you can add the below line of code just before cin like below
std::cin.clear();
cin >> userInput;
I recommend inputting an integer instead of a character for your input.
You will need to change the case values too:
int selection = 0;
//...
cin >> selection;
switch (selection)
{
case 1:
//...
}
You won't have to worry about characters in the buffer. The stream will fail if an integer is not read.

Error C3861 in Visual with std::transform

I am a little curious why the program I wrote on Xcode with a mac runs fine, but when I try compiling on a windows system with visual studio,
I get following error:
c:\users\bryan\documents\visual studio
2010\projects\new\new\new.cpp(172): error C3861: 'transform':
identifier not found.
When I write transform anywhere in the program, in fact, it says the same message, as if transform is not a part of the std namespace. Here is my code if you would like to see for yourself:
#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, tempString;
char outChar;
int idx = 0, idxTwo = 0, newLines = 0;
stringstream outSentence;
do {
while (getline(* inFile, inData, '\n')) {
for (idx = 0; idx <= inData.length() - 1; idx++) {
if (inData[idx] >= 'a' && inData[idx] <= 'z') {
outChar = (((inData[idx] - 'a') + shiftNum) % 26) +
'a';
outSentence << outChar;
}
else if (inData[idx] >= 'A' && inData[idx] <= 'Z') {
outChar = (((inData[idx] - 'A') + shiftNum) % 26) +
'A';
outSentence << outChar;
}
else {
outChar = inData[idx];
outSentence << outChar;
}
}
outSentence << '\n';
newLines++;
}
}
while (!inFile->eof());
for (idxTwo = 0; idxTwo <= newLines + 1; idxTwo++) {
getline(outSentence, tempString);
outData.append(tempString);
outData += '\n';
}
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 is the transform under the capitalize funciton. It doesn't seem to know transform at all, I even tried to write std:: before it, but it said that there is no member called transform. Is there a problem with my compiler, or is transform even used anymore since i downloaded the new studio, or maybe it is just bad practice ?
As you would discover from reading documentation (e.g. http://en.cppreference.com/w/cpp/algorithm/transform), std::transform is defined in the standard header <algorithm>, which you aren't including.

stop getline from discarding newline character

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.
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
getline( the_stream, the_string );
the_string += '\n';