calculate sum and avg of the numbers in data file - c++

created a data file to store integers and after the program reads the numbers from the data file, i want to calculate the sum total and average of the numbers and output the total and the average from the second code that reads the data file. what do i need to do to get to that to work?
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//declarations
ofstream outputfile;
int num, integer, sentinel;
//open file for output
outputfile.open("savedata.dat");
//get input from user
cout << "How many integers would you like to enter? " << endl;
cin >> integer;
//use a for loop to get integers from user and store them in the file
for (int i = 0; i < integer; ++i)
{
cout << "Enter integer: " << endl;
cin >> num;
outputfile << num << endl;
}
//close file
outputfile.close();
return 0;
}
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//open file for input and read contents
ifstream inputfile;
int num;
inputfile.open("savedata.dat");
cout << "Contents of file: " << endl;
while (inputfile >> num) // read until end of file
{
cout << num << endl;
}
//close file
inputfile.close();
return 0;
}
tried adding int sum to find sum total but am lost

This is not that complicated. As per definition, the average can be calculated by divdiding the sum of the values by the count of the values.
So, we need to add 2 variables
counter --> To count the values in the file
sum --> To sum up the values
The variables will be defined and initialized to 0 before your read-loop.
In the for loop, we can simply incremented the counter add the newly read value to the sum. After the for loop, we can output all values. But we need to "cast" the values for "counter" and "sum" to a double value, because the average is typically not an integer.
Your second program could then look like the below:
int main()
{
main2();
//open file for input and read contents
ifstream inputfile;
int num;
inputfile.open("savedata.dat");
cout << "Contents of file: " << endl;
int counter = 0;
int sum = 0;
while (inputfile >> num) // read until end of file
{
cout << num << endl;
sum += num;
++counter;
}
//close file
inputfile.close();
cout << "\nNumber of value: " << counter << "\tSum: " << sum << "\t\tAverage: " << (double)sum/(double)counter << '\n';
return 0;
}

Related

Using sentinel values and counter control to get data from a file

I am trying to allow the user to select which file to open then use either a sentinel value or counter control to get all the values from the selected file. The code I have just outputs:
There are 0 values in the file.
The values in the file are: -1206517578
The average is -inf
Which is not true as there are 10 numbers in each file and they are all less than 9. I have been staring at this and can't figure out what is wrong.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main() {
char fileSel;
double numValues = 0; //# of values in list
int values; //numbers in list
double avg = values / numValues;
int counter = 10;
const int SENTINAL_VALUE = -9999;
//Which file would you like to open?
cout << "Which file would you like to open?" << endl;
//1. Counter Controlled
cout << "1. Counter Controlled" << endl;
//2. Sentinel Controlled
cout << "2. Sentinel Controlled" << endl;
//Input file
cin >> fileSel;
//loop file selected
//counter controlled
while (fileSel == 1){
//open and check file
ifstream inFile;
inFile.open("counter_controlled.txt ");
if (inFile.fail()) {
cerr << "Could not open input file" << endl;
return -1;
}
while (numValues <= counter) {
inFile >> values;
numValues += 1;
}
inFile.close();
}
//sentinal
while ( fileSel == 2) {
//open and check file
ifstream inFile;
inFile.open("sentinel_controlled.txt");
if (inFile.fail()) {
cerr << "Could not open input file" << endl;
return -1;
}
//get values until
while (inFile >> values);
numValues += 1;
if (values == SENTINAL_VALUE){
cout << "There are " << numValues << " values in the file." << endl;
cout << "The values in the file are: " << values << endl;
//The average is 4.93.
cout << "The average is " << avg << endl;
}
inFile.close();
}
//The values in the file are:
cout << "There are " << numValues << " values in the file." << endl;
cout << "The values in the file are: " << values << endl;
cout << "The average is " << avg << endl;
return 0;
}
Starting with just these 3 lines of code:
double numValues = 0; //# of values in list
int values; //numbers in list
double avg = values / numValues;
at this point avg is UNINITIALIZED divided by ZERO, which is not good in multiple ways. I'd think the compiler would have a lot to say about this.
values actually has to be accumulated before its average can be calculated, and values is never accumulated into anything, you just read it in over and over.
...C++ is imperative, not declarative like Excel.
In addition to dirck's observation that you are computing the results before you have the data, there is much more wrong with it.
You are reading the same value over and over, not making a collection of values and not summing the values read.
while (inFile >> values);
has nothing to do with stopping at the sentinel, and the following block of code will test the last value read (only), which is the last value in the file.

String doesn't want to store a 2700 character word

I'm trying to make a program that prints all the numbers from 100-999. After that you get to choose how many numbers you want to find. Then you type the number's position and it will be outputed.
There is one problem. The string, named str, stops storing at the number 954.
Here's the code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
//Prints to myFile the numbers from 100 to 999 without a space in between. Like this: 100101102...999
ofstream myFile("numere.txt");
for(int i = 100; i <= 999; i++)
myFile << i;
//Makes the string str to store the line: 100101102103...999. But only stores until 954 (100101102..954)
ifstream myFileRead("numere.txt");
string str;
while(getline(myFileRead, str))
cout << str << endl;
//Ouputs the lenght that should be 2700 but is instead 2565
cout << endl;
cout << "String legth: " << str.size() << endl;
cout << endl;
int n, k;
cout << "Enter how many numbers do you want to find: ";
cin >> n;
for(int i = 1; i <= n; i++){
cout << "Enter number position(it starts from 0) : ";
cin >> k;
cout << "Here's the number on position " << k << ": " << str.at(k);
cout << endl;
}
system("pause>0");
}
Thanks for your attention. I’m looking forward to your reply.
C++ streams are buffered. When you use << to write to a file it is not immediately written to the file.
Try to close or flush the ofstream before you read from it:
myFile.close(); // or...
myFile.flush();
For more details I refer you to flush() and close().
PS: Actually it is rather rare that you need to close a fstream explicitly. You wouldn't need to do it when you used seperate functions for writing and reading:
void write_to_file() {
std::ofstream myFile("numere.txt");
//...
}
void read_from_file() {
std::istream myFile("numere.txt");
//...
}
Because the destructor of ofstream already closes the file.

Segmentation fault when accessing a structure

The program works all the way up until it checks for the name the user enters. When you enter the name you wish to search for in the array of structures that have been imported from a file full of customer info) it comes back segmentation fault core dumped. This puzzles me.
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
struct AccountsDataBase{
char name[50];
string email;
long int phone;
string address;
};
#define MAX 80
AccountsDataBase * account = new AccountsDataBase[MAX];
void readIn(ifstream& file){
int i=0;
while(!file.eof()){
file >> account[i].name >> account[i].email >> account[i].phone >> account[i].address;
}
}
void getAccount(){
char userPick[50];
char streamName[50];
cout << " What account will we be using? " << endl;
cin.getline(streamName, 50);
for(int i=0; strcmp(account[i].name, streamName)!=0; i++){
if( strcmp(account[i].name, streamName)==0){
cout << "\n\n FOUND IT!! \n\n";
cout << account[i].name << "\n" << account[i].email << "\n" << account[i].phone << "\n" << account[i].address << endl;
}
}
}
int main(){
ifstream file;
file.open("2.dat"); //opens data account records text
readIn(file);
getAccount();
delete account;
return 0;
}
Your loop keeps reading everything into the initial element of the array:
while(!file.eof()){
file >> account[i].name >> account[i].email >> account[i].phone >> account[i].address;
}
because the value of i is never incremented. You can convert this to a for loop, like this:
for (count = 0 ; count < MAX && !file.eof() ; count++) {
file >> account[count].name >> account[count].email >> account[count].phone >> account[count].address;
}
Note that I changed i to count:
AccountsDataBase * account = new AccountsDataBase[MAX];
int count = 0;
This will help you solve another problem - determining when the array ends in the getAccount function. Currently, you assume that the record is always there, so the outer loop keeps going on. Now that you have count, you could change the loop like this:
for(int i=0; i < count && strcmp(account[i].name, streamName)!=0; i++){
if( strcmp(account[i].name, streamName)==0){
cout << "\n\n FOUND IT!! \n\n";
cout << account[i].name << "\n" << account[i].email << "\n" << account[i].phone << "\n" << account[i].address << endl;
break;
}
}
if (i == count) {
cout << "Not found." << endl;
}

Using C++ Fstream to output numbers from text file - Need help separating lines

I need to create a program that takes integers from a text file, and outputs them, including the number, lowest number, largest number, average, total, N amount of numbers, etc. I can do this just fine with the code below, but I also need to process the text per line. My sample file has 7 numbers delimited with tabs per row, with a total of 8 rows, but I am to assume that I do not know how many numbers per row, rows per file, etc. there are.
Also, for what it's worth, even though I know how to use vectors and arrays, the particular class that I'm in has not gotten to them, so I'd rather not use them.
Thanks.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
int num;
int count = 0;
int total = 0;
int average = 0;
string str = "";
int numLines = 0;
int lowNum = 1000000;
int highNum = -1000000;
ifstream fileIn;
fileIn.open("File2.txt");
if (!fileIn) {
cout << "nError opening file...Closing program.n";
fileIn.close();
}
else {
while (!fileIn.eof()) {
fileIn >> num;
cout << num << " ";
total += num;
count++;
if (num < lowNum) {
lowNum = num;
}
if (num > highNum) {
highNum = num;
}
}
average = total / count;
cout << "nnTotal is " << total << "." << endl;
cout << "Total amount of numbers is " << count << "." << endl;
cout << "Average is " << average << "." << endl;
cout << "Lowest number is " << lowNum << endl;
cout << "Highest number is " << highNum << endl;
fileIn.close();
return 0;
}
}
One way to deal with the individual lines is to skip leading whitespaces before reading each value and to set the stream into fail-state when a newline is reached. When the stream is good after skipping and reading a value, clearly, there was no newline. If there was a newline, deal with whatever needs to happen at the end of a line, reset the stream (if the failure wasn't due to reaching eof()) and carry on. For example, the code for a loop processing integers and keeping track of the current line could like this:
int line(1);
while (in) {
for (int value; in >> skip >> value; ) {
std::cout << "line=" << line << " value=" << value << '\n';
}
++line;
if (!in.eof()) {
in.clear();
}
}
This code uses the custom manipulator skip() which could be implemented like this:
std::istream& skip(std::istream& in) {
while (std::isspace(in.peek())) {
if (in.get() == '\n') {
in.setstate(std::ios_base::failbit);
}
}
return in;
}

File pointer movement for getline

I have got an input file with following data
2
100
2
10 90
150
3
70 10 80
Now, I am able to read till 4th line ( 10 90) but when reading 5th line(150), the file pointer seems to be stuck at 4th line. I have tried infile.clear() just incase. How do I make sure that file pointer is moving correctly or position it at next line? Appreciate your feedback.
-Amit
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
int main(void) {
int cases;
int total_credit=0;
int list_size=0;
string list_price;
//Read file "filename".
ifstream infile;
infile.open("A-large-practice.in",ifstream::in);
if(!infile.is_open()) {
cout << "\n The file cannot be opened" << endl;
return 1;
}
else {
cout<<"Reading from the file"<<endl;
infile >> cases;
cout << "Total Cases = " << cases << endl;
int j=0;
while (infile.good() && j < cases) {
total_credit=0;
list_size=0;
infile >> total_credit;
infile >> list_size;
cout << "Total Credit = " << total_credit << endl;
cout << "List Size = " << list_size << endl;
//cout << "Sum of total_credit and list_size" << sum_test << endl;
int array[list_size];
int i =0;
while(i < list_size) {
istringstream stream1;
string s;
getline(infile,s,' ');
stream1.str(s);
stream1 >> array[i];
//cout << "Here's what in file = " << s <<endl;
//array[i]=s;
i++;
}
cout << "List Price = " << array[0] << " Next = " << array[1] << endl;
int sum = array[0] + array[1];
cout << "Sum Total = " << sum << endl;
cout <<"Testing" << endl;
j++;
}
}
return 0;
}
The problem is that you're using ' ' (space) as your "line terminator" for getline. So when you're reading the numbers on line 4 into the string s, the first one will be "10" and the second will be "90\n150\n3\n70" -- that is, everything up to the next space. This is almost certinaly not what you want and is leading to your confusion about where you are in the file. The next number you read will be 10, leading you to think you're on line 4 when in fact you're on line 7.
edit
The easiest way to fix this is probably to not use getline at all and just read ints directly from the input:
while (i < list_size)
infile >> array[i++];
This ignores the newlines altogether, so the input might as well be all on one line or split between lines randomly, but as you have an initial number that tells you how many numbers to read, that's just fine.