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

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 :)

Related

C++ fstream Won't Find Relative Path

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.

C++ Code that manipulates CSV file outputs correctly via Sublime Text Command Palette...but not in Terminal

For my latest lab I was given a fairly basic assignment - take a CSV file with population data and output various details, like the country with the largest population. For the sake of brevity, I've included a truncated version of my code below:
#include <iostream>
#include <fstream>
using namespace std;
struct Country {
string name;
double pop1950;
double pop1970;
double pop1990;
double pop2010;
double pop2015;
};
struct World {
int numCountries;
Country countries[229]; // plugged this value with the number of countries from the CSV file.
} myWorld;
int main()
{
ifstream csvStream;
csvStream.open ("population.csv");
double vpop1950;
double vpop1970;
double vpop1990;
double vpop2010;
double vpop2015;
string conName;
int counter = 0;
while (csvStream >> vpop1950 >> vpop1970 >> vpop1990 >> vpop2010 >> vpop2015)
{
getline(csvStream, conName);
// instantiate a country structure per line.
myWorld.countries[counter].name = conName;
myWorld.countries[counter].pop1950 = vpop1950;
myWorld.countries[counter].pop1970 = vpop1970;
myWorld.countries[counter].pop1990 = vpop1990;
myWorld.countries[counter].pop2010 = vpop2010;
myWorld.countries[counter].pop2015 = vpop2015;
counter++;
// cout << conName << endl;
}
// For task 2, where are going to get the top 3 countries. Let's start with the top country, and repeat the loop below 2 more times.
// Figure out the biggest population.
double placeVal = myWorld.countries[0].pop2015; // use this to compare and store the top 100
string topCon = " ";
for (int i = 0; i < 229; i++)
{
if (placeVal < myWorld.countries[i].pop2015)
{
placeVal = myWorld.countries[i].pop2015;
topCon = myWorld.countries[i].name;
}
}
cout << "The largest country is" << topCon << " which had " << placeVal * 1000 << " people in 2015." << endl; // Multiplied by 1000 as per lab instructions.
return 0;
csvStream.close();
}
When I type Command+Shift+B in sublime text and have the file compile and execute, I get this output:
The largest country is China
which had 1.37605e+09 people in 2015.
[Finished in 0.3s]
Execute that same executable in terminal, and I get the following (on both mac and ubuntu):
The largest country is which had 0 people in 2015.
My actual code is a fair bit longer, and I perform various other calculations in that original version of my program, but the same bug persists - the output shows in sublime text but not in the actual terminal. Any thoughts?
Your program assumes that population.csv is in the current working directory. If the current directory does not contain that file, then that file won't be able to be read in.
SublimeText most likely sets the current directory when executing your program to the directory where that program is located.
When running commands from a terminal, the executed program inherits the current directory from the terminal. For example, if your program is in ~/src/my_program, but the current directory in the terminal is your home directory, then the current directory for your program will be your home directory, not ~/src/my_program.
If you change the current directory in the terminal to the directory where your program is located, then the file should be read in correctly.

C++ copying parts of a file to a new file

I am trying to create a new file with data from two different existing files. I need to copy the first existing file in it's entirety, which I have done successfully. For the second existing file I need to copy just the last two columns and append it to the first file at the end of each row.
Ex:
Info from first file already copied into my new file:
20424297 1092 CSCI 13500 B 3
20424297 1092 CSCI 13600 A- 3.7
Now I need to copy the last two columns of each line in this file and then append them to the appropriate row in the file above:
17 250 3.00 RNL
17 381 3.00 RLA
i.e. I need "3.00" and "RNL" appended to the end of the first row, "3.0" and "RLA" appended to the end of the second row, etc.
This is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
int main() {
//Creates new file and StudentData.tsv
ofstream myFile;
ifstream studentData;
ifstream hunterCourseData;
//StudentData.tsv is opened and checked to make sure it didn't fail
studentData.open("StudentData.tsv");
if(studentData.fail()){
cout << "Student data file failed to open" << endl;
exit(1);
}
//My new file is opened and checked to make sure it didn't fail
myFile.open("file.txt");
if(myFile.fail()){
cout << "MyFile file failed to open" << endl;
exit(1);
}
//HunterCourse file is opened and checked to make sure if didn't fail
hunterCourseData.open("HunterCourse.tsv");
if(myFile.fail()){
cout << "Hunter data file failed to open" << endl;
exit(1);
}
// Copies data from StudentData.tsv to myFile
char next = '\0';
int n = 1;
while(! studentData.eof()){
myFile << next;
if(next == '\n'){
n++;
myFile << n << ' ';
}
studentData.get(next);
}
return 0;
}
I am going bananas trying to figure this out. I'm sure it's a simple fix but I can't find anything online that works. I've looked into using ostream and a while loop to assign each row into a variable but I can't get that to work.
Another approach that has crossed my mind is just to remove all integers from the second file because I only need the last two columns and neither of those columns include integers.
If you take a look at the seekg method of a file-stream, you'll note the second version allows you to implement the location to set an offset from (such as ios_base::end which sets the offset compared to the end of the file. With this you can effectively read backwards from the end of the a file.
Consider the following
int Pos=0;
while(hunterCourseData.peek()!= '\n')
{
Pos--;
hunterCourseData.seekg(Pos, ios_base::end);
}
//this line will execute when you have found the first newline-character from the end of the file.
Much better code is available at this Very Similar question
Another possibility is simply to find how many lines are in the file beforehand. (less fast, but workable), in this case one would simply loop though the file calling getline and increment a count variable, reset to the start, then repeat until reaching the count - 2. Though I wouldn't use this technique myself.

C++ reading certain lines from output file

I am making a program for class that needs to read certain lines from an output file based on what "data set" a person chooses. For example, if a person inputs "1" for the desired data set, I need it to use lines 1 through 8 of the data file (inclusively). If they input "2" for the desired data set, I need the program to use lines 9 through 16 from the data file (inclusively), and if "3", then lines 17 through 24 (inclusively).
Here is the code I have so far-
int main()
{
int latA, latB, latC, latD;
int longA, longB, longC, longD;
int AtoB, BtoC, CtoD, threeFlightTotal, nonStop;
int dataSet;
string cityA, cityB, cityC, cityD;
intro();
cout << "Which data set do you wish to use? 1, 2, or 3? ";
cin >> dataSet;
while(dataSet < 1 || dataSet > 3)
{
cout << "Sorry, that is not a valid choice. Please choose again." << endl;
cin >> dataSet;
}
ifstream dataIn;
dataIn.open("cities.txt");
if (dataIn.fail())
{
cout << "File does not exist " << endl;
system("pause");
exit(1);
}
else
{
cout << "File opened successfully" << endl;
}
dataIn.close();
system("pause");
return 0;
}
Here is my data file-
43.65 79.4
Toronto
40.75 74
New York
33.64 84.43
Atlanta
51.5 0
London
37.78 122.42
San Francisco
47.61 122.33
Seattle
44.88 93.22
Minneapolis
41.88 87.63
Chicago
21.19 157.5
Honolulu
45.31 122.41
Portland
42.2 83.03
Detroit
25.47 80.13
Miami
How would I go about doing this? I've looked at other posts but I am having a hard time understanding how to implement their solutions to mine. Thank you for any help in advance. If I'm not giving enough information let me know.
You can simply skip the unneeded lines:
//here you calculate the amount of lines to skip.
//if dataSet=1 --> linesToSkip=0, if dataSet=2 --> linesToSkip=8...
int linesToSkipt = (dataSet-1) * 8;
//getline Needs a string to load the Content.
//So we don't use the data but wee Need to store it somewhere
std::string helper;
//We use a for Loop to skip the desired amount of lines
for(int i = 0; i < linesToSkip; ++i)
std::getline(dataIn, helper); //Skip the unneeded lines
If you knew the exact length of one line you could simply seek to desired Position. But from your example data set it seems like you don't. So you Need to read the file line by line until you reach the desired Position.

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.