Calculating average from imported 2D array - c++

Earlier I asked how to export a 2D array with random numbers as the data.
Link: Converting 2D array to text using c++ functions
Now I'm trying to write a separate program that can calculate the average of each column of that array.
But now I'm having issues with "uninitialized variables" that I'm pretty sure are initialized.
Not really sure what to do from here. Any help would be appreciated!
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main ()
{
string Data, FileName;
int row, col, x, y;
float Matrix[50][50], sum, average;
cout << "Enter the name you gave the matrix file.\n";
cout << "(DO NOT INCLUDE ANY SPACES OR EXTENSIONS!)\n";
cin >> FileName;
FileName = "C:\\Users\\Public\\Documents\\" + FileName + ".ascii";
ifstream Fin(FileName);
if (Fin.is_open())
{
row=0;
while(!Fin.eof())
{
getline(Fin, Data);
stringstream ss(Data);
col=0;
while(ss >> Matrix[row][col])
{
col++;
}
row++;
}
Fin.close();
}
else
cout << "Unable to open file";
for (int y = 0; y < col; y++)
{
for (int x = 0; x < row; x++)
{
sum = sum + Matrix[x][y];
}
average = sum / row;
cout << average << " for column " << col << "\n";
}
system("pause");
return 0;
}
UPDATE:
Solved the "uninitialized variables" error.
But now get "-nan(ind)" when I try to calculate the average.
Here's the new code...
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main ()
{
string Data, FileName;
int row, col;
float Matrix[50][50], sum, average;
sum = 0;
cout << "Enter the name you gave the matrix file.\n";
cout << "(DO NOT INCLUDE ANY SPACES OR EXTENSIONS!)\n";
cin >> FileName;
FileName = "C:\\Users\\Public\\Documents\\" + FileName + ".ascii";
ifstream Fin(FileName);
if (Fin.is_open())
{
row=0;
while(!Fin.eof())
{
getline(Fin, Data);
stringstream ss(Data);
col=0;
while(ss >> Matrix[row][col])
{
col++;
}
row++;
}
Fin.close();
}
else
cout << "Unable to open file";
for (int y = 0; y < row; y++)
{
for (int x = 0; x < col; x++)
{
sum = sum + Matrix[x][y];
}
average = sum / col;
cout << average << "\n";
}
system("pause");
return 0;
}
UPDATE 2:
All I can seem to get is the average for the first column. Can't really work out how to repeat this step. I've tried using do and for loops, but this got me a bunch of errors and losing the only average I get.
If anyone want's to take a look, be warned its very messy...
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main ()
{
string Data, FileName;
int row, col;
float Matrix[50][50], sum, average;
sum = 0;
cout << "Enter the name you gave the matrix file.\n";
cout << "(DO NOT INCLUDE ANY SPACES OR EXTENSIONS!)\n";
cin >> FileName;
FileName = "C:\\Users\\Public\\Documents\\" + FileName + ".ascii";
ifstream Fin(FileName);
if (Fin.is_open())
{
row=0;
while(!Fin.eof())
{
getline(Fin, Data);
stringstream ss(Data);
col=0;
while(ss >> Matrix[row][col])
{
col++;
}
row++;
}
Fin.close();
}
else
cout << "Unable to open file";
double AvgArray[50];
for (int y = 0; y < 50; y++)
{
for (int x = 1; x < 50; x++)
{
if (Matrix[x][y]<0)
{
break;
}
sum = sum + Matrix[x][y];
average = sum / x;
}
if (Matrix[y][y]<0)
{
break;
}
average = AvgArray[y];
}
cout << average << "\n";
system("pause");
return 0;
}

You forgot to set sum to 0 before the second for-loop. In UPDATE 2 you still don't set sum to 0!?
after the first 'for' and before the second ... before you start adding the sums for a column ...
like this
for (int y = 0; y < col; y++)
{
sum = 0;
for (int x = 0; x < row; x++)
{
sum = sum + Matrix[x][y];
}
average = sum / row;
cout << average << " for column " << y << "\n";
}

You gave this:
for (int y = 0; y < 50; y++)
{
for (int x = 1; x < 50; x++)
{
if (Matrix[x][y]<0)
{
break;
}
sum = sum + Matrix[x][y];
average = sum / x;
}
if (Matrix[y][y]<0)
{
break;
}
average = AvgArray[y];
}
In this part of your code, it appears that you are trying to calculate the average at every row in every column (because you put average = sum / x; inside both of the for loops.) I would recommend calculating the sum of the entire column before calculating the average, in order to save code/time. Furthermore, you also put average = AvgArray[y];. Assuming you're trying to fill this array with the averages for each column, you will want to assign average to AvgArray[y] instead. Currently, you never assign any values to AvgArray[].
cout << average << "\n";
Like in the code Zsolt Marx gave, you will want to put this line inside the larger of the two for loops. Otherwise, if you leave it the way you have it, the code will only display the average for the last column calculated.

Related

how read char array(with some space) from file in c++

I am trying to create a maze map in txt file
here is the .txt file
7 7
e%
%% %%
%% %%%
%%% %%%
% %
% %
x % %%
7 and 7 are the number of rows and columns respectively. The spaces are the contents of the array too/
how can I print the spaces in c++
I have tried to code for it but it doesn't work with space:
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
ifstream map("m.txt");
if (!map) {
cout << endl << "Failed to open file";
return 1;
}
int rows = 0, cols = 0;
map >> rows >> cols;
vector<vector<char> > arr(rows, vector<char>(cols));
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
map >> arr[i][j];
}
}
map.close();
cout << "This is the grid from file: " << endl;
for (int i = 0; i < rows; i++)
{
cout << "\t";
for (int j = 0; j < cols; j++)
{
cout << arr[i][j];
}
cout << endl;
}
system("pause");
return 0;
}
first time to ask question hope you guys can get the point thanks a lot for helping
map >> arr[i][j]; is a formatted input. It skips whitespaces. You have to use a different method, e.g. std::basic_istream<CharT,Traits>::get or std::basic_istream<CharT,Traits>::getline
Here is an example with get()
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
ifstream map("m.txt");
if (!map) {
cout << endl << "Failed to open file";
return 1;
}
int rows = 0, cols = 0;
map >> rows >> cols;
// Skip linebreak after line: 7 7
map.ignore();
vector<vector<char> > arr(rows, vector<char>(cols));
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
// Read each char, also whitespaces and linebreaks
arr[i][j] = map.get();
}
// Skip linebreak
map.ignore();
}
map.close();
cout << "This is the grid from file: " << endl;
for (int i = 0; i < rows; i++)
{
cout << "\t";
for (int j = 0; j < cols; j++)
{
cout << arr[i][j];
}
cout << endl;
}
return 0;
}
I had to add two map.ignore(); because the line
map >> arr[i][j];
skipped all linebreaks but
arr[i][j] = map.get();
would read them so we have to manually skip them.
To better clarify my answer (as Yunnosch asked). My point wasn't to solve all problems, only to point at the problem of why the initial code does not work. True, I didn't clarify, I only posted some "new" code.
Original code posted by Cynthia doesn't work because operator>> reads all characters until the first space. My approach was to read the whole line and then break it to the same nested vector as in the initial code. Be aware that this also reads and stores "7 7" line as part of arr
Edit: I had to add a few semicolons for it to compile, and I removed 'reserve' since it can only confuse fresh programmers.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
ifstream map("m.txt");
if (!map) {
cout << endl << "Failed to open file";
return 1;
}
vector<vector<char> > arr;
string line;
// no need for size at start, we can deduce it from line size
while(getline(map, line))
{
vector<char> temp;
for (auto c : line)
temp.push_back(c);
arr.push_back(temp);
}
map.close();
cout << "This is the grid from file: " << endl;
// you can always get number of rows and cols from vector size
// additionally, each line can be of different size
for (int i = 0; i < arr.size(); i++)
{
cout << "\t";
for (int j = 0; j < arr.at(i).size(); j++)
{
cout << arr.at(i).at(j);
}
cout << endl;
}
system("pause");
return 0;
}

Read everything up to a whitespace from a text file

(C++) I've created a function to open the text file and assign the contents to an array. The first 2 elements in the array are the size of the grid. However, if either or both of the first 2 numbers are double digits, it doesnt read them in as double digits. Is there any way of doing this?
int openMap()
{
std::string fileName;
std::cout << "Please enter the file name with extension that you want to open: ";
std::cin >> fileName;
system("CLS");
std::ifstream file(fileName); //OPENS MAP FILE
int tmp;
int i = 0;
if (!file.is_open()) //CHECKS IF THE MAP FILE HAS OPENED CORRECTLY
{
std::cout << "Error Occured!\nCould not open file.";
return 0;
}
while (!file.eof()) //READS THE MAP FILE AND PASSES THE INFORMATION INTO AN ARRAY
{
file >> tmp;
checkNumber(tmp);
if (valid == true) //IF THE CHARACTER IS NOT A NUMBER THEN IT WONT BE PASSED INTO THE ARRAY
{
tmpArray[i] = tmp;
i++;
valid = false;
}
row = tmpArray[1]; //ASSIGNS THE FIRST 2 NUMBERS OF THE MAP FILE TO ROW AND COL VARIABLES
col = tmpArray[0];
}
return row, col;
}
I would assume I have to rewrite
file >> tmp
in some sort of different way, but not sure how.
Is there a way to scan through the text file until it hits a whitespace?
The text file contents looks like this
6 4 0 0 1 0 0 0 2 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 3 0
(the 6 or 4 or both can be double digits instead)
Edit:
for (int j = 0; j < row; j++)
{
for (int k = 0; k < col; k++)
{
_map[j][k] = tmpArray[l];
std::cout << _map[j][k] << " ";
l++;
}
}
There's quite a number of bugs in the code, you should probably use a debugger to step through and identify which parts of your program don't behave as expected.
while(!file.eof())
file >> tmp;
checkNumber(tmp);
if (valid == true) //IF THE CHARACTER IS NOT A NUMBER THEN IT WONT BE PASSED INTO THE ARRAY
{
tmpArray[i] = tmp;
i++;
valid = false;
}
row = tmpArray[1]; //ASSIGNS THE FIRST 2 NUMBERS OF THE MAP FILE TO ROW AND COL VARIABLES
col = tmpArray[0];
You set row=tmpArray[1] and col = tmpArray[0] every iteration of the loop which is not only unnecessary but also incorrect, especially since row=tmpArray[1] is being executed at i=0 when nothing has been placed in tmpArray[1] yet.
EDIT: This is a lot smaller, less error prone due to less variables and type conversions, and easier to read:
int row,col;
//Add error checking here
cin >> col;
cin >> row;
cout << "Cols: " << col << " Rows: " << row << endl;
vector<vector<int> >_map(row, vector<int>(col,0));
for(int j=0; j < row; j++)
{
for(int k=0; k < col; k++)
{
int tmp;
cin >> tmp;
//Add error checking for tmp
_map[j][k] = tmp;
cout << _map[j][k] << endl;
}
}
There are some problems with your code. First the return type of your function is int but you are returning multiple values. Here is a complete running code which should solve your problem.
#include <iostream>
#include <fstream>
#include <vector>
std::vector< std::vector<int> > openMap() {
std::string fileName;
std::cout << "Please enter the file name with extension that you want to open: ";
std::cin >> fileName;
std::fstream myfile(fileName, std::ios_base::in);
int row, col;
myfile >> row;
myfile >> col;
int a;
std::vector< std::vector<int> > retval;
for (int i = 0; i < row; i++) {
std::vector<int> v1;
for (int j = 0; j < col; j++) {
myfile >> a;
v1.push_back(a);
}
retval.push_back(v1);
}
return retval;
}
int main(int argc, char * argv[])
{
std::vector< std::vector<int> > _map = openMap();
for(int i = 0; i < _map.size(); i++) {
for (int j = 0; j < _map[i].size(); j++) {
std::cout << _map[i][j] << " ";
}
std::cout << std::endl;
}
return 0;
}
I guess that not so many people will be interested. But please see below a possible solution to your problem.
The code uses modern C++ algorithms.
It is very simple and straightforward.
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
// Ask user, to give a filename
std::cout << "Please enter the file name with extension that you want to open: ";
// Get the filename from the user
if (std::string fileName; std::cin >> fileName) {
// Open the file and check, if it is open
if (std::ifstream sourceFile(fileName); sourceFile) {
// Read the number of rows and columns of the matrix
if (size_t numberOfColumns, numberOfRows; sourceFile >> numberOfColumns >> numberOfRows) {
// Create a matrix with the given number of rows and columns
std::vector<std::vector<int>> result(numberOfRows, std::vector<int>(numberOfColumns, 0));
// Read data from the input stream and put it into the matrix
for (size_t i = 0; i < numberOfRows; ++i) {
std::copy_n(std::istream_iterator<int>(sourceFile), numberOfColumns, result[i].begin());
}
// Print result. Go through all lines and then copy line elements to std::cout
std::for_each(result.begin(), result.end(), [](std::vector<int>& c) {
std::copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; });
}
}
else {
std::cerr << "\n*** Error: Could not open source File\n\n";
}
}
return 0;
}

How to open a file in Sudoku?

I am trying to write a program for Sudoku. The Sudoku runs well for my input file. But I want to make some changes that input the file in the compiler. It catches the error like no matching member function for call to 'open'. This is just part of my program because I think my problem is the I/O file. Any help is appreciated! Thanks you!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <string>
using namespace std;
int main()
{
char filename;
ifstream myfile;
//int row,column;
int choice;
cout << "Enter the desired sudoku 4 for (4x4) or 9 for (9x9) : \n";
cin >> choice;
if(choice == 9) {
for(int row = 0; row < 9; row++) // iterating the loop to assign initial dummy values
{
for(int column = 0; column < 9; column++)
{
sudoku[row][column] = 0; // assigining zeros
}
}
cout << "Enter the filename:" << endl;
cin >> filename;
myfile.open(filename); // opening the file mentioned
cout << "The values in the file are :" << endl;
if (myfile.is_open())
{
while (!myfile.eof())
{
for(int row = 0; row < 9; row++) // iterating the loope to get the values form the file
{
for(int column = 0; column < 9; column++)
{
myfile >> sudoku[row][column]; // assigning the values to the grid
cout << sudoku[row][column] << endl; // printing the grid
}
}
}
}
myfile.close(); // closing the file
solvesudoku(0,0);//We start solving the sudoku.
}
else if(choice == 4) {
for(int row = 0; row < 4; row++) // iterating the loop to assign initial dummy values
{
for(int column = 0; column < 4; column++)
{
sudoku1[row][column] = 0; // assigining zeros
}
}
cout << "Enter the filename:" << endl;
cin >> filename;
myfile.open(filename); // opening the file mentioned
cout << "The values in the file are :" << endl;
if (myfile.is_open())
{
while (!myfile.eof())
{
for(int row = 0; row < 4; row++) // iterating the loope to get the values form the file
{
for(int column = 0; column < 4; column++)
{
myfile >> sudoku1[row][column]; // assigning the values to the grid
cout << sudoku1[row][column] << endl; // printing the grid
}
}
}
}
myfile.close(); // closing the file
solsudoku(0,0);//We start solving the sudoku.
}
else {
cout << "Invalid Choice..!!!";
}
return 0;
}
Your filename variable has type char. That is a single integral value that can store one "character".
The compiler is correct when it says that no fstream constructor takes a filename of type char.
You probably meant char[SOME_BUFFER_SIZE], or ideally std::string.
Note that if you use std::string and you move to a C++03 compiler, you'll have to append c_str() when you pass it to the fstream, for historical reasons.

C++ Reading double values into a 2D array from a file containing both strings and doubles

I'm working through a program where I have an input file containing state names, and three separate taxes for each state: sales tax, property tax, and income tax. I'm attempting to read the tax values (read as double variables) into an array of type double. Here is my code:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
double a = 0,
b = 0,
c = 0;
double array[5][3];
string state_name;
ifstream fin;
fin.open("test.dat");
for (; fin >> state_name >> a >> b >> c;)
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 3; j++)
{
fin >> array[i][j];
cout << array[i][j] << "\t";
}
cout << endl;
}
}
return 0;
}
Here is the data file:
TEXAS .0825 .02 -.03
CALIFORNIA .065 .04 .05
MARYLAND .03 .025 .03
MAINE .095 .055 .045
OHIO .02 .015 .02
And from the this, the program outputs the array, except that each position reads -9.25596e+061. I was wondering if this was because the program was trying to read the string into the array. I was also wondering if there was a way to overlook the string in the file line by line so that only the double values are read into the array.
You read in the entire line in the for loop. You don't need to do fin >> array[i][j] later. Instead you should be doing this:
for (int i = 0; i < 5; i++)
{
fin >> state_name;
for(int j = 0; j < 3; ++j)
{
fin >> array[i][j];
cout << array[i][j] << '\t';
}
cout << endl;
if(!fin)
{
// handle an error reading the file
}
}
This should do the job:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
double array[5][3];
string state_name;
ifstream fin;
fin.open("test.dat");
// Read the file row by row
int row =0;
while(fin >> state_name >> array[row][0] >> array[row][1] >> array[row][2]) {
++row;
}
// Print the result
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 3; j++) {
cout << array[i][j] << "\t";
}
cout << endl;
}
return 0;
}
If you allow me to think one step further, you probably prefer to push each row into a vector rather than a static array. Otherwise you need to rewrite your code if the file will have more than 5 rows.

Mean & Variance in c++ with 2d array

+1I have a 2D array in which I need to calculate the mean/average and variance. Problem is that when I do it, I get number bigger than I should. IE: My max value in my 2D array is 256 however I can end up with averages as high as 303.
As such, it is clear that I am calculating mean and variance incorrectly. Can someone tell me where I am going wrong here? Code in entirety below.
Here is one of the files if you would like to try and compile and see the results: http://shawndibble.com/baboon.pgma
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int THRESHOLD = 2048; //random threshold variable to determine when to replace a row.
void optimizeImage(int (*imageFile)[512], int mincol, int maxcol, int row) {
int sum, average;
double temp, variance, elements;
elements = (maxcol-mincol+1)*row;
if(mincol != maxcol) { // if maxcol and mincol are the same. We are on a single row & don't need to do anything.
// Figure out average
for (int i = mincol; i < maxcol; i++) {
for (int j = 0; j < row; j++) {
sum += imageFile[i][j];
}
}
average = sum / elements;
// figure out variance
for (int i = mincol; i < maxcol; i++) {
for (int j = 0; j < row; j++) {
temp += (imageFile[i][j] - average) * (imageFile[i][j] - average);
}
}
variance = temp / elements; //calculate variance
//cout << "var: " << variance << " thresh: " << THRESHOLD << endl;
cout << "rows : " << maxcol-mincol+1 << " | average: " << average << endl;
// if threshold is higher than variance, replace entire row with average
if(THRESHOLD >= variance) {
for(int i = mincol; i < maxcol; i++) { // if quad variance is < THRESHOLD, write whole quad to output array
for (int j = 0; j < row; j++) {
imageFile[i][j] = average;
}
}
cout << "run average" << endl;
// otherwise break in half and repeat.
} else {
int mid = ((maxcol+mincol)/2) ;
optimizeImage(imageFile, mincol, mid, row);
optimizeImage(imageFile, mid+1 , maxcol, row);
}
}
}
int main() {
ifstream inFile;
inFile.open ("baboon.pgma");
if (!inFile) {
cout << inFile << " is a not working for me.";
} else {
//time to read the file,
string line1, line2;
int row, col, maxval;
getline (inFile, line1);
getline (inFile, line2);
inFile >> row;
inFile >> col;
inFile >> maxval;
int imageFile [512][512];
// read each integer and place it into a 2D array
for (int i=0; i < col ; i++) {
for (int j=0; j<row; j++){
inFile >> imageFile[i][j];
}
}
inFile.close();
ofstream dataOut;
dataOut.open ("BaboonOptimized.pgma");
dataOut << line1 << endl << line2 << endl << row << " " << col << endl << maxval << endl;
optimizeImage(imageFile, 0, col, row);
for (int i=0; i < col ; i++) {
for (int j=0; j<row; j++){
dataOut << imageFile[i][j] << " ";
}
}
dataOut.close();
}
return 0;
};
You have not initialized sum and temp.