C++ fstream Won't Find Relative Path - c++

The problem is below. I am using Microsoft Visual Studio and admissions.txt is in the same folder as the .cpp, .h, and .sln files, yet the program can't find the relative path. Explicitly stating the path doesn't work either. I am just concerned with getting the ifstream working right now.
/*
A new aquarium just opened up and your boss would like you to write a short program that allows him / her to calculate the number of tickets sold and money brought in for ticket sales.
There are different types of tickets you can buy : All - Access, Gold, and Silver.
The data for ticket sales will be stored in the file admissions.txt with the following format where the first column represents the ticket cost and the second the number of tickets sold.
150.00 89
56.50 300
45.25 450
The first line indicates that the ticket price is $150.00 and that 89 tickets were sold at that price.Output the total number of tickets sold and the total sale amount for ALL tickets.Format your output with two decimal places.
Sample input file :
226 1761
153 28513
62 35779
*/
include fstream
include iostream
include string
using namespace std;
int main()
{
ifstream inFileData;
string line1;
string line2;
string line3;
inFileData.open("admissions.txt"); //contains sample input
inFileData >> line1;
inFileData >> line2;
inFileData >> line3;
cout << line1;
cout << line2;
cout << line3;
inFileData.close();
system("pause");
return 0;
}

You can use this program to generate a test file. Whereever it generates said file, your input file has to be. In my case, it is relative to the .vcxproj for the VS debugger and in the same directory as the .exe when using the .exe.
#include <iostream>
#include <fstream>
int main() {
std::ofstream file("relative_path_test.txt");
if (file.is_open()) {
file << "Test file";
}
file.close();
return 0;
};

add a system("dir") to your program to see the path to the directory you are in when the program runs. From there you should be able to figure out what the correct path to the file is.

Related

File open failure! reading from a file, c++, xcode

I am having an issue reading from a file in a c++ problem. Please find my code below and tell me what you think. I keep on getting "File open failure!"
Problem:
Write a program that produces a bar chart showing the population growth of Prairieville, a small town in the Midwest, at 20 year intervals during the past 100 years. The program should read in the population figures (rounded tot he nearest 1000 people) for 1900, 1920, 1940, 1960, 1980 and 2000 from a file. For each year it should display the date and a bar consisting of one asterisk for each 1000 people. For example, let's use 3000, 7000,10000, 25000, 29000 and 30000.
Here is an example of how the chart might begin:
PRAIRIEVILLE POPULATION GROWTH
(each * represents 1000 people)
1900 ***
1920 *******
1940 **********
// main.cpp
// Population Chart
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int year,population;
ifstream inputFile;
inputFile.open("People.txt");
//if (inputFile.fail())
if(!inputFile)
{
cout << "File open failure!";
}
cout << "PRAIRIEVILLE POPULATION GROWTH\n" <<endl;
cout << "(each * represents 1000 people)\n" <<endl;
while (inputFile >> population)
{
for (year =1900 ; year<=2020; year += 20)
{
cout<< year;
for (int i = 1; i <= population/1000; i++)
{
cout<<"*";
}
cout<< endl;
}
}
inputFile.close();
return 0;
}
From the tag you put to the question, I think you are using Xcode, right? You need to know where does Xcode output the executable, and your People.txt file needs to be put under the same folder as the executable. In Xcode, goto
Xcode > Preference > Locations
The path shown under "Derived Data", is where Xcode put executable. It's typically ~/Library/Developer/Xcode/DerivedData.
There you will probably find a lot of folders of your projects. Go into the folder corresponds to this project and goto Build/Products/Debug, then you will find your executable. What you can do is put your People.txt there.
OR your can add the full path of your "People.txt" file to your inputFile.open() method.
ifstream open() sets errno on failure. So you may obtain its string representation to output the reason of failure:
cout << "File open failure:" << strerror(errno);
This post was very useful New to Xcode can't open files in c++? the issue is now resolved. Turns out the file was not in the folder containing the generated executable. Thanks :)

C++ edit a binary file with another

Solved! thanks all of you very much. My day has been made!(well morning, its 4am)
I'm trying to write a program in C++ that opens a .dat file in binary and replaces the first 1840 hex characters with that of another .dat file, while leaving the remaining hex values of the first .dat file the same. I have spent about 12 hours on this today and have had little success. I am a beginner programmer, I have taken one semester worth of c++ courses and we did not get to streams.
(it opens a file and everything, but deletes every thing after the new values have been added)
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <cstring>
using namespace std;
int main (){
string filename;
long size;
char* memblock;
cout << " Enter a file to be modded by Mod.dat ";
cin >> filename;
ofstream infile ( filename ,std::ofstream::binary);
//filename: the file that will be opened and changed)
ifstream modFile ("Mod.dat", ifstream::binary);
// (mod.dat is the file that i get the first 1840 hex values from)
modFile.seekg (0,modFile.end);
size = modFile.tellg();
memblock = new char [size];
modFile.seekg (0, ios::beg);
modFile.read (memblock, size);
infile.write(memblock, 1840);
modFile.close();
infile.close();
cout << endl;
return 0;
}
Any help would be greatly appreciated, I hope there is some simple way to do this.
Solved! thanks all of you very much. My day has been made!(well morning, its 4am)
Edit:
You can modidy your file in place with something like :
std::fstream s(my_file_path, std::ios_base::binary);
s.seekp(position_of_data_to_overwrite, std::ios_base::beg);
s.write(my_data, size_of_data_to_overwrite);
std::fstream will not truncate your input file as std::ofstream does.
The other solution is to not use the same file for reading and writing. Use three files :
One for the output file.
One for the First input file.
One for the second input file.
fstream infile ( filename ,std::ofstream::binary); does not keeps the contents of the original file. Everything you write will erase the contents of the file.
Thus, you should:
open the output file
open the "Mod" file, read the first 1840 bytes from the first file, write them into the output file.
open the "main input file" file, move the cursor to 1840, read the remaining data and write it to the output file.
Depending on the "main input file" size, you may want to buffer you read/write operation.
My preferred fix, although Matthieu Rouget's fix does indeed work, is to just add ofstreeam::in to the opening of the input file:
ofstream infile ( filename.c_str(), std::ofstream::binary | ofstream::in);
(I had to use c_str() in my build, as glibc in my version doesn't take std::string as input).
I tested this on my local system (it took a while to realize that mod.dat is actually "Mod.dat"!)
It is probably a good idea to also check that the files actually opened, so something like this after ofstream infile line:
if (!infile)
{
cout << "Couldn't open " << filename << endl;
}
and similar for the modfile line.
And since you go through the effort of figuring out what the first part of the modfile size is, I would suggest that you also USE that for the writing of the file.

C++ Sentinel/Count Controlled Loop beginning programming

Hello all this is my first post. I'm working on a homework assignment with the following parameters.
Piecework Workers are paid by the piece. Often worker who produce a
greater quantity of output are paid at a higher rate.
1 - 199 pieces completed $0.50 each
200 - 399 $0.55 each (for all pieces)
400 - 599 $0.60 each
600 or more $0.65 each
Input: For each worker, input the name and number of pieces completed.
Name Pieces
Johnny Begood 265
Sally Great 650
Sam Klutz 177
Pete Precise 400
Fannie Fantastic 399
Morrie Mellow 200
Output: Print an appropriate title and column headings. There should
be one detail line for each worker, which shows the name, number of
pieces, and the amount earned. Compute and print totals of the number
of pieces and the dollar amount earned.
Processing: For each person, compute the pay earned by multiplying the
number of pieces by the appropriate price. Accumulate the total
number of pieces and the total dollar amount paid.
Sample Program Output:
Piecework Weekly Report
Name Pieces Pay
Johnny Begood 265 145.75
Sally Great 650 422.50
Sam Klutz 177 88.5
Pete Precise 400 240.00
Fannie Fantastic 399 219.45
Morrie Mellow 200 110.00
Totals 2091 1226.20
You are required to code, compile, link, and run a sentinel-controlled
loop program that transforms the input to the output specifications as
shown in the above attachment. The input items should be entered into
a text file named piecework1.dat and the ouput file stored in
piecework1.out . The program filename is piecework1.cpp. Copies of
these three files should be e-mailed to me in their original form.
Read the name using a single variable as opposed to two different
variables. To accomplish this, you must use the getline(stream,
variable) function as discussed in class, except that you will replace
the cin with your textfile stream variable name. Do not forget to code
the compiler directive #include < string > at the top of your program
to acknowledge the utilization of the string variable, name . Your
nested if-else statement, accumulators, count-controlled loop, should
be properly designed to process the data correctly.
The code below will run, but does not produce any output. I think it needs something around line 57 like a count control to stop the loop.
something like (and this is just an example....which is why it is not in the code.)
count = 1;
while (count <=4)
Can someone review the code and tell me what kind of count I need to introduce, and if there are any other changes that need to be made.
Thanks.
//COS 502-90
//November 2, 2012
//This program uses a sentinel-controlled loop that transforms input to output.
#include <iostream>
#include <fstream>
#include <iomanip> //output formatting
#include <string> //string variables
using namespace std;
int main()
{
double pieces; //number of pieces made
double rate; //amout paid per amount produced
double pay; //amount earned
string name; //name of worker
ifstream inFile;
ofstream outFile;
//***********input statements****************************
inFile.open("Piecework1.txt"); //opens the input text file
outFile.open("piecework1.out"); //opens the output text file
outFile << setprecision(2) << showpoint;
outFile << name << setw(6) << "Pieces" << setw(12) << "Pay" << endl;
outFile << "_____" << setw(6) << "_____" << setw(12) << "_____" << endl;
getline(inFile, name, '*'); //priming read
inFile >> pieces >> pay >> rate; // ,,
while (name != "End of File") //while condition test
{ //begining of loop
pay = pieces * rate;
getline(inFile, name, '*'); //get next name
inFile >> pieces; //get next pieces
} //end of loop
inFile.close();
outFile.close();
return 0;
}
Can someone review the code and tell me what kind of count I need to introduce, and if there are any other changes that need to be made.
You need statements that direct output to your output file, just as the assignment said to do. The compiler can't read your mind, and it can't read your homework assignment either. It can only read your code.
You also have a problem with your input statements. The pay rates are not in the input file. All that's in the input file are the workers' names and the number of pieces they produced.

Input from text file, not displaying correctly, why?

Here is some part of my main:
int main() {
Inventory Master;
bool flag;
Customer Bob("Bob", "CreditCard.txt");
Customer Chris("Chris", "CreditCard.txt" );
}
Here is my method:
Customer::Customer( string n, string fileName ) {
name = n;
ifstream Credit;
Credit.open(fileName.c_str(), ios::in);
while( Credit.good() && !Credit.eof() ) {
Credit >> card >> balance >> ws;
cout << card <<"\t" << balance << endl;
}
CreditCard _CC( int card, double balance);
}
Here is my "CreditCard.txt file:
12345 15.00
32564 20.00
The way I wanted the info to display is have line 1 "12345 15.00" assigned to Bob and line 2 assigned to Chris and do that so on and so forth if i make new instances or objects of a customer. However the way I currently implemented it is it keeps assigning "12345 15.00 and 32564 20.00" to both Bob and Chris. I could appreciate the help if someone could SHOW me how to somehow point to certain lines of the text file so Bob is assigned to line 1, Chris to line 2, and more customers to other lines when i add them in the text file.
Everything you're doing to Bob and Chris happens inside the constructor. So, as written, your code says: while the stream is in good condition and it's not the end of the file(key point), write to here.
Well, if you think about it, this will read until the end of the file is reached for each instance of Customer. That's not what you want. I might suggest adding the name as the first field in the data file for each record. You could then search the file for the correct record, assuming you ensure the names are all uniquely defined, then pull the data out string by string. That way it's not reading from the beginning to the end each time. I added "Bob" as the first field on line 1, and "Chris" to line 2 and made string name = "Chris";. So...
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
string tempStr;
string name = "Chris";
ifstream Credit;
Credit.open("Info.txt", ios::in);
while( Credit.good() && !Credit.eof() )
{
getline(Credit, tempStr, ' ');//Reads the first records name field
cout << tempStr << endl;
if(name.compare(tempStr) == 0)//Compares the "name" to the field.
{ //If true they are the same
//Proceed to do reading and assignments with additional getline statements
cout << "Chris was matched the second time around!";
Credit.setstate(ios::eofbit, true);//***Sets eof to true
}
else
{
Credit.ignore(50, '\n');
//That should put Credit in the proper position to read the next name
}
}
}
The way you're doing it will cause problems. The only way that it would work for sure is if you knew where the record was at in the file. What if you had five records? By the time you got to the third one you would have to ignore, or similar, all the fields prior to the one you're working on. Also, it could be handy for a human to read a print out of the data file. Another reason to provide a label(name) to each record. Also, you're apparently using namespace std;, so I did too, but it's frowned upon.
istream.getline() http://www.cplusplus.com/reference/iostream/istream/getline/ could be your answer. Just read one line at a time.
A little example here:
http://www.cplusplus.com/forum/beginner/27799/
Little Example from one of my old homerworks:
ifstream fin(fileName);
char buffer[256];
int count = 0;
if (fin.is_open())
{
while (!fin.eof())
{
fin.getline(buffer, 256);
}
}

Attaching text file to Visual Studio project...?

I'm almost done with a homework assignment but I'm having a hell of a time with one aspect of it. The purpose of the program is to read in a text file, and then do analysis. Now, if I'm on my computer, I can put in the full path of the file and it runs fine.
But it won't run ok if my professor tries to run it. I tried prompting the user to input a full path and that didn't work. I tried attaching the text file to the .exe but I don't think I did it right.
Anyone have any advice?
//int bookinput = 0;
//string whichbook;
//ifstream bookread;
//ifstream bookread(whichbook.c_str());
//cout << "Welcome to the book analysis program.\n";
//cout << "Please type in the full path of the book, remembering to double backslashes: ";
//cin >> whichbook;
//
//if(bookinput == 1){
// bookselect = "1984.txt";
//}
//else if(bookinput == 2){
// bookselect = "conneticutYankeeInKingArthursCourt.txt";
//}
//
//bookread.open(bookselect.c_str());
//bookread.open(whichbook.c_str());
bookread.open(whichbook.c_str());
if(bookread.is_open()){
std::cout << "opening book\n\n";
if(bookread.good()){
cout << "opening of book successful :D";
}
while(bookread.good()){ //reads to end of file
string input;
//getline(bookread, input);
bookread >> input;
//only add alphanumerical strings to the word list
if (isAlphaNumerical(input))
{
words.push_back(input);
}
}
}
This is the problem:
cout << "Please type in the full path of the book, remembering to double backslashes: ";
Double-backslashes are only meaningful to the C++ compiler. When you prompt the user for a path, the compiler isn't involved and double backslashes should NOT be used. (and string input cannot use \t to indicate a tab, etc., unless you implement special processing afterward)
You can keep the source file/exe file and text file in the same folder. Inform your professor to copy the entire folder and run it from there.
On another thought, the Prof. should have his own copy of the text file and he should be giving you instructions on how to locate the file within your program.
This bit of code I'm assuming is where the file path is being entered/decided.
.......
cin >> whichbook;
if(bookinput == 1){
bookselect = "1984.txt";
}
else if(bookinput == 2){
bookselect = "conneticutYankeeInKingArthursCourt.txt";
}
//should'nt this be either one line?
bookread.open(bookselect.c_str());
bookread.open(whichbook.c_str());
So if bookinput is 1 or 2, you're trying to open a file without specifying the path? You could keep the two text files in the same path as the executable and then you have to get the path of the executable and use it with the filename, instead, the easier/crappier route would be, you could hardcode it to a known path
Like:
bookselect = "C:\\Temp\\1984.txt";