I posted something on this last night, but I have decided to change my approach slightly as I wasn't fully understanding the code I was trying to use.
I apologise as I know this topic has been done to death but I'd like a little help with the code I've written.
I'm loading a .txt file from my computer with 100 integers in. They are each on new lines.
This is my code so far:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main ()
{
ifstream fout;
ifstream fin;
string line;
ifstream myfile ("100intergers.txt");
if (myfile.is_open())
{
while ( getline(myfile,line) )
{
cout << line << '\n';
}
// Closes my file
myfile.close();
// If my file is still open, then show closing error
if (myfile.is_open())
cerr << "Error closing file" << endl;
exit(1);
}
int y = 0;
int z = 0;
int sum = 0;
double avg = 0.0;
avg = sum/(y+z);
cout << endl << endl;
cout << "sum = " << sum << endl;
cout << "average = " << avg << endl;
// checking for error
if (!myfile.eof())
{
cerr << "Error reading file" << endl;
exit(2);
}
// close file stream "myfile"
myfile.close();
return(0);
}
When I run it I get exit code 1 (as well as a list of my 100 integers).
Which means my if clause isn't the right choice, what's a better alternative?
If I delete that bit completely, it fails to run do to an arithmetic error which I think is 0/0*0
Also I think the code I've written for the .txt file is for words, not numbers, but when I change string to int it really bugs and tells me I have more problems than without.
Finally - after this I want to make an array to calc variance - any tips?
Cheers
Jack
You're reading lines from the file, which you output.
Then you do arithmetic with some variables, all of which have the value zero.
These variables have no connection to the file's contents.
I'll help with the basic loop structure by showing a way to count the numbers in the file:
int main()
{
int value = 0;
int count = 0;
ifstream myfile("100intergers.txt");
while (myfile >> value)
{
count++;
}
cout << "There were " << count << " numbers." << endl;
}
Summing and the rest is left as an exercise.
Related
I am a newbie to C++ and I've got my first assignment. We've got a text file that contains 5 employee names, wages, and hours worked.
And this is my code so that my program could read it.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
using namespace std;
int main()
{
ifstream input;
ofstream output;
string name;
int h;
float w;
int numEployee = 0;
double maxPay, minPay, avgPay;
int gross, adjGross;
//input/output file document path
input.open("/Users/jmduller/Documents/xcode/Lab1/Lab1/Employees.txt");
output.open("/Users/jmduller/Documents/xcode/Lab1/Lab1/Employeesoutput.txt");
//checks if the input file is working
if (input.fail())
{
cout << "Input file failed to open." << endl;
system("pause");
exit(0);
}
//checks if output file is working
if (output.fail())
{
cout << "Output file failed to open." << endl;
system("pause");
exit(0);
}
//prints the name, wage, hours worked of the employees to the output file
while (input >> name >> w >> h)
{
output << setw(5) << name << setw(5) << w << setw(5) << h << endl;
}
system("pause");
return 0;
}
It's reading it properly and giving me the output file that I want but there are missing items. The complete output file should be have the number of employees, max pay, min pay, avg pay, gross pay, and adjusted gross.
Can anyone help me point to the right direction?
Thanks
What you got to do is use some conditions and statements inside your while loop statement (which is reading from the file). Increment your 'numEmployee' variable everytime the loop executes(counts number of entries).
compare the 'w' read to check if it is lower than than the minPay(initialized to something very large) then update minPay otherwise if higher than maxPay(intialized to the least value possible) update maxPay.
Also, add the 'w' to another variable sumPay(initialized to zero) in loop and at the end divide it by numEmployee and you are done.
Just output them into the file before return statement.
I wrote a code which shows a question and 4 answers, ask to choose the correct one, and checks the choice.
Now I would build a table which would contain 6 columns: question/a/b/c/d/correct_answer, and about hundred of lines with my questions. Now I would like my program to randomly choose 5 of a question from table and show it to user.
First question is, can I do my table in Excel and use it than in Visual Studio? If not, what software should I use to do table like this as simply as possible, and how to implement it into my Visual studio project? If yes, how to implement Excel table to my Visual studio project?
Second question is, what simplest code should I write to randomly choose 5 of 100 question from my table?
A code of a question is:
int main()
{
string ans; //Users input
string cans; //Correct answer, comes from table
string quest; //Question, comes from table
string a; // Answers, come from table
string b;
string c;
string d;
int points; //Amount of points
points = 0;
cout << "\n" << quest << "\n" << a << "\n" << b << "\n" << c << "\n" << d << "\n";
cout << "Your answer is: ";
cin >> ans;
if (ans == cans)
{
points = points + 1;
cout << "Yes, it is correct\n";
}
else
{
cout << "No, correct answer is " << cans << "\n";
}
return 0;
}
First Part
You can definitely use Excel to edit your questions and save them. But when you save it, pay attention to the file format.
You want to save your Excel file as a .csv file instead of .xls or .xlsx file. Just go to File -> Save File As -> and change type to .csv.
This is because, reading .csv files is a lot easier. .csv files have each cell in row separated by a comma (,) and each row by a newline ('\n') character.
So, here is a sample Excel file:
After I save it as a .csv file and open it using a text editor (Atom, here), it looks like this:
After, that you only need to write some code to read the file.
This is the code I used (I've added excessive comments to make the code more explicit for beginners):
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;
const int MAX_QUESTIONS = 3;
const int COLUMNS = 6; //Question, Options A, B, C, D, Correct Answer
int main() {
ifstream fp;
fp.open("test.csv");
//If file could not be opened
if (fp.fail()) {
std::cout << "failed to open file" << std::endl;
return 1;
}
//Create a 2D vector of strings to store the values in the file
vector< vector<string> > table;
string line;
//Loop through the entire file (fp)
//Store all values found until I hit a newline character ('\n') in the string line
//This loop automatically exits when the end-of-file is encountered
while (getline(fp, line, '\n')) {
//Create an temporary vector of strings to simulate a row in the excel file
vector<string> row;
//Now I am passing in this string into a string stream to further parse it
stringstream ss;
ss << line;
string part;
//Similar to the outer loop, I am storing each value until I hit a comma into the string part
while (getline(ss, part, ',')) {
//Add this to the row
row.push_back(part);
}
//Add this row to the table
table.push_back(row);
}
//Print out the entire table to make sure your values are right
for (int i = 0; i <= MAX_QUESTIONS; ++i) {
for (int j = 0; j < COLUMNS; ++j) {
cout << table[i][j] << " ";
}
cout << endl;
}
return 0;
}
Second Part
To choose a random number, you can use this code (I borrowed it from another answer)
#include <random>
std::random_device rd; // only used once to initialise (seed) engine
std::mt19937 rng(rd()); // random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // guaranteed unbiased
auto random_integer = uni(rng);
Unlike the old method, this doesn't create bias towards the lower end. However, the new engine is available only in C++11 compilers. So keep that in mind. If you need to use the old method, you can correct the bias by following this answer.
To choose 5 different numbers, each time you generate a random number store it in an array and check whether this number has already been used. This can prevent repetition of questions.
To answer question 1: In Excel, click File>Save As. Choose UTF-16 Unicode Text (.txt), name your file, and save it where your program can access it. In your C++ program, use the fstream library for text files:
#include <fstream>
With the text file in the same directory, use
ifstream fin;
fin.open("FILENAME.txt");
.
.
.
fin >> variable;
.
.
.
fin.close();
To answer question 2: There is a rand() function that returns an integer between zero and RAND_MAX. Then you can use modulus(%) to get a random number in the desired range.
#include <cstdlib> // for srand() and rand()
#include <ctime> // for time()
.
.
.
srand(time(NULL)); // seed the RNG on seconds
.
.
.
var = rand() % ONE_MORE_THAN_MAX;
Here's a quizzer I made to help myself study:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
const char QUESTIONS_FILE_NAME[] = "questions.dat";
const char QUESTION_ANSWER_SEPARATOR = ',';
const char QUESTION_SEPARATOR = '\n';
const short MAX_QUESTION_LENGTH = 300;
const short MAX_ANSWER_LENGTH = 300;
const short MAX_NUM_QUESTIONS = 300;
int main()
{
char questions[MAX_NUM_QUESTIONS][MAX_QUESTION_LENGTH];
char answers[MAX_NUM_QUESTIONS][MAX_ANSWER_LENGTH];
short counter = 0;
short question_choice;
char user_answer[MAX_ANSWER_LENGTH];
ifstream fin;
fin.open( QUESTIONS_FILE_NAME );
srand(time(NULL));
while(fin.getline( questions[counter], MAX_QUESTION_LENGTH-1,
QUESTION_ANSWER_SEPARATOR ))
{
fin.getline( answers[counter], MAX_ANSWER_LENGTH-1,
QUESTION_SEPARATOR );
counter++;
}
fin.close();
cout << endl << "Press CTRL+C to quit at any time" << endl << endl;
while ( counter > 0 )
{
question_choice = rand() % counter;
cout << endl << questions[question_choice] << " ";
cin >> user_answer;
if ( strcmp( user_answer, answers[question_choice] ) )
{
cout << endl << "Incorrect" << endl
<< "It was " << answers[question_choice] << endl;
strcpy( questions[counter], questions[question_choice] );
strcpy( answers[counter], answers[question_choice] );
counter++;
}
else
{
cout << endl << "Correct" << endl;
counter--;
strcpy( questions[question_choice], questions[counter] );
strcpy( answers[question_choice], answers[counter] );
}
}
cout << endl << "You Win!!!!" << endl;
return 0;
}
questions.dat would have data like this
In what year was the Pendleton Civil Service Reform Act enacted?
a.1873
b.1883
c.1893
d.1903,b
In what year did Hurricane Katrina occur?
a.2001
b.2003
c.2005
d.2007,c
I am a newbie here!Although this code completed outputting most of the file, it aborted just before it ended, what went wrong? (2VI3 is a huge data file for coordinates).
Could someone recommend better ways of writing this code?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
string *array = new string[2000];
ifstream iFile("2VI3_SA.txt");
if (!iFile.is_open()) {
cerr << "error: file cannot be opened" << endl;
abort();
}
int x = 0;
while (!iFile.eof()) {
getline(iFile, array[x]);
cout << array[x] << endl;
x++;
}
iFile.close();
cout << x << endl;
ofstream oFile("something.txt");
if (!oFile.is_open()) {
cerr << "error: file cannot be opened" << endl;
abort();
}
for (int i = 0; i < 2000; i++) {
if (i < 818) {
oFile << array[i] << "\n";
}
else if (i<1317){
oFile << array[i].substr(0, 8) << i - 378 << array[i].substr(11, 68) << '\n';
//renumbering all lines below the change
}
else {
oFile << array[i];
}
}
oFile.close();
delete[] array;
return 0;
}
I see at least three problems with the code:
1.
while (!iFile.eof())
This approach to reading a file is always wrong.
2.
An array of 2000 strings gets allocated. There is no explicit check for the actual number of lines read from the input files. It is stated that the file is very big. It is highly likely that there are more than 2000 lines in the file, which will result in a corrupted heap, and undefined behavior.
3.
A more comprehensive review of the code's logic reveals the fact that reading the entire file into a memory buffer is completely unnecessary in the first place! It is perfectly sufficient to read the input file one line at a time, and then write the corresponding output line or lines to the output file, and simply tracking the number of the line currently read. The entire array can be completely eliminated. It's not needed.
I was asked to write a program to open a txt.doc and find the: number of numbers in the list, the sum and the avg. With I compile the code my valves equal zero. I cant find out where I went wrong.
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
ifstream inputFile;
string filename;
int valve;
int aNumber = 0;
int numbers = 0;
double sum = 0.0;
double average = 0.0;
// get file from user
cout << "enter the filename\n";
cin >> filename;
cout << "_________________________________________\n";
// open file
inputFile.open(filename.c_str());
// if loop(if the file successfully opened, process it.)
if (inputFile)
{
while (inputFile >> valve)
{
cout << valve << endl;
}
}
else
{
//display an error message
cout << "Error opening the file\n";
}
cout << "\n";
while (inputFile >> aNumber)
{
numbers++;
sum += aNumber;
}
if (numbers > 0)
average = sum / numbers;
else
average = 0.0;
cout << "Number of numbers: " << numbers << "\n";
cout << "Sum is: " << sum << "\n";
cout << "Average is: " << average;
inputFile.close();
return 0;
}
I don't know why my "numbers" "sum" "average" = zero.
The problem with your code is that you try to read the same file multiple times without getting it off the end: once the stream converts to false it will stay in this state until the stream state is cleared and ignore any real file operations. Also, even if you clear() the file's state it would go immediately back into failure state when an attempt to read data is made because either the next value is misformatted or the end of the stream is reached. You could clear() the state and seekg() to the beginning of the file, though (although I'm not recommending this approach):
while (inputFile >> value) {
...
}
inputFile.clear(); // clear any state flags
inputFile.seekg(0, std::ios_base::beg);
Reading files is generally fairly expensive, not to mention that some sources for "files" can't be read multiple times (for example, a named pipe looks like a file but can be only read once). The cost comes from both the need to access the physical media and the, if that access is fast, the conversion internal to the program. Thus, you are best off to read the file just once and do all of the relevant calculations in the same pass. If combining these operations is deemed unreasonable, you might want to load the content into a container and then operated on the container:
std::vector<double> values{ std::istream_iterator<double>(inputFile),
std::istream_iterator<double>() };
// now use values
In case you'd argue that the file is large: in this case you actually do not want to read the file more than once nor do you want to store it in a container, i.e., you'd process the file in a single pass. For the task at hand doing so is fairly trivial and certainly quite feasible.
I am creating a school project but seems lost at the moment. Can someone help me figure out my problem? Here's what's going on:
I have a program that outputs a random generated numbers in a text file using ofstream. It is generated with a format of two columns (one column is SalePrice & the second column RegularPrice). My problem is creating a code that will do the following:
Create a function that will read the text file generated by the first program
Find the average of the second column ONLY! (Regular Price) then outputs it in the screen
Find the minimum and maximum of the second column ONLY! (Regular Price) then outputs it in the screen
Please help! I need help how to code the ifstream part, I am new to C++ and have tried all the solutions in many books but doesn't seem to work for my needs? :-( Any help will be greatly appreciated! Thanks in advance!
Here's just the section of my code (not the entirety), it is not giving me an error . . . it is simply not giving me anything:
float SalePrice[userInput];
float RegularPrice;
string cPrice;
string readFile;
int count = 0;
ifstream inputFile;
inputFile.open(fileName);
inputFile >> RegularPrice;
// To get you all the lines and place the line from myfile into the line variable
while(!inputFile.eof() && getline(inputFile, readFile))
{
if (count < userInput)
{
inputFile >> readFile;
readFile += cPrice; // Saves the line in STRING.
//display the line we gathered:
cout << cPrice << endl;
}
++count;
}
avgRPrice = RegularPrice / userInput;
cout << endl;
cout << fixed << setprecision (2);
cout << "The average of all the Regular Prices in the file is: " << avgRPrice << endl;
cout << "The minimum Regular Price in the file is: " << minRPrice << endl;
cout << "The maximum Regular Price in the file is: " << maxRPrice << endl;
EDITED:
Here's my current code for finding the max & min:
int maxRPrice(float RPrice[])
{
if (RPrice > maxRPrice)
maxRPrice = RPrice;
return maxRPrice;
}
int minRPrice(float RPrice[])
{
if (RPrice < minRPrice)
minRPrice = RPrice;
return minRPrice;
}
Here is an improved version of your code which works perfectly for me:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int userInput = 2;
float SalePrice[userInput]; //Make an array
float RegularPrice[userInput]; //Make an array
string readFile;
ifstream inputFile;
inputFile.open("yourFile.txt");
if(!inputFile){ //Check wether the file is open
cout<<"Couldn't open file!" << endl;
return -1;
}
// To get you all the lines and place the line from myfile into the line variable
for(int count = 0; !inputFile.eof() && (count < userInput) ; ++count) //Why are you using a while-loop if you need to count the iterations
{
//
inputFile >> SalePrice[count] >> RegularPrice[count]; //loads column SalePrice/RegularPrice into the array at position 'count'
}
float sumRegularPrice = 0;
for(int i=0; i < userInput; i++)
sumRegularPrice += RegularPrice[i];
float avgRPrice = sumRegularPrice / userInput;
cout << endl;
cout << fixed;
cout << "The average of all the Regular Prices in the file is: " << avgRPrice << endl;
//cout << "The minimum Regular Price in the file is: " << minRPrice << endl;
//cout << "The maximum Regular Price in the file is: " << maxRPrice << endl;
system("pause");
return 0;
}
Why are you loading RegularPrice only once? As far as I got your explanation about the file format (you said one column is SalePrice & the second column RegularPrice), every line might have this content:
3.44 5.99
To get the min and max price you can simply write two functions.
With this input:
3.44 5.99
5.54 8.99
I get this output (in the console):
The average of all the Regular Prices in the file is: 7.490000
If you have some questions don't hesitate to ask me.