does not stop at, clearing cin creates infinite loop - c++

I am a beginner at C++ and I have read various problems and solutions, but I still cannot get my code to work! The problem is that if i do not include the commented-out cin.clear() or cin.synch() my code does not stop at the beginning getline. When i do add them, it loops infinitely. Is there something that I am not including? Here is my source code:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string inputFileName, outputFileName, inData, outData, inWord, outWord;
ifstream inFile, testStream;
ofstream outFile;
bool outPutOpened = false;
char outChar;
int shiftNum = 0, idx = 0;
do {
inWord.clear();
outWord.clear();
//cin.clear();
//cin.sync();
cout << "Available options: " << endl;
cout << "1. ENCRYPT - Encrypt a file using Caesar Cypher" << endl // menu
<< "2. Quit - Exit the program" << endl << endl;
cout << " Enter keyword or option index: ";
getline(cin, inWord); // get option
outWord.resize(inWord.length());
transform(inWord.begin(), inWord.end(), outWord.begin(), ::toupper); //capitalize
if (outWord.compare("ENCRYPT") == 0 || outWord.compare("1") == 0) {
cout << "CAESAR CYPHER PROGRAM" << endl
<< "======================" << endl << endl;
do {
cout << "Provide the input file name: ";
getline(cin, inputFileName);
inFile.open(inputFileName.c_str());
if (inFile.fail()) {
cout << "Cannot open file, please try again!" << endl;
inFile.clear();
}
}
while (!inFile.is_open());
getline(inFile, inData);
do {
cout << "Provide the output file name: ";
cin >> outputFileName;
testStream.clear();
testStream.open(outputFileName.c_str());
if(testStream.good()) {
cout << "That file already exists, choose another" << endl;
testStream.clear();
testStream.close();
}
else {
testStream.clear();
testStream.close();
outFile.open(outputFileName.c_str());
if (outFile.good()) {
outPutOpened = true;
}
}
}
while (!outPutOpened);
cout << "Enter the shift number: ";
cin >> shiftNum;
for (idx = 0; idx <= inData.length() - 1; idx++) {
if (inData[idx] >= 'a' && inData[idx] <= 'z') {
outChar = (((inData[idx] - 'a') + shiftNum) % 26) + 'a';
outFile.put(outChar);
}
else if (inData[idx] >= 'A' && inData[idx] <= 'Z'){
outChar = (((inData[idx] - 'A') + shiftNum) % 26) + 'A';
outFile.put(outChar);
}
else {
outFile.put(inData[idx]);
}
}
}
else if (outWord.compare("2") == 0 || outWord.compare("QUIT") == 0) {
break;
}
else {
cout << inWord << " is an unrecognized option, please try again"
<< endl;
}
}
while (outWord.compare("2") || outWord.compare("QUIT"));
return 0;
}

The problem that in all your places where you use something like:
cin >> something;
the new line character remains in cin, so that what you will be reading next. Just every time you are finished reading from a line with this, write
string trash;
getline(cin, trash);
like:
cin >> something;
string trash;
getline(cin, trash);
and then the new line character won't remain in cin and you will start with a fresh line.

Related

why does the getline() function does not work unless I call it twice in the function charmodifier [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Why must type getline(cin, string) twice?
(5 answers)
Closed 9 months ago.
what's wrong
if I use the get line function only once in the character modifier function the compiler will ignore it
unless I call the function twice
why cant I use it only once?
I tried using other ways, it worked but I wanna understand this one
I'm now just writing random things so the add more details error messages go away
#include <iostream>
#include<string>
using namespace std;
class egybest
{
string link,m;
char sys, type, restart;
int s = 1, e = 1, date;
public:
string charmodifier()
{
//here
getline(cin, m);
getline(cin, m);
for (int x = 0; x <= m.size(); x++)
{
if (m[x] == ' ')
m[x] = '-';
}
return m;
}
~egybest()
{
system("cls");
cout << "do you want to restart the program? y:n;" << endl;
cin >> restart;
system("cls");
if (restart == 'y' || restart == 'Y')
egybest();
else if (restart == 'n' || restart == 'N')
{
system("exit");
}
}
egybest()
{
cout << "do you want to watch a movie or a series? 1:2;" << endl;
cin >> type;
system("cls");
if (type == '1')
linkmovie();
else if (type == '2')
series();
else
cout << "wrong input!" << endl;
}
void linkmovie()
{
cout << "enter the name of the movie:" << endl;
charmodifier();
cout << "enter the release date: " << endl;
cin >> date;
link = "start https://cape.egybest.cool/movie/" + m + "-" + to_string(date);
cout << endl;
system(link.c_str());
}
void series()
{
cout << "do you want it to open links for a particular season, particular episode or all seasons? s:e:a;"
<< endl;
cin >> sys;
system("cls");
if (sys == 'S' || sys == 's')
linkseason();
else if (sys == 'A' || sys == 'a')
linkall();
else if (sys == 'E' || sys == 'e')
linkepisode();
else
cout << "wrong input!" << endl;
}
void linkall()
{
cout << "season No." << endl;
cin >> s;
cout << "episode No." << endl;
cin >> e;
cout << "enter the name of the show:" << endl;
charmodifier();
for (int j = 1; j <= s; j++)
{
for (int i = 1; i <= e; i++)
{
link = "start https://cape.egybest.cool/episode/" + m + "-season-" + to_string(j) + "-ep-" + to_string(i);
system(link.c_str());
}
}
cout << endl;
}
void linkepisode()
{
cout << "season No." << endl;
cin >> s;
cout << "episode No." << endl;
cin >> e;
cout << "enter the name of the show:" << endl;
charmodifier();
link = "start https://cape.egybest.cool/episode/" + m + "-season-" + to_string(s) + "-ep-" + to_string(e);
cout << endl;
system(link.c_str());
}
void linkseason()
{
cout << "season No." << endl;
cin >> s;
cout << "episodes No." << endl;
cin >> e;
cout << "enter the name of the show:" << endl;
charmodifier();
for (int i = 1; i <= e; i++)
{
link = "start https://cape.egybest.cool/episode/" + m + "-season-" + to_string(s) + "-ep-" + to_string(i);
cout << endl;
system(link.c_str());
}
}
};
int main()
{
egybest egy;
return 0;
}```
The problem is that after entering an integer or a character as for example
cout << "episode No." << endl;
cin >> e;
cout << "enter the name of the show:" << endl;
charmodifier();
//...
the input buffer contains the new line character '\n' that corresponds to the pressed Enter key.
So the following call of getline reads an empty string until the new line character is encountered.
In such a case before calling getline you need to remove the new line character from the input buffer like for example
#include <limits>
//...
cout << "episode No." << endl;
cin >> e;
cout << "enter the name of the show:" << endl;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
charmodifier();
//...

How do I get the for loops working for searching in a txt file?

I have been working on this code for a while now but I can't seem to get this for loop working:
if (name != "n")
{
for (unsigned int i = 1; getline(mov, line); i++)
{
if (line.find(name, 0) != string::npos)
{
cout << "\n Fount it!\n In line no# " << i << endl;
}
}
}
It's a code to search for text in a file and I tried running this syntax in other projects too but it doesn't work at all.
Here's some more of the code:
bool search() // The search option to search in the txt file
{
string choi;
string line;
bool mainFlag = false;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
reSrch:
string name = "n";
string star = "n";
int year = 0;
string blunt = "n";
string blunt2 = "n";
int blunt3 = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
cout << "\n Please enter the name of the Movie (or n to skip name) : ";
cin >> blunt;
if (blunt != "n")
name = blunt;
cout << "\n Please enter a name of any one star of the Movie (or n to skip name of star) : ";
cin >> blunt2;
if (blunt2 != "n")
star = blunt;
cout << "\n Please enter the year of production of the Movie (or 0 to skip year) : ";
cin >> blunt3;
if (blunt3 != 0)
year = blunt3;
////////////////////////////////////////////////////////////////////////////////////////////
if (blunt == "n" && blunt2 == "n" && blunt3 == 0)
{
cout << "\n You have not entered any of the information to make a search. Would you\n like to try again? If not then you will be sent back to the main menu."
"\n\n Please enter yes or no : ";
cin >> choi;
if (choi == "YES" || choi == "Yes" || choi == "yes")
{
Sleep(1500);
system("CLS");
goto reSrch;
}
else
{
Sleep(1500);
system("CLS");
mainFlag = true;
}
}
///////////////////////////////////////////////////////////////////
else
{
mov.open("movie.txt", ios::app);
if (name != "n")
{
for (unsigned int i = 1; getline(mov, line); i++)
{
if (line.find(name, 0) != string::npos)
{
cout << "\n Fount it!\n In line no# " << i << endl;
}
}
}
else if (star != "n")
{
for (unsigned int i = 1; getline(mov, line); i++)
{
if (line.find(star, 0) != string::npos)
{
cout << "\n Fount it!\n In line no# " << i << endl;
}
}
}
else if (year != 0)
{
string year_string = to_string(year);
for (unsigned int i = 1; getline(mov, line); i++)
{
if (line.find(year, 0) != string::npos)
{
cout << "\n Fount it!\n In line no# " << i << endl;
}
}
}
mov.close();
}
return mainFlag;
}
This part is in a bool function that return the user's choice if he wanted to go through again the whole entry are or anything. There is a problem somewhere within this function and not outside but If in comments then of course I surely will provide. And this is my second time making a project on file handeling so I don't know much. I did some editing before moving the code to another project and before that I remember it working just fine.
EDIT: The code stops when it reaches the for loop. It closes the compiling. no error. ok so here is the full code anyways:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <Windows.h>
using namespace std;
fstream mov, mov2;
void demo();
int menu();
bool search();
void addMR();
int main()
{
reMain:
switch (menu())
{
case 1:
if (search() == true){ goto reMain; }
else{ break; }
case 2:
addMR(); break;
case 3:
delMR(); break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
demo(); goto reMain;
default:
cout << "\n Please enter a valid option!";
Sleep(3000);
system("CLS");
goto reMain;
}
string line;
cout << endl;
return 0;
}
//////////////////// - FIN
int menu() // The main menu prompt options to the user
{
int choice;
cout << "\n Please choose any of the options given below :"
"\n ======================================================================================================================\n"
"\n 1. search for a movie"
"\n\n 2. add a new movie record"
"\n\n 3. delete a movie record"
"\n\n 4. edit existing movie record"
"\n\n 5. change availability status"
"\n\n 6. check availability"
"\n\n 7. Add demo information for program testing\n\n"
"\n\n Your choice : ";
cin >> choice;
Sleep(2000);
system("CLS");
return choice;
}
//////////////////// - FIN
void demo() // A function to add demo values to test program functionality
{
string line2 = "name alien\n"
"year 1979\n"
"stars yaphet-kotto\n"
"stars sigourney-weaver\n"
"totalNoOfCopies 2\n"
"noOfCopiesRentedOut 1\n"
"\nname repo-man\n"
"Year 2020\n"
"stars harry-dean-stanton\n"
"totalNoOfCopies 4\n"
"noOfCopiesRentedOut 2\n"
"\nname midnight-run\n"
"year 2011\n"
"stars yaphet-kotto\n"
"totalNoOfCopies 1\n"
"noOfCopiesRentedOut 1\n\n";
mov.open("movie.txt", ios::app);
mov << line2;
mov.close();
system("CLS");
cout << "\n Demo information has been added to the file!";
Sleep(4000);
system("CLS");
}
bool search() // The search option to search in the txt file
{
string choi;
string line;
bool mainFlag = false;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
reSrch:
string name = "n";
string star = "n";
int year = 0;
int file_line_number = 0;
string blunt = "n";
string blunt2 = "n";
int blunt3 = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
cout << "\n Please enter the name of the Movie (or n to skip name) : ";
cin >> blunt;
if (blunt != "n")
name = blunt;
cout << "\n Please enter a name of any one star of the Movie (or n to skip name of star) : ";
cin >> blunt2;
if (blunt2 != "n")
name = blunt;
cout << "\n Please enter the year of production of the Movie (or 0 to skip year) : ";
cin >> blunt3;
if (blunt3 != 0)
year = blunt3;
////////////////////////////////////////////////////////////////////////////////////////////
if (blunt == "n" && blunt2 == "n" && blunt3 == 0)
{
cout << "\n You have not entered any of the information to make a search. Would you\n like to try again? If not then you will be sent back to the main menu."
"\n\n Please enter yes or no : ";
cin >> choi;
if (choi == "YES" || choi == "Yes" || choi == "yes")
{
Sleep(1500);
system("CLS");
goto reSrch;
}
else
{
Sleep(1500);
system("CLS");
mainFlag = true;
}
}
///////////////////////////////////////////////////////////////////
else
{
mov.open("movie.txt", ios::app);
if (name != "n")
{
while (std::getline(mov, line))
{
++file_line_number;
if (line.find(name, 0) != string::npos)
{
std::cout << "\n"
<< "Found it!\n"
<< "In line no# " << file_line_number << std::endl;
break; // ??? So, what does this do?????
}
}
}
else if (star != "n")
{
for (unsigned int i = 1; getline(mov, line); i++)
{
if (line.find(star, 0) != string::npos)
{
cout << "\n Fount it!\n In line no# " << i << endl;
}
}
}
else if (year != 0)
{
string year_string = to_string(year);
for (unsigned int i = 1; getline(mov, line); i++)
{
if (line.find(year, 0) != string::npos)
{
cout << "\n Fount it!\n In line no# " << i << endl;
}
}
}
mov.close();
}
return mainFlag;
}
///////////////////// - FIN
void addMR() // The option to add a movie in the record
{
string name;
cout << "\n Enter the name of the movie : "; cin >> name;
int year;
cout << "\n Enter the production year of the movie : "; cin >> year;
string star;
cout << "\n Enter names of the stars (e.g. starA-starB) : "; cin >> star;
int copiesAvl;
cout << "\n Enter total number of copies available : "; cin >> copiesAvl;
int copiesRnt;
cout << "\n Enter number of copies rented out : "; cin >> copiesRnt;
string line3;
mov.open("movie.txt", ios::app);
mov << "\n\nname " << name
<< "\nyear " << year
<< "\nstars " << star
<< "\ntotalNoOfCopies " << copiesAvl
<< "\nnoOfCopiesRentedOut " << copiesRnt;
mov.close();
}
You may want to switch to a while loop:
int file_line_number = 0;
while (std::getline(mov, line))
{
++file_line_number;
if (line.find(name, 0) != string::npos)
{
std::cout << "\n"
<< "Found it!\n"
<< "In line no# " << file_line_number << std::endl;
break; // ??? So, what does this do?????
}
}
The above code fragment reads lines until EOF.
If the line is found, the loop ends with the break statement.
You aren't opening your file correctly
mov.open("movie.txt", ios::app);
This opens the file for writing not reading.
Try this to open the file for input
mov.open("movie.txt", ios::in);
Some advice to avoid this problem in the future. Declare file variables in the functions that need them, not globally. This also has the advantage that you don't have to remember to close the file because it will be closed automatically when the function exits. Use ifstream for functions which need to read data, and ofstream for functions which need to write data, only use fstream for the rare occaisions where you want to read and write at the same time.

How to add new row to a vector using struct in C++

Hello I am having issues with a final project. The objective is to have the user create a form that allows a user to view data, edit data, add data, and save their password data in an encoded format. The program starts with an input file made by the user. The delimiter is ';', and the first char is a "code", then the, site, username, password, and notes follow.
I am very new to vectors, and I am not allowed to use a 2d array, or map.
Thank you for your time.
#include <iomanip>
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
const int MAX_SIZE = 30;
const int BUFFER_SIZE = 200;
struct dataRow {
string site, user, pass, notes;
string code;
};
string inFileName; //name of inputfile
string outFileName;
ifstream pathStream;
ofstream outFile;
char inputChar;
int extPosition(1), count = 0,lineNum;
void displayVector(vector<dataRow> inputData);
void viewLineData(vector<dataRow> inputData, int lineNum);
void addNewRow(vector<dataRow> inputData,int& lastRowNum, string site, string user, string pass, string notes);
void editLineData(vector<dataRow> inputData, int& lineNum, string site, string user, string pass, string notes);
void warning();
void cleanBuffer();
bool displayMenu();
int exit();
dataRow descripLine;
int main()
{
vector<dataRow> inputData;
string rowDescripin,userin,passin,notesin,sitein;
string codein,errorMsg;
int lastRow;
//add a .txt extension to the file if the user didn't provide an extension
if (inFileName.size() > 4)
// If there's a valid extension, it will be in the last 4 positions of the string; Adjust by 1 for 0 offset
extPosition = inFileName.size() - 4;
int ext = inFileName.find_last_of(".txt");
if (!(inFileName.find_last_of(".") == extPosition))
{
inFileName += ".txt";
}
cout << "\nPlease enter the filename of input file: ";
cin >> inFileName;
pathStream.open(inFileName.c_str());
if (pathStream.fail())
{
cerr << inFileName << " failed to open.\n";
system("pause");
exit(1);
}
else
{
cout << "startup success" << endl;
}
getline(pathStream, codein, ';');
descripLine.code = codein;
while (!pathStream.eof())
{
getline(pathStream, sitein, ';');
descripLine.site = sitein;
getline(pathStream, userin, ';');
descripLine.user = userin;
getline(pathStream, passin, ';');
descripLine.pass = passin;
getline(pathStream, notesin, ';');
descripLine.notes = notesin;
inputData.push_back(descripLine);
}
displayVector(inputData);
displayMenu();
while (cin){
cin >> inputChar;
inputChar = toupper(inputChar);
//Adjust calculations based on inputCHar
if (inputChar == 'D') // Display line descriptions
{
displayVector(inputData);
}
else if (inputChar == 'V') //View line data
{
cout << "Enter line number you wish to view: ";
cin >> lineNum;
viewLineData(inputData, lineNum);
}
/* else if (inputChar == 'E') //Edit line Data
{
cout << "Enter line number you wish to edit: ";
cin >> lineNum;
editLineData(inputData, lineNum);
}*/
else if (inputChar == 'A') //Add line data
{
warning();
lastRow = inputData.size();
cout << "Enter a line description: ";
cin >> rowDescripin;
cout << "Enter a line username: ";
cin >> userin;
cout << "Enter a line password: ";
cin>>passin;
cout << "Enter notes: ";
cin>>notesin;
addNewRow(inputData, lastRow, rowDescripin, userin, passin, notesin);
}
/*else if (inputChar == 'S') //Save and encode file
{
}*/
else if (inputChar == 'X') //exit program
{
exit();
}
}
system("pause");
}
bool displayMenu()
{
cout << endl << " AVAILABLE OPTIONS " << endl << endl <<
"D - DISPLAY LINE DESCRIPTIONS" << endl <<
"V - VIEW LINE DATA" << endl <<
"E - EDIT LINE DATA" << endl <<
"A - ADD LINE DATA" << endl <<
"S - SAVE AND ENCODE FILE" << endl <<
"X - EXIT PROGRAM" << endl;
return 0;
}
void viewLineData(vector<dataRow> inputData,int lineNum)
{
cout << inputData[lineNum].site << endl << inputData[lineNum].user<<endl<<inputData[lineNum].pass <<endl<<inputData[lineNum].notes;
}
void displayVector(vector<dataRow> inputData)
{
cout << fixed << setprecision(3);
for (unsigned int i = 0; i < inputData.size(); i++)
{
cout << left << setw(20) << inputData[i].site ;
}
}
void addNewRow(vector<dataRow> inputData, int& lastRowNum, string site, string user, string pass, string notes)
{
char ans;
cout << "You have entered:" << endl << site << endl << user << endl << pass << endl << notes<<endl;
cout << "Is this the data you wish to add (Y/N)? ";
cin >> ans;
ans = toupper(ans);
if (ans == 'Y')
{
dataRow tempRow = { site, user, pass, notes };
inputData.push_back(tempRow);
cout << inputData.size();
int num = inputData.size()-1;
for (unsigned int i = 0; i < inputData.size(); i++)
{
cout << inputData[i].site << endl << inputData[i].user << endl << inputData[i].pass << endl << inputData[i].notes;
}
}
else if (ans == 'N')
{
cout << "ok enter of no";
}
}
void warning()
{
cout<< "WARNING: You cannot use semi-colons in these fields. Any semi-colons entered will be removed." << endl;
return;
}
int exit()
{
pathStream.close();
system("pause");
return 0;
}
void cleanBuffer()
{
cin.clear();
cin.ignore(BUFFER_SIZE, '\n');
}

ofstream creates a file but can't write to it

REVISED: Here is my entire compilable program. It is menu driven, but the part that I am stuck on is option DECRYPT, to decrypt a caesar cyphered file, or number 5 (either could be typed in at the initial question, the decrypt could be lower case, upper case, or camel case). The ofstream variable outFile creates a file named by the user (must be a non-existing file). The problem is that it only creates the empty file, and does not print any of the data into it. All of the variables store the correct values. cout works, but outFile does not. Is there something that I am not doing correctly? I have tried to test for bad, fail, and is_open and none of them have any trouble. I do not think that file permissions would prevent anything either, since the other options in the program create and write to a file just fine. Can anyone help me?
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
#include <vector>
using namespace std;
int main() {
string inputFileName, outputFileName, inData, outData, inWord, outWord, trash;
ifstream inFile, testStream;
ofstream outFile;
bool outPutOpened = false, isLowerCase = false;
char outChar, inChar;
int shiftNum = 0, idx = 0, total = 0, max = 0, shiftValue = 0;
map<char,int> charMap;
map<char,int>::iterator mapIt;
vector<char> alphabet(26);
vector<char>::iterator shiftIt;
do {
inWord.clear();
outWord.clear();
cout << "Available options: " << endl;
cout << "1. ENCRYPT - Encrypt a file using Caesar Cypher" << endl
<< "2. CHARFREQ - display character frequency table for file"
<< endl << "3. Quit - Exit the program" << endl
<< "5. DECRYPT - decrypt a cyphered file" << endl << endl;
cout << " Enter keyword or option index: ";
getline(cin, inWord);
outWord.resize(inWord.length());
transform(inWord.begin(), inWord.end(), outWord.begin(), ::toupper);
if (outWord.compare("ENCRYPT") == 0 || outWord.compare("1") == 0) {
cout << "CAESAR CYPHER PROGRAM" << endl
<< "======================" << endl << endl;
do {
cout << "Provide the input file name: ";
getline(cin, inputFileName);
inFile.open(inputFileName.c_str());
if (inFile.fail()) {
cout << "Cannot open file, please try again!" << endl;
inFile.clear();
}
}
while (!inFile.is_open());
do {
cout << "Provide the output file name: ";
cin >> outputFileName;
getline(cin, trash);
testStream.clear();
testStream.open(outputFileName.c_str());
if(testStream.good()) {
cout << "That file already exists, choose another" << endl;
testStream.clear();
testStream.close();
}
else {
testStream.clear();
testStream.close();
outFile.open(outputFileName.c_str());
if (outFile.good()) {
outPutOpened = true;
}
}
}
while (!outPutOpened);
cout << "Enter the shift number: ";
cin >> shiftNum;
getline(cin, trash );
while(getline(inFile, inData)) {
for (idx = 0; idx <= inData.length() - 1; idx++) {
if (inData[idx] >= 'a' && inData[idx] <= 'z') {
outChar = (((inData[idx] - 'a') + shiftNum) % 26) + 'a';
outFile.put(outChar);
}
else if (inData[idx] >= 'A' && inData[idx] <= 'Z'){
outChar = (((inData[idx] - 'A') + shiftNum) % 26) + 'A';
outFile.put(outChar);
}
else {
outFile.put(inData[idx]);
}
}
}
inFile.clear();
inFile.close();
outFile.clear();
outFile.close();
}
else if (outWord.compare("2") == 0 || outWord.compare("CHARFREQ") == 0){
cout << "Enter input file name: ";
getline(cin, inputFileName);
inFile.open(inputFileName.c_str());
while (inFile.get(inChar)) {
if (charMap.find(inChar) == charMap.end()) {
charMap[inChar] = 1 ;
}
else {
++charMap[inChar];
}
}
cout << "Character Frequencies For \"" << inputFileName << "\""
<< endl;
for (mapIt = charMap.begin(); mapIt != charMap.end(); mapIt++) {
total += (*mapIt).second;
}
cout << "Total bytes read: " << total << endl;
for (mapIt = charMap.begin(); mapIt != charMap.end(); mapIt++) {
cout << " ('" << (*mapIt).first << "') occurs "
<< (*mapIt).second << " times ("
<< static_cast<double> ((*mapIt).second)
/ static_cast<double> (total) << "% of all characters)" << endl;
}
inFile.clear();
inFile.close();
}
else if (outWord.compare("5") == 0|| outWord.compare("DECRYPT") == 0) {
outPutOpened = false;
do {
cout << "Provide the input file name: ";
getline(cin, inputFileName);
inFile.open(inputFileName.c_str());
if (inFile.fail()) {
cout << "Cannot open file, please try again!" << endl;
inFile.clear();
}
}
while (!inFile.is_open());
while (inFile.get(inChar)) {
if (inChar < 'a' || inChar > 'z') {
inFile.ignore();
}
else {
inChar -= 'a';
alphabet[static_cast<int> (inChar)]++;
}
}
for (idx = 0; idx < alphabet.size(); idx++) {
if(max < alphabet[idx]){
max = alphabet[idx];
}
}
shiftIt = find(alphabet.begin(), alphabet.end(), max);
shiftValue = (distance(alphabet.begin(), shiftIt) - 4);
if (shiftValue < 0) {
shiftValue += 26;
}
inFile.close();
do {
inFile.open(inputFileName.c_str());
if (inFile.fail()) {
cout << "Cannot open file, please try again!" << endl;
inFile.clear();
}
}
while (!inFile.is_open());
outPutOpened = false;
do {
cout << "Provide the output file name: ";
cin >> outputFileName;
getline(cin, trash);
testStream.clear();
testStream.open(outputFileName.c_str());
if(testStream.good()) {
cout << "That file already exists, choose another" << endl;
testStream.clear();
testStream.close();
}
else {
testStream.clear();
testStream.close();
outFile.open(outputFileName.c_str());
if (!outFile.good()) {
cout << "bad output"<< endl;
outFile.clear();
}
if (outFile.good()) {
outPutOpened = true;
}
}
}
while(!outPutOpened);
while((inFile.get(inChar))) {
if (inChar >= 'a' && inChar <= 'z') {
inChar -= shiftValue;
if (inChar < 'a') {
inChar += 26;
}
outFile << inChar;
}
else if (inChar >= 'A' && inChar <= 'Z'){
inChar -= shiftValue;
if (inChar < 'A') {
inChar += 26;
}
outFile << inChar;
}
else {
outFile << inChar;
}
}
}
else if (outWord.compare("3") == 0 || outWord.compare("QUIT") == 0) {
break;
}
else {
cout << inWord << " is an unrecognized option, please try again"
<< endl;
}
}
while (outWord.compare("3") || outWord.compare("QUIT"));
return 0;
}
you have to flush the stream in order for the chars to actually be written to file.
after your write-to-outFile-while loop do a:
outFile.flush();
.. and the text will be written fine to the file.
Try outFile.close();. It worked for me.

reading bytes using fstream c++

I created a read / write of bytes into a binary file using fstream object
#include <iostream>
#include <fstream>
using namespace std;
#define COL_WIDTH 20
int writeBinaryFile(char *desPath);
int readBinaryFile(char *desPath);
int age;
char name[COL_WIDTH];
int recsize = sizeof(int)+sizeof(name);
int n;
int main(){
char desPath[MAX_PATH+1];
char input[2];
while(true){
cout << "Main Menu:\n1 Write Binary File\n2 Read Binary File\n3 EXIT" << endl;
cin.getline(input, 2);
if(atoi(input)== 1){
cout << "Enter destination path:" << endl;
cin.getline(desPath, MAX_PATH+1);
for(;;){
int output = writeBinaryFile(desPath);
if(output == 1) break;
else if(output == 2) { *input = '4'; break;}
}
}
else if(atoi(input) == 2){
cout << "Enter destination path:" << endl;
cin.getline(desPath, MAX_PATH+1);
for(;;){
int output = readBinaryFile(desPath);
if(output == 1) break;
else if(output == 2){ *input = '4'; break;}
}
}
else if(atoi(input) == 3)
break;
else cout << "You entered wrong input, enter only 1 or 2." << endl;
if(atoi(input) == 4) continue;
else break;
}
system("pause");
return 0;
}
int writeBinaryFile(char *desPath){
char option[2];
fstream wBin(desPath, ios::binary | ios::out);
if(!wBin){
cout << desPath << " is not good path."<< endl;
return 1;
}
cout << "Enter name: " << endl;
cin.getline(name,COL_WIDTH);
cout << "Enter age: " << endl;
cin >> age;
cout << "Enter record number: " << endl;
cin >> n;
wBin.seekp(n*recsize);
wBin.write(name, sizeof(name));
wBin.write((char*)&age, sizeof(age));
wBin.close();
cout << "Enter record again? Press:" << endl
<< "Enter to continue" << endl
<< "Q to quit" << endl
<< "M to go back to main menu" << endl;
cin.ignore(256,'\n');
cin.getline(option,2);
if(option[0] == 'q' ||option[0] == 'Q') return 1;
else if(option[0] == 'm' ||option[0] == 'M') return 2;
return 0;
}
int readBinaryFile(char *desPath){
char option[2];
fstream rBin(desPath, ios:: binary | ios:: in);
if(! rBin){
cout << "File not found!" << endl;
return 1;
}
cout << "What record number?" <<endl;
cin >> n;
rBin.seekp((n*recsize));
rBin.read(name,sizeof(name));
rBin.read((char*)&age, sizeof(int));
cout << name <<endl;
cout << age << endl;
rBin.close();
cout << "Print more? Press enter. Press Q to QUIT or M to go back." << endl;
cin.clear();
cin.sync();
cin.getline(option, 2);
if(option[0] == 'q'|| option[0] == 'Q'){rBin.close(); return 1;}
else if(option[0] == 'm' || option[0] == 'M'){rBin.close(); return 2;}
return 0;
}
i created a binary file first with name, age, recordnumber ( position of bytes which is 0) then on second loop i input name, age, recordnumber 2.
When i tried to read the first pair(char*, int) of bytes pos(0) but it returns wrong result but when i tried to read the last pair in pos(1) it returns correct result.
I also tried making 3 times the input, but only the last char* and int is correct.
Why is it getting wrong results in first bytes(name(20bytes),age(4bytes)) but getting correct it last bytes?
In each call to writeBinaryFile the output is reopened, destroying the previous contents of the file.
You'll want to use ios::binary | ios::ate | ios::out | ios::in.
But, this bitmask will not create the file if it does not exist. You can work around that problem with this code sequence:
int writeBinaryFile(char *desPath) {
...
// Create the file only if it doesn't exist
fstream(desPath, ios::binary|ios::out|ios::app);
// Now it exists -- open it
fstream wBin(desPath, ios::binary|ios::out|ios::in);
...
}
Credit #JoeFish for the useful part of the answer.