I am having issues with cin.getline(). When I put it into the below program, it is giving an error:
no instance of overload function (ect) matches the argument list
I am also having an issue with my variable nx. The compiler says that it cannot be a constant, but I'm not sure how it is.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//create a class for one book
class Book
{
//member variables
public:
string title;
string author;
int year;
//function to print the book details
void print()
{
cout << "Title: " << title << endl;
cout << "Authot: " << author << endl;
cout << "Year: " << year << endl;
}
};
int main()
{
std::string filename, temp;
//prompt the user to enter the file name
cout << "Enter filename: ";
cin >> filename;
//open the file
fstream file;
file.open(filename.c_str());
int nx;
//read the first line of the file to know the number of books
file >> nx;
//move to the next line of the file
std::cin.getline(file, temp);
//allocate an array of n Book
Book books[nx];
//read the data for n books from the file
for (int i = 0; i < nx; i++)
{
//read file and initialize the books array
std::cin.getline(file, books[i].title);
std::cin.getline(file, books[i].author);
file >> books[i].year;
//move to the next line of the file
getline(file, temp);
}
//Display the output
cout << "Books found: " << nx << endl;
for (int i = 0; i < nx; i++)
{
cout << "\nBook " << i + 1 << ":" << endl;
cout << "Title: " << books[i].title << endl;
cout << "Author: " << books[i].author << endl;
cout << "Year: " << books[i].year << endl;
}
}
The 2-parameter std::cin.getline() method does not take a std::fstream or a std::string as parameters. It takes a char* and a std::streamsize instead, as it is meant to fill a char[] buffer. To fill a std::string from a stream, you need to use the standalone std::getline() function instead, eg:
std::getline(file, temp);
...
std::getline(file, books[i].title);
...
As for the "constant" error relating to your nx variable, the problem is on this line:
Book books[nx];
You are trying to declare a fixed-sized array using a size that is not known until runtime. You can't do that in standard C++, an array's size must be known at compile-time instead. Otherwise, you have to use new[] or std::vector to allocate the array dynamically at runtime instead, eg:
Book* books = new Book[nx];
...
delete[] books;
Or:
#include <vector>
std::vector<Book> books(nx);
Demo
On a side note:
When you want to discard content from an istream up to the next '\n' character, you can use the stream's ignore() method instead of std::getline(), that way you are not wasting memory unnecessarily for an unused std::string, eg:
#include <limits>
//move to the next line of the file
//std::getline(file, temp);
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Also, you have defined a print() method in Book, but you are not actually using it. Your final display loop can do this instead:
//Display the output
cout << "Books found: " << nx << endl;
for (int i = 0; i < nx; i++)
{
cout << "\nBook " << i + 1 << ":" << endl;
/*
cout << "Title: " << books[i].title << endl;
cout << "Author: " << books[i].author << endl;
cout << "Year: " << books[i].year << endl;
*/
books[i].print();
}
Related
I'm done with my assignment for a beginner C++ course, and the only annoying thing is I cannot get rid of the extra space that appears on the screen when I input data from a file and print to screen while outputting to another file.
I have looked into the input.ignore() and putback() functions, but I cannot get them to work while messing around.
I know this is cause the extra \n character is at the end of the first line, or cause I skipped the comma.
Any tips would be great, in terms of formatting a .ignore() or .putback(), as the professor rushed through explaining it at the end of class as we were leaving without examples.
It outputs to the screen as such:
John 13333 .69 // one extra space after John for every number and item
Susie 12222 .75...
#include <iomanip> //include directives to use various keywords
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <limits>
using std::cin; //various usings to avoid namespace std
using std::cout;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;
using std:: left;
using std::setw;
using std::numeric_limits;
void getName(string & fileName);
void readandsend(ifstream &input,ofstream &output);
int main()
{
//my variables I will use in function calling
string fileN;
ifstream input;
ofstream output;
getName(fileN); //calls to functions
input.open(fileN); //opens file to be streamed for input
output.open("Assgn6-BB.txt");
if (!input)
{
cout << "The input file failed to open! Try again." << endl; //checks that the file opened correctly
return -1;
}
cout << "============================================================" << endl; //prints header
cout << "=" << " ";
cout << "FARMER'S MARKET INVENTORY" <<" " << "=" <<endl;
cout << "============================================================" << endl;
readandsend(input, output);
return 0;
}
void getName(string & fileName)
{
//pre-conditions: a corrcet filename is entered by the user that exists and has data
//post-conditions: a filename is entered and processed without error to be used later
cout << "Enter the name of the file: "; //takes in file name
cin >> fileName;
}
void readandsend(ifstream &input,ofstream &output)
{
//pre-conditions: filename is a correct file that exists and has data that is opened correctly
//post-conditions: prints out the data from the file until the end of the file is reached while outputting the data and calculations to another file
char farm[25];
string item;
int numItems;
double pricePer, subTotal, total = 0, totalItems = 0;
input.getline(farm,25,','); //reads in first set of data to make sure the standard input.eof reads correctly
input >> numItems;
input >> item;
input >> pricePer;
totalItems += numItems;
total +=(pricePer * numItems);
while(!(input.eof()))
{
output << left << setw(25) << farm //sends to output file
<< setw(10) << numItems << setw(15)
<< item << setw(8) << pricePer
<< setw(8) << (numItems * pricePer);
cout << left << setw(25) << farm //prints to screen to verify
<< setw(10) << numItems
<< setw(15) << item
<< setw(8) << pricePer
<< setw(8) << (numItems*pricePer) << endl;
input.getline(farm, 25, ',');
input >> numItems;
input >> item;
input >> pricePer;
totalItems += numItems;
total += (pricePer * numItems);
}
cout << left << setw(24) << "Grand Total: " << totalItems << " items's totaling $" << total << endl;
input.close(); //closes the files
output.close();
}
I have a little question. I'm currently doing a school assignment in c++ and the task is to have something similar to a small library, where the user can ask to look at a book and then the program will print out the release year, author, how many pages etc etc. The assignment is focused on vectors and arrays, but I thought a smart way of doing it could be to have the release years in a text file and then save those years in an array. When I first it, everything was saved in characters, (meaning "1","8","8","5"), when I'd actually like it to save every line in the text document as a string in the array, or something similar (like this: "1885",). I couldn't really figure out how to split them up into strings then. I then talked a bit to a friend and this is where I am with my code now, it's not really working and at the moment I have no idea how I am supposed to solve it. Main problem is I don't know how to read and save every line in the text document as a string, however I am grateful for any help that would make me be able to print out a single year from the text document, in any other way.
This is what my code looks like:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <istream>
using namespace std;
void book();
void readFile(int input);
void oddEven();
void stringLiner();
void factorial();
int main()
{
int input;
while (input != 0)
{
cout << "Hello. Welcome to the first, truly big, assignment in this programming course." << endl;
cout << "Which part do you wish to access?" << endl;
cout << "1. Book program" << endl;
cout << "2. 2 arrays - One EVEN ~ One ODD" << endl;
cout << "3. The one at a time string" << endl;
cout << "4. Factorial array" << endl;
cout << "0. Exit " << endl;
cin >> input;
switch (input)
{
case 1:
book();
break;
}
}
}
void book() //This is the function used to do the book thing
{
cout << string( 100, '\n' );
int input;
string year[5] = {"1883"/*Treasure Island*/ }; //Array for the years the books were written
string author[5] = {"Robert Louis Stevenson"/*Treasure Island*/, "yollo"}; //Array for the authors
string pages[5] = {"304"/*Treasure Island*/,"420" }; //Array for the number of pages
string books[5] = {"Treasure Island", "Swagolo" }; //Array for the name of the books
cout << "You have chosen to look at books." << endl;
cout << "These are the books in the library. Pick one to see what year it was written in, what author wrote it and how many pages it contains. " << endl;
cout << "These are the books in the library: " << endl;
for (int i = 0; i<5; i++) //Loop to display all the books + what number to press to access them.
{
cout << i+1 << " " << books[i] << endl;
};
cout << "Please type a number to look at that book. " << endl;
cin >> input;
int TresIsl = input-1;
switch (input) //Switch case to chose which book to look at.
{
case 1: //Info about Treasure Island
cout << "This is " << books[TresIsl] << " and this is some info. " << endl << endl;
cout << books[TresIsl] << " was released in " ;
readFile(input);
cout << " and it was written by " << author[TresIsl] << ". ";
cout << "This book contains " << pages[TresIsl] << " pages. " << endl;
break;
case 2:
cout << "This is " << books[TresIsl] << " and this is some info. " << endl << endl;
cout << books[TresIsl] << " was released in " ;
readFile(input);
cout << " and it was written by " << author[TresIsl] << ". ";
cout << "This book contains " << pages[TresIsl] << " pages. " << endl;
break;
}
}
void readFile(int input)
{
ifstream file("year.txt");
int numlines = 0;
int numMaxLines = 5;
vector<string> lines (numMaxLines);
while(numlines < numMaxLines && !file.eof())
{
getline(file, lines);
numlines++;
}
cout << lines[input];
}
The other void functions are for other tasks in this assignment which I didn't include now, I just copy pasted the code where they were included. Also please don't mind the slightly childish stuff in the code.
Also I am very sorry if this breaks any rules for the forum or something similar. I tried to find another topic like this for c++, but I couldn't find anything helpful.
It's not clear what exactly your problem is, but assuming that you want to read a file line-by-line and get a vector of those lines, something like this would do it:
std::vector<std::string> readLines(const std::string& filename)
{
std::vector<std::string> lines;
std::ifstream input(filename);
std::string line;
while (std::getline(input, line))
{
lines.push_back(line);
}
return lines;
}
if any one's still got a question, a friend and me discussed it and he helped me a bit, and we got a code that works in my case at least, so I thought I'd show it to you:
void readFile(int input)
{
ifstream file("year.txt");
string in;
vector<string> lines;
if (file.is_open())
{
while ( getline (file, in) )
{
lines.push_back(in);
}
cout << in;
}
file.close();
cout<<lines[input-1]<<endl;
}
The cout in the end I guess is unnecessary in some cases, but this worked for me and my homework. Thanks for everyone's help anyways.
I am trying to figure out how to store binary data that is saved to a .dat file "customer.dat" into a structure of vectors. I thought I have had it a few times, but with no luck.
Basically, I have a working method of storing the data into the .dat file, the newEntry function, but I can not seem to work out on how to bring the data back one set at a time into an order structure of vectors. The function in question is the searchDisplay function. Here is the code:
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <string>
#include <cstring>
#include <cctype>
using namespace std;
const int NAME_SIZE = 51, ADDR_SIZE = 51, PHONE_SIZE = 14;
struct Client {
char name[NAME_SIZE];
char address1[ADDR_SIZE];
char address2[ADDR_SIZE];
char phone[PHONE_SIZE];
double acctBal;
double lastPay;
};
//void welcome();
int menu();
int newEntry();
int searchDisplay();
int main() {
int selection;
int option = 0;
int end;
//welcome();
while (option != 6) {
selection = menu();
if (selection == 1) {
cin.ignore();
end = newEntry();
if (end == 0) {
return 0;
}
} else if (selection == 2) {
end = searchDisplay();
if (end == 0) {
return 0;
}
}
}
return 0;
}
int menu() {
int selection;
cout << "User please enter the number that corresponds with what you wish to do..."
<< endl;
cout << "1) Add An Entry" << endl
<< "2) Search for a Specfic Person and erase." << endl;
cin >> selection;
return selection;
}
int newEntry() {
string input;
Client person;
char response = 'y';
//create file object and open file
fstream customer("customer.dat", ios::app | ios::binary);
if (!customer) {
cout << "Error opening file. Program aborting." << endl;
return 0;
}
do {
cout << "Enter person information:" << endl << endl;
cout << "Name: " << endl;
getline(cin, input);
strcpy(person.name, input.c_str());
cout << endl << person.name;
cout << endl << "Street Adress (And Apartment Number):" << endl;
cin >> person.address1;
getline(cin, input);
strcpy(person.address1, input.c_str());
cout << endl << "City, State, Zipcode: " << endl;
cin >> person.address2;
getline(cin, input);
strcpy(person.address2, input.c_str());
cout << endl << "Phone: " << endl;
cin >> person.phone;
getline(cin, input);
strcpy(person.phone, input.c_str());
cout << endl << "Account Balance: " << endl;
cin >> person.acctBal;
//input validation to ensure a non neg number
cin.ignore();
cout << endl << "Last Payment: " << endl;
cin >> person.lastPay;
//input validation to ensure a non neg number
customer.write(reinterpret_cast<char *>(&person), sizeof(person));
cout << endl << "Do you want to enter another record? (Enter Y for Yes, N for No) " << endl;
cin >> response;
cout << "_______________________________________________" << endl << endl;
if (toupper(response) == 'Y') {
cin.ignore();
}
} while (toupper(response) == 'Y');
customer.close();
return 1;
}
/********************************************
My main problem is with the below function
********************************************/
int searchDisplay() {
vector<Client> store(2);
Client foo;
int i = 0;
fstream customer("customer.dat", ios::in | ios::binary);
if (!customer) {
cout << "Error opening file. Program aborting." << endl;
return 0;
}
//MY HOPE WAS THIS WOULD STORE EACH SET OF DATA INTO THE STRUCTURE OF VECTORS
customer.read(reinterpret_cast<char *>(&store), sizeof (store[0]));
while (!customer.eof()){
cout << store[i].name << ":" << endl
<< store[i].address1 << endl
<< store[i].address2 << endl
<< store[i].phone << endl
<< store[i].acctBal << endl
<< store[i].lastPay << endl << endl;
i++;
customer.read(reinterpret_cast<char *>(&store), sizeof (store[i]));
}
customer.close();
return 1;
}
Sorry if any of the coding is a little off in its indenting, I was having issues with the method of putting the code onto the text block.
But yes, any help would be great. This is my first time working with vectors significantly and first time ever with more file classes.
Your first problem is the opening of the data file for writing. You are currently opening it with the flag "ios::app", when it should be "ios::out". Over here (gcc version 4.7.2) i get no output to file when opening the file with "ios::app".
Using "ios::out" it creates a file and dumps the data into it.
The second problem is in the line where you open and read the file. You are missing a "[0]". Check the corrected version below:
customer.read(reinterpret_cast<char *>(&store[0]), sizeof (store[0]));
Making this modifications you can get closer to the desired results.
The main problem here is that writing and reading binary files is a bit different from regular text files, that have indications of line endings, for example. You need to organize your data differently, which can be quite complicated. Try Serializing with Boost.
I've tried to write a simple database program. The problem is that ofstream does NOT want to make a new file.
Here's an extract from the offending code.
void newd()
{
string name, extension, location, fname;
cout << "Input the filename for the new database (no extension, and no backslashes)." << endl << "> ";
getline(cin, name);
cout << endl << "The extension (no dot). If no extension is added, the default is .cla ." << endl << "> ";
getline(cin, extension);
cout << endl << "The full directory (double backslashes). Enter q to quit." << endl << "Also, just fyi, this will overwrite any files that are already there." << endl << "> ";
getline(cin, location);
cout << endl;
if (extension == "")
{
extension = "cla";
}
if (location == "q")
{
}
else
{
fname = location + name + "." + extension;
cout << fname << endl;
ofstream writeDB(fname);
int n = 1; //setting a throwaway inteher
string tmpField, tmpEntry; //temp variable for newest field, entry
for(;;)
{
cout << "Input the name of the " << n << "th field. If you don't want any more, press enter." << endl;
getline(cin, tmpField);
if (tmpField == "")
{
break;
}
n++;
writeDB << tmpField << ": |";
int j = 1; //another one
for (;;)
{
cout << "Enter the name of the " << j++ << "th entry for " << tmpField << "." << endl << "If you don't want any more, press enter." << endl;
getline(cin, tmpEntry);
if (tmpEntry == "")
{
break;
}
writeDB << " " << tmpEntry << " |";
}
writeDB << "¬";
}
cout << "Finished writing database. If you want to edit it, open it." << endl;
}
}
EDIT: OK, just tried
#include <fstream>
using namespace std;
int main()
{
ofstream writeDB ("C:\\test.cla");
writeDB << "test";
writeDB.close();
return 0;
}
and that didn't work, so it is access permission problems.
ofstream writeDB(fname); //-> replace fname with fname.c_str()
If you lookup the documentation of the ofstream constructor, you will see something like:
explicit ofstream ( const char * filename, ios_base::openmode mode = ios_base::out );
The second argument is optional, but the first one is a const char*, and not a string. To solve this problem the most simple way is to convert your string to something called a C-string (char*, which is basically an array of chars); to do that just use c_str() (it«s part of the library).
Other than that, you could just place the information directly on a C-str, and then pass it normally to the ofstream constructor.
I want to write a little program which should be used in supermarkets. everything is fictitious and it's only for learning purposes.
However, The tool generate a new data for every new article. in the data there are 2 lines, the name and the prise.
The data is named as the article number of the product. So the user enter a articlenumber and the tool looks for a data with this number, if it found it, it reads the 2 lines and initiates the variables.
But for some reasons it does not convert and copy the strings correctly.
here is the part which loads the data.
int ware::load()
{
string inhalt;
cout << "please insert article number" << endl;
cin >> articlenumber;
productname.open(articlenumber, ios::in);
if (!productname.is_open())
{
cout << "can't find the product." << endl;
return 1;
}
if (productname.is_open())
{
while (!productname.eof())
{
getline(productname, inhalt);
strcpy(name,inhalt.c_str());
getline(productname, inhalt);
price = atoi (inhalt.c_str());
cout << inhalt << endl;
}
warenname.close();
}
cout << endl << endl <<
"number: " << inhalt <<
" preis: " << price <<
" name: " << name <<
endl << endl; //this is a test and will be deleted in the final
}
hope you can help me!
Here is the class:
class ware{
private:
char articlenumber[9];
char name[20];
int price;
fstream warennamefstream;
ifstream warenname;
public:
void newarticle(); //this to make a new product.
void scan(); //this to 'scan' a product (entering the article number ;D)
void output(); //later to output a bill
int load(); //load the datas.
};
hope everything is fine now.
First, you have a using namespace std; somewhere in your code. This occasionally leads to subtle bugs. Delete it. ( Using std Namespace )
int ware::load()
{
string inhalt;
cout << "please insert article number" << endl;
cin >> articlenumber;
The type of articlenumber is incorrect. Declare it std::string, not char[]. ( What is a buffer overflow and how do I cause one? )
productname.open(articlenumber, ios::in);
There is no reason to have an ifstream lying around waiting to be used. Also, there is no point in providing ios::in -- it is the default. Just use the one-argument form of the ifstream constructor.
if (!productname.is_open())
{
cout << "can't find the product." << endl;
return 1;
}
Don't bother checking to see if the file opened. Your users don't care if the file was present or not, they care whether the file was present AND you retrieved the essential data.
if (productname.is_open())
{
while (!productname.eof())
{
getline(productname, inhalt);
strcpy(name,inhalt.c_str());
getline(productname, inhalt);
price = atoi (inhalt.c_str());
cout << inhalt << endl;
}
warenname.close();
}
This loop is just wrong.
Never invoke eof(). It doesn't do what you think it does, and will cause bugs.
Why is this a loop? Aren't there only two lines in the file?
There is no point in calling close. Just let the file close when the istream goes out of scope.
Why is warename different than productname?
Don't store your data in char[]. This is the 21st century. Use std::string.
.
cout << endl << endl <<
"number: " << inhalt <<
" preis: " << price <<
" name: " << name <<
endl << endl; //this is a test and will be deleted in the final
Never use endl when you mean to say '\n'. Each of those endl manipulators invokes flush, which can be very expensive. ( What is the C++ iostream endl fiasco? )
You forgot to return a value.
Try this instead:
int ware::load()
{
// This declaration should be local
std::string articlenumber;
cout << "please insert article number" << endl;
cin >> articlenumber;
// This declaration should be local
std::ifstream productname(articlenumber.c_str());
// These declarations can be class members:
std::string name;
int price;
std::string number;
if(getline(productname, name) &&
productname>>price &&
productname>>number)
{
cout << "\n\n" <<
"number: " number <<
" preis: " << price <<
" name: " << name <<
"\n\n"; //this is a test and will be deleted in the final
return 0;
} else {
cout << "can't find the product." << endl;
return 1;
}
}