Error C3861 in Visual with std::transform - c++

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.

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

Wrong saving in data file

I am watching a youtube video from 2020 on how to make login system with c++. I have the exact same code as him but I have 1 error where when I save my first password everything works fine the password and user are saved as ID:1, but when I add another user the ID is set to -858993459.
Here's the code, it's only in main.cpp.
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <sstream>
using namespace std;
class loginManager {
public:
loginManager() {
accessGranted = false;
}
void login() {
cout << "Enter your UserName and Password.\n";
cout << "UserName: ";
cin >> userNameAttempt;
int usrID = retriveFile(userNameAttempt, "users.dat");
if (usrID != 0) {
cout << "Password: ";
cin >> passwordAttempt;
int pswID = retriveFile(passwordAttempt, "passwords.dat");
if (usrID == pswID) {
cout << "Successfull login!\n";
accessGranted = true;
login();
}
else {
cout << "Wrong password!\nTry Again!\n\n";
login();
}
}
else {
cout << "Wrong username!\nTry Again!\n\n";
login();
}
}
void addUser(const string username, const string password) {
if (retriveFile(username, "users.dat") != 0) {
cout << "That username is already in use!" << endl;
return;
}
int id = 1 + getLastID();
saveFile(username, "users.dat", id);
saveFile(password, "passwords.dat", id);
}
int getLastID() {
fstream file;
file.open("users.dat", ios::in);
file.seekg(0, ios::end);
if (file.tellg() == 0) {
return 0;
}
string s;
for (int i = -1; s.find("#") == string::npos; i--) {
file.seekg(i, ios::end);
file >> s;
}
file.close();
s.erase(0, 5);
int id;
istringstream(s) >> id;
return id;
}
int retriveFile(string attempt, const char* pathFile) {
string line;
fstream file;
string currentChar;
long long eChar;
file.open(pathFile, ios::in);
while(1) {
file >> currentChar;
if (currentChar.find("#ID:") != string::npos) {
if (attempt == line) {
file.close();
currentChar.erase(0,4);
int id;
istringstream(currentChar) >> id;
return id;
}
else {
line.erase(line.begin(), line.end());
}
}
else {
istringstream(currentChar) >> eChar;
line += (char)decrypt(eChar);
currentChar = "";
}
if (file.peek() == EOF) {
file.close();
return 0;
}
}
}
void saveFile(string p_line, const char* pathFile, const int& id) {
fstream file;
file.open(pathFile, ios::app);
file.seekg(0, ios::end);
if (file.tellg() != 0) {
file << "\n";
}
file.seekg(0, ios::beg);
for (int i = 0; i < p_line.length(); i++) {
file << encrypt(p_line[i]);
file << "\n";
}
file << "#ID:" << id;
file.close();
}
long long encrypt(int p_letter) {
return powf(p_letter, 7) * 3 - 70;
}
long long decrypt(long long p_letter) {
return powf((p_letter + 70) / 3, 1/7.f);
}
private:
string userNameAttempt;
string passwordAttempt;
bool accessGranted;
};
int main() {
loginManager app;
app.addUser("Something", "Somethingelse");
app.login();
return 0;
}

How to separate comma delimited values without using vectors in 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;
}

C++: Getting random negative values when converting char to int

Why do I get negative values when I'm trying to convert chars from the string read from file to int?
fin.getline(text, 512);
fin.close();
someInt = (int)text[0]; // It happens to be the random value and always negative.
WHOLE CODE:
The problem itself is in the Decrypt function.
When I read the string from file, and convert chars from that string to int, i get negative values, always random, even if characters are the same.
// WUEncryptor.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void Encrypt(string filePath, string password = "");
void Decrypt(string filePath, string password = "");
int main(int argc, char** argv)
{
int mode = 0;
string filePath;
if (argc > 2) {
mode = atoi(argv[1]);
filePath = argv[2];
/** Checking which mode to use */
switch (mode) {
case 0:
if (argc > 3)
Encrypt(filePath, argv[3]);
else
Encrypt(filePath);
break;
case 1:
if (argc > 3)
Decrypt(filePath, argv[2]);
else
Decrypt(filePath);
break;
default:
return 0;
}
}
else {
/** If something was entered wrong by user, print the error message and quit */
cout << "Invalid launch..\nYou should use arguments\nFor example: \"WUEncryptor 0 EncryptedFile\n";
}
return 0;
}
/** Encrypting function */
void Encrypt(string filePath, string password) {
string text;
string pass = password;
/** Quit if pass word isn't determined */
if (pass == "") {
cout << "Use \"WUEncryptor 0/1 \"filepath\" password\n";
return;
}
cout << "Enter the message which is going to be encrypted\n";
char tempstr[512];
gets_s(tempstr);
text = tempstr;
/** Loop that replaces characters in the text */
for (int i = 0, m = 0, temp = 0; i < text.length(); i++) {
temp = (int)text[i] + (int)pass[m];
cout << temp;
if (temp > 255)
temp -= 256;
cout << temp;
text[i] = (char)temp;
/** Looping the pass code */
if (m >= pass.length() - 1)
m = 0;
else
m++;
cout << "Encrypting " << i << " of " << text.length() << "...\n";
}
cout << "Successfully encrypted\nTEXT: " << text << '\n';
ofstream fout;
try {
filePath += ".encrypted";
cout << "Creating the file...\n";
fout.open(filePath, ios_base::trunc);
cout << "Writing to file...\n";
fout << text;
fout.close();
cout << "We're all set!\n";
system("pause");
}
catch (exception) {
cout << "Something went wrong";
}
}
/** Decrypting function */
void Decrypt(string filePath, string password) {
string text, pass;
pass = password;
ifstream fin;
/** Quit if pass word isn't determined */
if (pass == "") {
cout << "Use \"WUEncryptor 0/1 \"filepath\" password\n";
return;
}
string openPath = filePath + ".encrypted";
char tempstr[512];
try {
fin.open(openPath);
fin.getline(&tempstr[0], 512);
fin.close();
text = tempstr;
//cout << (int)text[1];
for (int i = 0, m = 0, temp = 0; i < text.length(); i++) {
temp = (int)text[i] - (int)pass[m];
cout << temp;
if (temp < 0)
temp += 256;
cout << temp;
text[i] = (char)temp;
/** Looping the pass code */
if (m >= pass.length() - 1)
m = 0;
else
m++;
cout << "Decrypting " << i << " of " << text.length() << "...\n";
}
cout << "Successfully decrypted\nTEXT: " << text << '\n';
}
catch (exception) {}
ofstream fout;
try {
string savePath = filePath + ".txt";
cout << "Creating the file...\n";
fout.open(savePath, ios_base::trunc);
cout << "Writing to file...\n";
fout << text;
fout.close();
cout << "We're all set!\n";
system("pause");
}
catch (exception) {
cout << "Something went wrong";
}
}
Someone, clear my mind :D
You're probably using char* as datatype for text.
Note that char is signed, so if you (think you) have a value of e.g. 200 there, it's really -72, and so if you cast that to int, you get -72 :)

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