How to print to file? - c++

I'm need to print some info on a file ".txt".
I wrote on the program the link of the file I want to copy the info. The ".txt" file is empty.
Eclipse tells me that the code is without error. This is the part of code of the print on file:
void stampaVendute(string& vendute,int& n,Opere f[],char p[],int a){
cout<<"\nInserisci il file sul quale vuoi visualizzare le opere vendute: "<<endl;
getline(cin,vendute);
ofstream ofs;
ofs.open(vendute.c_str());
if(!ofs.good()){
cout<<"C'è qualche problema nell'apertura del file"<<endl;
return;
}
for(int i=0;i<n;i++){
if((!stricmp(p,f[i].N_C)) and a<=f[i].anno){
ofs<<"\nOPERA "<<(i+1)<<endl;
ofs<<"Codice: "<<f[i].codice<<";"<<endl;
ofs<<"Titolo: "<<f[i].titolo<<";"<<endl;
ofs<<"Autore: "<<f[i].N_C<<";"<<endl;
ofs<<"Anno: "<<f[i].anno<<";"<<endl;
ofs<<"Valore: "<<f[i].prezzo<<";"<<endl;
}
ofs.close();
}
cout<<"\nI DATI SONO STATI COPIATI CORRETTAMENTE SUL FILE!"<<endl;
}

If if((!stricmp(p,f[i].N_C)) and a<=f[i].anno){ fails the test then nothing is printed to the file. Add a line that unconditionally prints to the file after opening, to see if it works.
Print the file name to the user when the file is opened successfully.
If you are using Windows, you can use process monitor from SysInternals (now owned by Microsoft) to see what file is actually being opened.
ofs.open(vendute.c_str());
why are you using c_str here? You know that open takes a std::string normally! You are getting a pointer to the raw characters just to construct a new different string object, and forcing the compiler to re-count the number of characters (calling strlen() again).
You should write it as one line anyway. Initialize the variable when you define it:
ofstream ofs {vendute};
⧺SL.io.50 Don't use endl.
for(int i=0;i<n;i++){
... many uses of `f[i]` follows
You should be using a range-based for loop rather than subscripts, but the way you are passing the data (separate pointer to the first element and length) instead of simply passing a collection prevents that. This is not a good way to do things! See Standard Guidelines ⧺I.13 etc.
If you did need to go over the collection via subscripts, don't keep subscripting it over and over and over. Make a reference variable pointing to that spot:
for(int i=0;i<n;i++){
const auto& x = f[i];
... now use x over and over, not f[i]
here's your problem
Look where ofs.close(); is being called. The indentation of the code in the post is all messed up... it looks like this should be after the loop, before the final cout line. But what's that extra } coming from?
You are closing the file after the first iteration through the loop. If that case (i==0) did not print results, nothing will ever be shown.

Related

Multiple text files inside two loop

I want to create some file inside two loops and fill out them without closing the file inside the first and second loop.
Here you can find what I mean of this question by looking at this part of a code, and it doesn't work ... of course, it creates 100 files but the problem is that each file just holds the last iteration of the first loop while I want each file to write the whole iteration of the first loop.
ofstream fout;
for(int t = 0; t < N; t++){
for(int e = 0; e < 100; e++){
fout.open("myfile_"+strcpp(e)+".txt");
fout << t << psi[e] << endl;
}
}
fout.close();
where the function strcpp(e) is given by
template <class T>
string strcpp(T value){
ostringstream out;
out << value;
return out.str();
}
Every time you call:
fout.open(...);
The whole contents of the file before opening it are erased. Since you open each file many times you are constantly erasing anything that you had written to it before you write the next line. This is why the last write of your outer for loop is the only thing in each file.
We can fix this by specifying we want to append to the file we are opening. std::ofstream::open() takes a second optional argument that specifies the mode. You can set the mode to append whatever you write in the file to the end of what is already in there instead of erasing the original file contents.
Ex:
fout.open(my_file_name, ios::app);
Although a better solution might be to just switch in your inner and outer for loop. Then you open each file before the start of the inner for loop, do all the writes to that one file, then close that file and move on to the next one. This way you don't have to open each file many, many times.

How do i find a string and delete it with a following string from a file in C++?

How do i find a string in a file? In my code, i want to find the name of a person in the file. and do the actions in the comments. Here is my code:
int main(){
size_t found;
ofstream myfile;
cout << "Enter the name you wish to delete." << endl;
getline(cin, name);
myfile.open("database.dat");
found=myfile.find(name);
if (found!=string::npos){
number = myfile.tellg();
/*Delete current line and next line*/
}
}
Do you want to modify the file, or simply skip those two lines while reading?
Actually, the solution is the same for both, because removing data from the middle of the file requires reading everything after that and rewriting it with an offset (just like removing an element from the middle of an array).
So, read the entire file into memory except for any lines you determine need to be deleted (just skip those). After that, write the surviving lines back to disk. It's probably a good idea to use a temporary file which gets moved to the original name as a final step, so that data isn't destroyed if your process is aborted.

Initializing a Vector of Objects from a .txt file

#include<iostream>
#include<vector>
#include<fstream>
#include "stock.h"
int main(){
double balance =0, tempPrice=0;
string tempStr;
vector < Stock > portfolio;
typedef vector<Stock>::iterator StockIt;
ifstream fileIn( "Results.txt" );
for(StockIt i = portfolio.begin(); i != portfolio.end(); i++)
{
while ( !fileIn.eof( ))
{
getline(fileIn,tempStr);
i->setSymbol(tempStr);
fileIn >> tempPrice;
i->setPrice(tempPrice);
getline(fileIn,tempStr);
i->setDate(tempStr);
}
fileIn.close();
}
for(StockIt i = portfolio.begin(); i != portfolio.end(); i++){
cout<<i->getSymbol() <<endl;
cout<<i->getPrice() <<endl;
cout<<i->getDate() <<endl;
}
return 0;
}
Sample text file, Results.txt:
GOOG 569.964 11/17/2010
MSFT 29.62 11/17/2010
YHOO 15.38 11/17/2010
AAPL 199.92 11/17/2010
Now obviously, I want this program to create a vector of Stock Objects which has the appropriate set/get functionality for object: Stock(string, double, string).
Once that is done, I want to print out each individual member of each Object in the vector.
One thing that boggles my mind about fstream, is how can it decipher spaces and end of lines, and intelligently read strings/ints/doubles and place them into the appropriate data type? Maybe it can't...and I have to add an entirely new functionality?
now it would seem that I'm not actually creating a new object for each iteration of the loop? I think would need to do something along the lines of:
portfolio.push_back(new Stock(string, double, string));? I'm just not entirely sure how to get to that point.
Also, this code should be interchangeable with std::list as well as std::vector. This program compiles without error, however, there is zero output.
First of all, iterating over the vector only makes sense when it isn't empty. So remove the line:
for(StockIt i = portfolio.begin(); i != portfolio.end(); i++)
because otherwise the contents of this loop will never be executed.
Second, you have problems with your input reading: you use getline for the first field, which would read the values of all 3 fields on the line into the tempStr variable.
Third, you shouldn't use while(!fileIn.eof()) - the eof function only returns true after you tried to read past the end of the file. Instead, use:
while (fileIn >> symbol >> price >> date) {
//here you should create a Stock object and call push_back on the vector.
}
This will read the three fields, which are separated by spaces.
Few issues in your code.
the first for loop runs on an empty portfolio vector, as the vector is not initialized (no objects are being pushed to it) the begin() and end() are the same.
you should read line by line from the fstream until EOF, then push objects to the vector.
each line you read, you should split (tokenize) into the 3 parts, and create a new Stock object to be pushed to the vector.
Another side feedback, whenever using an stl iterator, use ++itr on for loops, it will run much more fast

Binary file only overwrites first line C++

So I have a binary file that I create and initialize. If I set my pointer to seekg = 0 or seekp = 0, then I can overwrite the line of text fine. However if I jump ahead 26 bytes (the size of one line of my file and something I have certainly confirmed), it refuses to overwrite. Instead it just adds it before the binary data and pushes the old data further onto the line. I want the data completely overwritten.
char space1[2] = { ',' , ' '};
int main()
{
CarHashFile lead;
lead.createFile(8, cout);
fstream in;
char* tempS;
tempS = new char[25];
in.open("CarHash.dat", ios::binary | ios::in | ios::out);
int x = 2000;
for(int i = 0; i < 6; i++)
tempS[i] = 'a';
int T = 30;
in.seekp(26); //Start of second line
in.write(tempS, 6); //Will not delete anything, will push
in.write(space1, sizeof(space1)); //contents back
in.write((char *)(&T), sizeof(T));
in.write(space1, sizeof(space1));
in.write(tempS,6);
in.write(space1, sizeof(space1));
in.write((char *)&x, sizeof(x));
//Now we will use seekp(0) and write to the first line
//it WILL overwrite the first line perfectly fine
in.seekp(0);
in.write(tempS, 6);
in.write((char*) &x, sizeof(x));
in.write(tempS, 6);
in.write((char *) &T, sizeof(T));
return 0;
}
The CarHashFile is an outside class that creates a binary file full of the following contents when create file is invoked: "Free, " 1900 ", Black, $" 0.00f.
Everything enclosed in quotes was added as a string, 1900 as an int, and 0.00f as a float obviously. I added all of these through write, so I'm pretty sure it's an actual binary file, I just don't know why it only chooses to write over the first line. I know the file size is correct because if I set seekp = 26 it will print at the beginning of the second line and push it down. space was created to easily add the ", " combo to the file, there is also a char dol[1] = '$' array for simplicity and a char nl[1] = '\n' that lets me add a new line to the binary file (just tried removing that binary add and it forced everything onto one row, so afaik, its needed).
EDIT: Ok so, it was erasing the line all along, it just wasn't putting in a new line (kind of embarrassing). But now I can't figure out how to insert a newline into the file. I tried writing it the way I originally did with char nl[1] = { '\n' }. That worked when I first created the file, but won't afterwards. Are there any other ways to add lines? I also tried in << endl and got nothing.
I suggest taking this one step at a time. the code looks OK to me, but lack of error checking will mean any behavior could be happening.
Add error checks and reporting to all operations on in.
If that shows no issues, do a simple seek then write
result = in.pseek(26);
//print result
result = in.write("Hello World",10);
// print result
in.close();
lets know what happens
The end problem wasn't my understand of file streams. It was my lack of understanding of binary files. The newline screwed everything up royally, and while it could be added fine at one point in time, dealing with it later was a huge hassle. Once I removed that, everything else fell into place just fine. And the reason a lot of error checking or lack of closing files is there is because its just driver code. Its as bare bones as possible, I really didn't care what happened to the file at that point in time and I knew it was being opened. Why waste my time? The final version has error checks, when the main program was rewritten. And like I said, what I didn't get was binary files, not file streams. So AJ's response wasn't very useful, at all. And I had to have 25 characters as part of the assignment, no name is 25 characters long, so it gets filled up with junk. Its a byproduct of the project, nothing I can do about it, other than try and fill it with spaces, which just takes more time than skipping ahead and writing from there. So I chose to write what would probably be the average name (8 chars) and then just jump ahead 25 afterwards. The only real solution I could say that was given here was from Emile, who told me to get a Hex Editor. THAT really helped. Thanks for your time.

reading data from files, file name as input

I am writing a program which reads data from different files, which are given as input strings, and stores them into a vector of vectors. The problem I am not able to debug the loop which reads different files. I have closed the ifstream object, cleared the string using empty function... but still it just terminates when i give second file name as input.
I am copying the code for your perusal. It is a function called by another another function. Transposectr transposes a matrix.
code:
vector<vector<float> > store1,store2;
ifstream bb;
string my_string;
float carrier;
vector<float> buffer;
cout<<"enter the file name"<<endl;
getline(cin,my_string);
while (my_string!="end")
{
bb.open(my_string.c_str());
while (!bb.eof())
{
bb >> carrier;
if (bb.peek() == '\n' || bb.eof() )
{
buffer.push_back(carrier);
store1.push_back(buffer);
buffer.clear();
}
else
{
buffer.push_back(carrier);
}
}
bb.close();
buffer.clear();
transposectr1(store1);
storex.push_back(store1[1]);
storey.push_back(store1[0]);
store1.clear();
my_string.empty();
cout<<"done reading the file"<<endl;
cout<<"enter the file name"<<endl;
getline(cin,my_string);
}
I'm really not clear what you are trying to do. But I have one golden ruile when it comes to using istreams:
Never use the eof() function!
It almost certainly does not do what you think it does. Instead you should test if a read operation succeeded.
int x;
while( in >> x ) {
// I read something successfully
}
You might also want to avoid peek() too. Try re-writing your code with this advice in mind.
Add
bb.clear();
after the bb.close() you may get the right thing. bb.close() doesn't reset the cursor I think.
Neil Butterworth is right
Never use the eof() function!
This link explains why.