I am trying to write song information to a text file but nothing is being written to it. The part where I am trying to write the information to onF is running but the file is blank. BTW the code below is part of a recursive function which is the reason for the first few if statements. Any ideas?
void writeToFile(int artist, int album, int song, int nA, int nAl, int nS)
{
ofstream onF("library.txt");
if(song>=nS)
{
album+=1;
song = 0;
}
if(album>=nAl)
{
artist++;
album = 0;
song = 0;
}
if(artist>=nA)
{
onF.close();
return;
}
if(onF.is_open())
{
onF<<artists[artist].artistName<<'#';
onF<<artists[artist].albums[album].albumName<<'#';
onF<<artists[artist].albums[album].songs[song].songName<<'#';
onF<<artists[artist].albums[album].songs[song].songLength<<endl;
cout<<"RAN"<<endl;
}
else
cout<<"File could not be opened."<<endl;
song++;
int numAlbums = artists[artist].numAlbums;
int numSongs = artists[artist].albums[album].numSongs;
writeToFile(artist, album, song, nA, numAlbums, numSongs);
}
Now that I have that working I am having trouble loading the information from the file. It's loading the song info twice with the second time loading everything but the song title. The loop runs twice:
if(inF)
{
while(!inF.eof())
{
getline(inF, newArtist, '#');
getline(inF, newAlbum, '#');
getline(inF, newSong, '#');
inF>>songLength;
cout<<"CALLED"<<endl;
addSong(newArtist, newAlbum, newSong, songLength, numArtists, 0, 0);
}
inF.close();
if(inF.is_open())
cout<<"FAILED TO CLOSE"<<endl;
}
You're truncating the file on entry to the function, so the last call will erase all that has been written.
If you want to append, add the std::ios::app flag
Related
I am trying to pass 5th element of an array(Products[]) of class product to another function. The goal is to update the information of the element Product[5]. Everything seems to work fine except information of Product[5] variable is not updating.
Update: Problem solved by removing while(!EOF), thanks to Remy Lebeau.
The relevant part of Class:
class product
{
private:
float Wholesale_Price = 0;
float Retail_Price = 0;
string Supplier = "N/A";
string Note = "N/A";
int Stock_Amount = 0;
public:
string Name="N/A";
void UpdateRetailPrice(float New_Retail_Price)
{
Retail_Price = New_Retail_Price;
}
void UpdateProductAmount(int New_Stock_Amount)
{
Stock_Amount = New_Stock_Amount;
}
void UpdateWholesale_price(float New_Wholesale_Price)
{
Wholesale_Price = New_Wholesale_Price;
}
};
The relevant part of function:
void ReadProductFromFile(product* Products)
{
string Name, Supplier, Note, Wholesale_Price, Retail_Price, Stock_Amount;//wholesale price, stock amount,price are in string so that
//it becomes easy to use getline(). Use stoi() later for turning string to int.
ifstream ReadProductFromFile;
ReadProductFromFile.open("product.txt");
if (!ReadProductFromFile)
{
perror("Product File failed to open");
return;
}
while(!EOF)
{
/*read product info txt file------>*/
getline(ReadProductFromFile, Name);
getline(ReadProductFromFile, Wholesale_Price);
getline(ReadProductFromFile, Retail_Price);
getline(ReadProductFromFile, Stock_Amount);
/*update product info---------->*/
Products->Name = Name;
Products->UpdateWholesale_price(stoi(Wholesale_Price));
Products->UpdateProductAmount(stoi(Stock_Amount));
Products->UpdateRetailPrice(stoi(Retail_Price));
}
}
Relevant part of Main function:
int main(int argc, char const *argv[])
{
product Products[10];
ReadProductFromFile(Products+5);//is this the right way to send Products[5]? tried &(product[5]) but error
return 0;
}
Input:
Bananas
210
270
310
I made a phonebook program which includes Add and search a contact.
But when I made the delete function, it deleted all the contacts instead of the one I entered.
I know it's a little bit complicated but any ideas?
This is the input in phonebook.txt from which I want to delete a contact:
Barney Hackett 0114543053
Luis Avery 01056633489
Hudson Ramsay 01576633982
Ihe code is:
void DeletePhoneNumber() {
FILE* search, * fp1;
//to receive the enter from system("cls")
char temp;
scanf("%c", &temp);
search = fopen("PHONEBOOK.txt", "r+");
fp1 = fopen("temp.txt", "w");
system("cls");
printf("\t*****DELETE CONTACT*****");
printf("\n\t Enter Name: ");
int length;
length = strlen(SearchName);
int i, y = 0;
//string comparison//
while (fgets(name, 50, search) != NULL) {
fputs(name, fp1);
}
fclose(search);
fclose(fp1);
search = fopen("PHONEBOOK.txt", "w");
fp1 = fopen("temp.txt", "r");
while (fgets(name, 50, search) != NULL) {
fputs(name, search);
}
fclose(search);
fclose(fp1);
remove("temp.txt");
printf("\n\tPRESS ANY KEY TO CONTINUE");
getch();
MainMenu();
}
}
I'll use this "answer" space to give you a partial analysis of your code. You can use it to improve your code.
Basically, your loop is all wrong:
search = fopen("PHONEBOOK.txt", "r+");
while (fgets(name, 50, search) != NULL) {
// ...
while (token != NULL) {
// ...
fclose(search);
search = fopen("PHONEBOOK.txt", "w");
You opened the file in append mode, read from it and now close the file, to open it in a different mode. What will it read on the next fgets in the while loop?
Opening the file in mode "w" for writing will destroy the file. So here is why there are no more entries in your file.
fclose(search);
MainMenu();
At the bottom of the loop you close the file. How can it still read something with fgets in the while loop.
Next you call MainMenu. But I assume this function calls this DeletePhoneNumber function, so you are in a strange loop/recursion. Of course, when you are done with deleting the phone number, you simply return to the main menu, not call it again.
I have a directory Processed_Data with thousands of hists*****_blinded.root files. Each hists*****_blinded.root contains around 15 graphs and histograms in it. My goal is just to overlap 1 specific histogram sc***** from each file to get the final histogram finalhists_blinded.root which will represent all of those overlapped together.
I have tried the following macro:
void final()
{
TCanvas *time = new TCanvas("c1","overlap" ,600,1000);
time ->Divide(1,1);
time ->cd(1);
TH1F *h1 = new TH1F("h1","time" ,4096,0,4096);
ifstream in;
Float_t t;
Int_t nlines= 0;
in.open("Processed_Data", ios::in);
while (1) {
in >> t;
if (!in.good()) break;
h1->Fill(t);
nlines++;
}
in.close();
But I get the blank canvas at the end. The idea is to run each hists file through the code and add each one by one.
As a result, I want to see all those sc***** histograms overlapping so that the spikes in each of them will create a pattern in a finalhists_blinded.root file.
Shouldn't be that complicated, try this:
void overlap()
{
TCanvas *time = new TCanvas("c1", "overlap", 0, 0, 800, 600);
const char* histoname = "sc";
const int NFiles = 100000;
for (int fileNumber = 0; fileNumber < NFiles; fileNumber++)
{
TFile* myFile = TFile::Open(Form("Processed_Data/hists%i_blinded.root", fileNumber));
if (!myFile)
{
printf("Nope, no such file!\n");
return;
}
TH1* h1 = (TH1*)myFile->Get(histoname);
if (!h1)
{
printf("Nope, no such histogram!\n");
return;
}
h1->SetDirectory(gROOT);
h1->Draw("same");
myFile->Close();
}
}
It loops over all Processed_Data/histsXXXXXi_blinded.root files (given their names are Processed_Data/hists0_blinded.root, Processed_Data/hists1_blinded.root, Processed_Data/hists2_blinded.root, ..., Processed_Data/hists99998_blinded.root, Processed_Data/hists99999_blinded.root), opens each of them, grabs a 1D sc histogram, adds it to the canvas, closes the file and moves to the next file.
I am using ifstream to open a file and read line by line and print to console.
Now, I also want to make sure that if the file gets updated, it reflects. My code should handle that.
I tried setting fseek to end of the file and then looking for new entries by using peek. However, that did not work.
Here's some code I used
bool ifRead = true;
while (1)
{
if (ifRead)
{
if (!file2read.eof())
{
//valid file. not end of file.
while (getline(file2read, line))
printf("Line: %s \n", line.c_str());
}
else
{
file2read.seekg(0, file2read.end);
ifRead = false;
}
}
else
{
//I thought this would check if new content is added.
//in which case, "peek" will return a non-EOF value. else it will always be EOF.
if (file2read.peek() != EOF)
ifRead = true;
}
}
}
Any suggestions on what could be wrong or how I could do this.
UPDATE:There's no getfilename(), but there's name() function!
I'm trying to make a simple program to store all filenames in a String array and then show them in the LCD.
Code:
String* list(File root, int len) {
if (!root.isDirectory()) return NULL;
String files[50];
int i = 0;
while (true) {
File f = root.openNextFile();
if (i < 50) files[i] = f.getFilename();
f.close();
i++;
}
len = i;
root.close();
return files;
}
Code to display in LCD:
void displayToLCD(String* files, int len) {
lcd.clear();
lcd.home();
lcd.print("Files on SD:");
for (int i = 0; i < len; i++) {
lcd.setCursor(0, 1);
lcd.print(files[i]);
delay(1000);
}
lcd.clear();
lcd.home();
}
But the problem is that the class File doesn't have the 'getFilename()' function. Is there any way to get the filename?
Please help.
Best regards,
Mateiaru
Just remembered that that on arduino.cc at File section, at openNextFile example, they use File.name()! So there's no getFilename().
Mateiaru
I would recommend that you look at my MP3 FilePlayer.ino example. It accomplishes what you are attempting, but just to the serial port.
Additionally it won't run out of memory, as it does not store the file names into an array or memory. Rather displays them and lets the user select the number. This can also be readily adapted to an up/down arrow menu, for an LCD.
Note that I am using SdFat. It has more functions and attributes that are not made public in standard SD. along with the file.getFilename() .