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.
Related
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;
}
}
So I am working on a switch inside of a while loop. And it is not behaving properly. When I select 'l' and load the file it lets me select again, then when I try and press 'p' to print it, it just keeps looping over the selection prompt. I am pretty sure it is because choice != 'q', but don't know how to fix it.
Thank you for any help.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
//create a struct called Weather
struct Weather {
int month;
int date;
int high;
int avg;
int low;
double precip;
string event;
};
//function prototypes
int loadData(ifstream &file, Weather days[1000]);
void printData(Weather days[1000], int count);
int main() {
// declare variables
Weather days[1000];
ifstream inFile;
string checker;
char choice = '0';
int month = 0, count;
string path;
cout << "Welcome to the weather analyzer!" << endl;
while (choice != 'q') {
cout << "Would you like to (l)oad data, (p)rint data, (s)earch data, (o)rder the data, or (q)uit? ";
cin >> choice;
cout << endl;
switch (choice) {
case 'l':
// promt user for file path
cout << "Please enter the file path: ";
cin >> path;
// open the file
inFile.open(path);
// checks to see if file successfully opened and terminates if not
if (!inFile) {
cout << "Bad Path";
getchar();
getchar();
return 0;
}
loadData(inFile, days);
count = loadData(inFile, days);
break;
case 'p':
printData(days, count);
break;
case 's':
case 'o':
case 'q':
cout << "Good bye!";
break;
default:
cout << "Invalid option";
}
}
// Close file.
inFile.close();
// Pause and exit.
getchar();
getchar();
return 0;
}
//loading function
int loadData(ifstream &inFile, Weather days[1000]) {
string checker;
int month = 0;
int i; //i varaiable keeps track of how many lines there are for the print function
for (i = 0; !inFile.eof(); i++) {
inFile >> days[i].date; // gets date and checks if it is 2017 with if loop
if (days[i].date == 2017) {
getline(inFile, checker);
getline(inFile, checker);
inFile >> days[i].date; //gets correct date value
month++;//increments month counter
}
days[i].month = month;//gets and stores data from file into days
inFile >> days[i].high
>> days[i].avg
>> days[i].low
>> days[i].precip;
getline(inFile, days[i].event);
}
return i; //returns amount of days
}
// printing function
void printData(Weather days[1000], int count) {
for (int i = 0; i < count; i++) {
cout << days[i].month << " "
<< days[i].date << " "
<< days[i].high << " "
<< days[i].avg << " "
<< days[i].low << " "
<< days[i].precip << " "
<< days[i].event << " ";
cout << endl;
}
}
After reading the user input with cin, you probably want to flush the cin buffer:
cin.clear();
cin.ignore(INT_MAX);
I have written this code and I am supposed to read in a txt file and read every other line in the txt file to the string array bookTitle[ARRAY_SIZE] and the other every other line to bookAuthor[ARRAY_SIZE]. Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int ARRAY_SIZE = 1000;
string bookTitle [ARRAY_SIZE];
string bookAuthor [ARRAY_SIZE];
int loadData(string pathname);
void showAll(int count);
//int showBooksByAuthor (int count, string name);
//int showBooksByTitle (int count, string title);
int main ()
{
int number, numOfBooks;
char reply;
string bookTitles, authorName, backupFile;
cout << "Welcome to Brigham's library database." << endl;
cout << "Please enter the name of the backup file:";
cin >> backupFile;
numOfBooks = loadData (backupFile);
if (numOfBooks == -1) {
cout << endl;
} else {
cout << numOfBooks << " books loaded successfully." << endl;
}
cout << "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All:";
cin >> reply;
do {
switch (reply) {
case 'a':
case 'A':
cout << "Author's name: ";
cin >> authorName;
showBooksByAuthor (numOfBooks, authorName);
cout << endl;
break;
case 'q':
case 'Q':
cout << endl;
break;
case 's':
case 'S':
showAll(numOfBooks);
break;
case 't':
case 'T':
cout << "Book title: ";
cin >> bookTitles;
showBooksByTitle(numOfBooks, bookTitles);
cout << endl;
break;
default:
cout << "Invalid input" << endl;
break;
}
} while (reply != 'q' && reply != 'Q');
while (1==1) {
cin >> number;
cout << bookTitle[number] << endl;
cout << bookAuthor[number] << endl;
}
}
int loadData (string pathname){
int count = 0, noCount = -1;
ifstream inputFile;
string firstLine, secondLine;
inputFile.open(pathname.c_str());
if (!inputFile.is_open()) { //If the file does not open then print error message
cout << "Unable to open input file." << endl;
return noCount;
}
for (int i = 0; i <= ARRAY_SIZE; i++) {
while (!inputFile.eof()) {
getline(inputFile, firstLine);
bookTitle[i] = firstLine;
getline(inputFile, secondLine);
bookAuthor[i] = secondLine;
cout << bookTitle[i] << endl;
cout << bookAuthor[i] << endl;
count++;
}
}
return count;
}
void showAll (int count) {
for (int j = 0; j <= count; j++) {
cout << bookTitle[j] << endl;
cout << bookAuthor[j] << endl;
}
}
So I have the loadData function which I am pretty sure is my problem. When I have it print out each string[ith position] while running the loadData function it prints out each title and author just as it appears in the txt file. But then when I run the void showAll function which is supposed to be able to print the entire txt doc to the screen it doesn't work. Also just I checked to see if the strings were actually stored in memory and they were not. (After my do while loop I have a while loop that accepts input of type int and then prints the string array of the [input position]. This prints nothing. So what do I have to do to actually store each line to a different position in the string array(s)? Feel free to correct my code but it isn't pretty yet considering I still have two functions that I haven't done anything too. (Commented out).
You main problem is that you try to read you data using two loops rather than just one! You want read until either input fails or the array is filled, i.e., something like this:
for (int i = 0;
i < ARRAY_SIZE
&& std::getline(inputFile, bookTitle[i])
&& std::getline(inputFile, bookAuthor[i]); ++i) {
}
The problem with the original code is that it never changes the index i and always stores values into the cell with index 0. Since the input isn't checked after it is being read, the last loop iteration fails to read something and overwrites any earlier stored value with an empty value. Once reading of the stream fails the outer loop iterates over all indices but doesn't do anything as the check to the inner loop is always false.
I'm struggling with a vector push_back function.
The goal is to have a function which pushes n number of elements until you decide to stop.
So my idea of a 'stop', is cin.fail().
The faulty function is
void pushbackVector(vector<double> &data)
{
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
Problem is that when I attempt to use it, I enter a infinite loop.
I have yet to sort the first vector in ASC order, second in DESC order and concatenate the first and second into the third vector. However I'm confident that I can manage this on my own.
Anyway the whole code....
#include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
menu();
vector<double> row1;
vector<double> row2;
/* not yet used
vector<double> row3;
*/
int input;
cin >> input;
bool exit = 0;
while (!exit)
{
switch (input)
{
case 1:
pushbackVector(row1);
break;
case 2:
pushbackVector(row2);
break;
case 3:
printVector(row1);
break;
case 4:
printVector(row2);
break;
case 5:
cout << "Printing out the contents of row 1\n";
printVector(row1);
cout << "Printing out the contents of row 2\n";
printVector(row2);
cout << "Printing out the contents of row 3\n";
// printVector(row3);
break;
case 6:
cout << "Exitting\n";
exit = 1;
break;
default:
cout << "Invalid choice\n";
}
}
return 0;
}
void menu()
{
cout << "Choose an option\n";
cout << "1) Enter first vector\n";
cout << "2) Enter second vector\n";
cout << "3) Print out the first vector\n";
cout << "4) Print out the second vector\n";
cout << "5) Print out all three vectoros\n";
cout << "6) Exitting the program\n";
}
void printVector(const vector<double> &data)
{
for(int i = 0; i < data.size(); i++)
{
cout << data[i] << ", ";
}
cout << "\n";
}
void pushbackVector(vector<double> &data)
{
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
}
void sortVector (vector<double> &data)
{
cout << "Sorting your vector \n";
sort(data.begin(), data.end());
}
You're only reading once, move the read inside the loop:
void pushbackVector(vector<double> &data)
{
double input;
// cin >> input; --------------
//
for (int i = 0; i < 100; i++) //
{ //
cin >> input; // <---------
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
That'll make sure that you actually get input. Now, if you're not going to enter 100 values, you need to somehow notify the stream. That's done by insert "EOF character" in it. Press CTRL+Z on windows or CTRL+D on unix terminals.
When this gets read from the stream, it enters a fail (and eof) state and it'll stay like that unless you clear the error flags by calling cin.clear() when appropriate.
You've made the same mistake also in main. You only read once before the while loop, so input keeps the value you initialy entered and keeps entering the same choice. I think that's the infinite loop you're talking about. To fix it, move the read statement just before the switch.
Hope that helps.
Also, this is how I'd write the function:
double input;
for (int i = 0; (cin >> input) && i < 100; ++i) {
data.push_back(input);
}
cout << "Ending input.\n";
Streams can be used in boolean expression - they convert to the result of !fail() - and such are a convenient and idiomatic way to control a loop.
The infinite loop is cause by the fact that you are reading:
cin >> input;
once and then entering a while loop (in your main) that will keep going forever (unless the input is initially equal to 6).
Change:
cin >> input;
bool exit = 0;
while (!exit)
{
// ...
to:
bool exit = 0;
while (!exit)
{
cin >> input;
// ...
Depending on what your logic is, the same is happening in the pushbackVector function at:
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
// ...
You might want to change that to:
double input;
for (int i = 0; i < 100; i++)
{
cin >> input;
// ...
Do something like this instead:
void pushbackVector(vector<double> &data)
{
double input;
while (cin >> input) //will return true when there's valid input, otherwise false
{
if (input == -1)
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
This will read the input until you enter -1 or enter invalid input.
I think relying on cin.fail() is just not a good idea. The proper way to use fail() is explained in the link. It is not what you may expect.
Putting aside the reading which is misplaced, if you enter something you should not, you need to purge the input.
Add in the block of te first if
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
I would write the function the following way
void pushbackVector( std::vector<double> &data )
{
cin.clear();
cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
data.insert( data.end(), std::istream_iterator<double>( std::cin ), std::istream_iterator<double>() );
}
I was done some days before but I forgot to post my answer.
Who knew that I could just say if the cin fails, stop the input but don't end the program, lol.
#include<iostream>
#include<vector>
#include<algorithm> // for sort algorithms
#include<iomanip> // for setprecision
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
vector<double> row1;
vector<double> row2;
vector<double> row3;
int input;
bool exit = false;
while(!exit)
{
menu();
cin >> input;
switch (input)
{
case 1:
cout << "Entering vector 1\n";
pushbackVector(row1);
sortVector(row1);
cout << "\n";
break;
case 2:
cout << "Entering vector 2\n";
pushbackVector(row2);
sortVector(row2);
reverse(row2.begin(), row2.end());
cout << "\n";
break;
case 3:
cout << "Printing out vector 1\n";
printVector(row1);
cout << "\n";
break;
case 4:
cout << "Printing out vector 2\n";
printVector(row2);
cout << "\n";
break;
case 5:
// reserve enough space for all of row1's and row2's elements
row3.reserve(row1.size() + row2.size());
// insert row1's elements at the end of row3
row3.insert(row3.end(), row1.begin(), row1.end());
// insert row2's elements at the end of row3
row3.insert(row3.end(), row2.begin(), row2.end());
cout << "Printing out the contents of vector 1\n";
printVector(row1);
cout << "Printing out the contents of vector 2\n";
printVector(row2);
cout << "Printing out the contents of vector 3\n";
printVector(row3);
cout << "\n";
break;
case 6:
cout << "Exitting\n";
exit = true;
break;
default:
cout << "Invalid choice\n";
}
}
return 0;
}
void menu()
{
cout << "Choose an option\n";
cout << "1) Enter first vector\n";
cout << "2) Enter second vector\n";
cout << "3) Print out the first vector\n";
cout << "4) Print out the second vector\n";
cout << "5) Print out all three vectoros\n";
cout << "6) Exitting the program\n";
}
void printVector(const vector<double> &data)
{
for(int i = 0; i < data.size(); i++)
{
cout << setprecision(4) << data[i] << " ";
}
cout << "\n";
}
void pushbackVector(vector<double> &data)
{
double input;
int numOfItems;
cout << "How many items you want to add into vector?: ";
cin >> numOfItems;
for (int i = 0; i < numOfItems; i++)
{
cin >> input;
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
}
void sortVector(vector<double> &data)
{
cout << "Sorting your vector \n";
sort(data.begin(), data.end());
}
For some reason my bank script isn't working. More specifically, the search() does not work. I kind of understand why it doesn't, probably because of if(obj.returnId() == n), but I have no clue how to fix it. When I search an account, it will only allow me to find the last account made, not any of the previous ones. Here is my code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <Windows.h>
#include <conio.h>
using namespace std;
bool loop = true;
class account
{
int id;
char name[40];
char password[40];
public:
void getData()
{
cout << "\nEnter your name: ";
cin >> name;
cout << "\nEnter ID: ";
cin >> id;
cout << "\Enter pass: ";
cin >> password;
}
void showData()
{
cout << "\nName: ";
puts(name);
cout << "\nID: " << id;
cout << "\n";
}
int returnId()
{
return id;
}
};
void createAccount()
{
account obj;
ofstream fileCreate;
fileCreate.open("accounts.dat", ios::binary|ios::app);
obj.getData();
fileCreate.write((char*)&obj,sizeof(obj));
fileCreate.close();
}
void display()
{
account obj;
ifstream fileRead;
fileRead.open("accounts.dat", ios::binary);
while(fileRead.read((char*)&obj, sizeof(obj)))
{
obj.showData();
}
fileRead.close();
}
void search(int n)
{
account obj;
ifstream fileRead;
fileRead.open("accounts.dat", ios::binary);
while(fileRead.read((char *) &obj, sizeof(obj)) );
{
fileRead.seekg(0,ios::beg);
if(obj.returnId() == n)
{
obj.showData();
}
else {
cout << "\nUser not foud!\n";
}
}
fileRead.close();
}
void main()
{
cout << "Welcome to the Bank.\n\n";
while (loop==true)
{
char choice[10];
cout << "Please select an option:\n";
cout << "------------------------------------------------\n";
cout << "(a)Log into an account\n(b)Create an account\n(s)Search an account\n(e)Exit\n";
cout << "------------------------------------------------\n";
cout << "Choice: ";
cin >> choice;
choice[0] = tolower(choice[0]);
cout << "\n------------------------------------------------\n\n";
switch (choice[0])
{
case 'a':
display();
break;
case 's':
int n;
cout << "Enter the ID of the account: ";
cin >> n;
search(n);
break;
case 'b':
createAccount();
break;
case 'e':
loop = false;
break;
default:
system("CLS");
cout << "The option \"" << choice[0] << "\" is invalid.\n\n\n\n";
break;
}
};
cout << "\n\n\n";
cout << "Click anything to exit.";
getch();
}
Your problem is the semicolon at the end of this line:
while(fileRead.read((char *) &obj, sizeof(obj)) );
That makes this loop have an empty body. So you basically read the whole file and throw away the results, except for the last entry.
get rid of this also:
fileRead.seekg(0,ios::beg);
I don't know why you need that, it would only make you read the first entry over and over.
The other error is that you should only say 'User not found' when you've tested all the accounts and they all failed. Your loop (when you've removed the semi-colon) is saying 'User not found' after every failed test.
You probably don't find the entry you are looking for because each time you have read an entry from the file, you reset the position to the beginning. This means that your loop will run forever, reading the same entry over and over again and never finding the entry you search for.
the seek might be the problem:
while(fileRead.read((char *) &obj, sizeof(obj)) ) //;
{
// seek to start?
//fileRead.seekg(0,ios::beg);
...
}
have a look at http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/index.html
aside, use
cout << "text" << endl;
for platform-agnostic newlines.