When displaying an array using a loop, nothing works - c++

Here's my code
void printMatrix(string matrix[][NUMBER_OF_SCORES + 1], int NUMBER_OF_STUDENTS)
{
int row, col;
//this code below is to loop it so it displays all the values
/* for (row = 0; row < NUMBER_OF_STUDENTS + 1; col++)
{
cout << matrix[row][col];
cout << endl;
}
*/
int looper = 0;
// THIS IS THE FORMAT FOR DISPLAYING ONE LINE MAN
//cout << matrix[0][0];
//cout << matrix[0][1];
//this is just some test code to see if it can output certain values right
// cout << matrix[0][0];
// cout << matrix[0][1];
// cout << matrix[0][2];
// cout << matrix[0][3];
}
I have tried everything. I have tried for loops and I've tried while loops. I don't understand why it won't work. It either displays nothing and immediately crashes, or it just keeps "scrolling" down, like it's repeating infinitely but not displaying any text.
There was a while loop I tried that went like this
int looper;
int looper = NUMBER_OF_STUDENTS;
//in this instance, NUMBER_OF_STUDENTS was equal to 28
while (looper > 0)
{
cout << matrix[looper][0];
cout << matrix[looper][1];
looper--;
//i have tried both looper-- and --looper
}
I don't understand why it isn't working at all; it's incredibly frustrating. This is the same program I'm working on as How do I skip the first line of an array when reading from a file?
I feel very guilty asking you guys for so much help, but I'm seriously about to snap here.
EDIT: Here's my entire code.
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
const int NUMBER_OF_STUDENTS = 28;
const int NUMBER_OF_SCORES = 28;
void getData (ifstream& infile, string matrix[][NUMBER_OF_SCORES + 1 ],
int NUMBER_OF_STUDENTS) ;
void printMatrix(string matrix[][NUMBER_OF_SCORES + 1], int NUMBER_OF_STUDENTS);
int main()
{
string birdarray [NUMBER_OF_STUDENTS][NUMBER_OF_SCORES +1 ] ;
// column 0 will hold the student ID.
// row n has the ID and birdarray for student n.
ifstream inData; //input file stream variable
inData.open("one.txt");
if ( !inData)
{
cout << "invalid file name \n";
return 1;
}
// input the birdarray into two-D array birdarray
getData ( inData , birdarray, NUMBER_OF_STUDENTS );
printMatrix(birdarray, NUMBER_OF_STUDENTS);
// return the row number of a searchItem in a particular column.
// if not found, return -1
}
void getData (ifstream& infile,string chart[][NUMBER_OF_SCORES + 1 ],
int student_count)
{
int row, col;
string dummyLine;
getline(infile, dummyLine);
for ( row = 0; row < student_count; row++)
for (col =0; col < NUMBER_OF_SCORES +1 ; col++)
infile >> chart [row] [col] ;
}
void printMatrix(string matrix[][NUMBER_OF_SCORES + 1], int NUMBER_OF_STUDENTS)
{
int row, col;
//this code below is to loop it so it displays all the values
/* for (row = 0; row < NUMBER_OF_STUDENTS + 1; col++)
{
cout << matrix[row][col];
cout << endl;
}
*/
int looper = 0;
// THIS IS THE FORMAT FOR DISPLAYING ONE LINE MAN
//cout << matrix[0][0];
//cout << matrix[0][1];
//this is just some test code to see if it can output certain values right
// cout << matrix[0][0];
// cout << matrix[0][1];
// cout << matrix[0][2];
// cout << matrix[0][3];
}
//prints a labeled listing of students' scores

Here's the normal way to print a table of values
void printMatrix(string matrix[][NUMBER_OF_SCORES + 1], int NUMBER_OF_STUDENTS)
{
for (int row = 0; row < NUMBER_OF_STUDENTS + 1; ++row)
{
for (int col = 0; col < NUMBER_OF_SCORES; ++col)
{
cout << matrix[row][col] << ' ';
}
cout << '\n';
}
}
BUT there are lots of things about your code I don't like. So whether this is right I cannot say. In particular I'm dubious about
1) Why do you have NUMBER_OF_STUDENTS + 1? No obvious need for the + 1, you are probably trying to compensate for a mistake you made elsewhere.
2) Why do you have a matrix of strings? Scores would normally be a number.
I guess the main lesson to learn is to think about exactly what the code you write does. Code isn't a mysterious magic spell, it's a precise series of instructions to the computer. If you had thought about exactly what your code does, followed it through step by step, you would have seen the errors you'd made, and hopefully been able to fix them. You've got to get into that way of thinking.

Your attempts so far would not actually print the entire matrix even if they did not loop continuously. First for the while loop, it's very likely you should be initializing looper at NUMBER_OF_STUDENTS - 1 because if there are NUMBER_OF_STUDENTS rows in the array then the highest element would be NUMBER_OF_STUDENTS - 1. It's possible that you're saying NUMBER_OF_STUDENTS + 1 because of a coding problem elsewhere however. If that's the case I'd try to take care of that issue first for simplicity's sake.
Regarding your for loop
for (row = 0; row < NUMBER_OF_STUDENTS + 1; col++) {
cout << matrix[row][col];
cout << endl;
}
this will loop forever because your stop condition is dependent on row, but row never changes, only col does.
To print all the elements in your matrix you need two loops. Something like this:
for(int row=0; row < numOfRows; row++)
for(int col=0; col < numOfCols; col++)
cout << matrix[row][col];

Related

M.V. Studio C++ - 2D Arrays NOT working with Files

I am new to C++ (so, please forgive me for my C++ atrocities) and am asking for help once again to the helpful people at stack Overflow. I have to create a 2D Array program that reads from 2 files, one named after the Months of the year, and the other being a table of integer values.
I have four functions that break off of main in a switch menu. Function One should display the whole chart with the months going down the first column.
Months && Values. So, basically the months are all in the first column[0] and the values line up adjacent to the months (there will be some added flair to the top most row to give a description of what the values are, but I am sure I can figure that part out)
Then the second function takes all the values in column 1 & 2 (so not [0] because that's the months).
Then my third function takes columns [4] & [5] and adds them up and displays the totals, with the months to left of the values.
My fourth and final function will allow a user to input a given month and display the value display in the 1 first column after the months.
All of my output is never ending 0's.
Please if you could give me any tips/advice/code examples/anything would be greatly appreciated, and I thank you for taking your time to read this garbage code, so that I can hopefully get better at programming! Here is my code, I have not finished it yet since I keep having loop errors that display 0's when I try to ask the program to display one of the four options.
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
// Global Array Size
const int ROWS = 12, COLUM = 9;
int parkChart[ROWS][COLUM];
//Function Prototypes
void displayCodes(const int[][COLUM], int);
int totalRecNonRec(const int[][COLUM], int rows, int total);
int tentRvByMonth(const int[][COLUM], int);
int displayMonth(const int[][COLUM], int, string);
int main()
{
// Define variables
const int DISPLAY = 1, REC_NONREC = 2, TENT_RV = 3, PER_MONTH = 4;
int response, total = 0;
string month;
ifstream inputFile;
inputFile.open("Months.txt");
ifstream inputFile2;
inputFile2.open("Vistors.txt");
cout << "Visitors to National Park" << endl;
// Do While Loop to display the menu
cout << "Enter 1 to display data" << endl;
cout << "Enter 2 to display total number of recreation and non-recreational visitors" << endl;
cout << "Enter 3 to display total tent and RV campers by month" << endl;
cout << "Enter 4 to display the number of recreational visitors for a certain month" << endl;
cout << "Enter any other number to exit" << endl << "\n";
cin >> response;
do
{
switch (response)
{
case(DISPLAY):
{
inputFile;
inputFile2;
displayCodes(parkChart, ROWS);
break;
}
case(REC_NONREC):
{
totalRecNonRec(parkChart, ROWS, total);
break;
}
case(TENT_RV):
{
tentRvByMonth(parkChart, ROWS);
break;
}
case(PER_MONTH):
{
displayMonth(parkChart, ROWS, month);
break;
}
default:
{
// Closes the file and exits
inputFile.close();
exit(0);
}
}
} while (response == 1 || response == 2 || response == 3|| response == 4);
system("pause");
return 0;
}
// Four Functions
// Display Function
void displayCodes(const int parkChart[][COLUM], int ROWS)
{
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLUM; col++)
{
cout << parkChart[row][col] << "\t ";
}
cout << endl;
}
}
// Totals/Display Rec. & Non Rec. Visitors to the park + adds all months for visitors (must equal 3,350,493)
int totalRecNonRec(const int parkChart[][COLUM], int rows, int total)
{
// for loop that adds all the elements in [0-11,1]&&[0-11,2]
for (int col = 0; col < 1; col++)
{
total = 0;
for (int row = 0; row < ROWS; row++)
total += col;
cout << "The total number of recreational and non-recreational visitors: " << total << endl;
}
return total;
}
// Totals/Display Number of Tent & RV Campers by month (needs to add rv + tent) and show all months
int tentRvByMonth(const int parkChart[][COLUM], int rows)
{
for (int row = 0; row < ROWS; row++)
{
int total = 0;
for (int col = 4; col < 5; col++)
{
total += parkChart[row][col];
cout << parkChart[row][col] << " " << (col + 1) << endl;
}
cout << endl;
}
return 0;
}
int displayMonth(const int parkChart[][COLUM], int rows, string month)
{
// Prompt the user to enter a month/Display the number of Rec. Visitors for that month + Failsafe of non-months
// Need a for loop to search for the user given month, and then display the [month, 1]
cout << "Enter the month you want the number of recreational visitors\n";
getline(cin, month);
// search in first column of array
cout << "For the month of " << month << " there were " << " recreational visitors" << endl;
return 0;
}

Can't figure out why only one line of matrix is being read from a file and why I can't pass a 2D array to a function

I've been struggling on this for about an hour now so I'm turning to the almighty entity that is the internet for assistance.
I'm trying to write a program that will A) read a matrix from a txt file in the following format where the first number is the columns (4) and the second number is the rows(3) in the matrix. And each row of numbers corresponds to a row in the matrix.
4 3
1 2 3 4
0 1 2 7
4 1 9 2
and B) calculate the number of ones in the matrix. So the above example would return 3. My code is below.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void count_ones(int matrix[][], int rows, int columns)
{
int count = 0;
for(int i = 0; i < rows; i++)
{
for( int j = 0; j < columns; j++)
{
if( matrix[i][j] == 1)
{ count++;}
}
}
cout << "There are " << count << " ones in this matrix.";
}
int main(int argc, char* argv[])
{
int rows, columns;
string file_name = argv[1];
ifstream reader("m1.txt");
reader >> columns;
reader >> rows;
int matrix[rows][columns];
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < columns; j++)
{
reader >> matrix[i][j];
}
}
cout << columns << " " << rows;
cout << endl;
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++)
cout << matrix[k][l] << " ";
cout << endl;
reader.close();
count_ones(matrix, rows,columns);
return 0;
}
}
Right now I have two issues. The code i'm using to print the matrix I'm reading from the "m1.txt" file is only printing the first two lines and I have absolutely no clue what could be causing this but I'm guessing it has something to do with my ifstream reader.
4 3
1 2 3 4
Secondly, I'm getting a bunch of errors I don't understand when I try to pass my matrix to my count_ones function. I'm not very good with C++ so I would appreciate all the help I can get.
In a comment, you asked
Does anyone have a better way to pass the matrix to the count_ones method?
Don't use
int matrix[rows][columns];
This is not standard C++. It is supported by some compilers as an extension.
Use
std::vector<std::vector<int>> matrix;
You can initialize it with the correct sizes for rows and columns using
std::vector<std::vector<int>> matrix(rows, std::vector<int>(columns));
Change the declaration of count_ones to accept a std::vector<std::vector<in>>.
int count_ones(std::vector<std::vector<in>> const& matrix);
Update its implementation accordingly.
Suggestion for improvement
You can avoid the error of putting the closing } in the wrong place by using helper functions to write the matrix to cout.
std::ostream& operator<<(std::ostream& out, std::vector<int> const& row)
{
for ( int item : row )
out << item << " ";
return out;
}
std::ostream& operator<<(std::ostream& out, std::vector<std::vector<int>> const& matrix)
{
for ( auto const& row : matrix )
out << row << std::endl;
return out;
}
and then use
std::cout << matrix;
in main.
You have done a mistake in the last for loop.
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++)
cout << matrix[k][l] << " ";
cout << endl;
reader.close();
count_ones(matrix, rows,columns);
return 0;
}
}
It should be like this
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++)
cout << matrix[k][l] << " ";
cout << endl;
}
reader.close();
count_ones(matrix, rows,columns);
return 0;
}
Because of this the outer for loop in your code runs only once and prints only first row of matrix.
Edit:
Some more things to correct. You can not use matix[][] as a function parameter, it will through the error multidimensional array must have bounds for all dimensions except the first
You can use double pointer for this work. Change the check ones function declaration to this
void count_ones(int **matrix, int rows, int columns)
replace
int matrix[rows][columns];
with
int **matrix = (int **)malloc(sizeof(int *)*columns);
for(int i=0; i < columns; i++)
*(matrix + i) = (int *)malloc(sizeof(int)*rows);
and the code should work like a charm. And also remove this line, its redundant as file_name is not being used.
string file_name = argv[1];
So, I don't know what the errors are until you post them, but I have an idea why your output is cut off prematurely.
So, to recap, let's look at your code again (the relevant part":
cout << columns << " " << rows;
cout << endl;
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++) /* { */
cout << matrix[k][l] << " ";
/* } */
cout << endl;
reader.close();
count_ones(matrix, rows,columns);
return 0;
}
I've indented it so it's easier to read as well as added the comment braces, just so it's clearer what is getting executed by what.
And now, the output:
4 3
1 2 3 4
Okay, now let's break down what's happening.
cout << columns << " " << rows;
cout << endl;
This is creating the line:
4 3
So far so good, right?
Now, we enter the lop:
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++) /* { */
cout << matrix[k][l] << " ";
/* } */
cout << endl;
and get this:
1 2 3 4
This must be the first line of the matrix.
More code executes:
reader.close();
count_ones(matrix, rows,columns);
which isn't relevant to your problem.
And now this:
return 0;
}
Whoops! We've just left the function by calling return.
The loop will no longer execute because we've terminated it prematurely by returning, only outputting the first line of the matrix.
Solution: Just move the return statement outside the loop like so:
cout << columns << " " << rows;
cout << endl;
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++) /* { */
cout << matrix[k][l] << " ";
/* } */
cout << endl;
reader.close();
count_ones(matrix, rows,columns);
}
return 0;
And that should fix the problem.
Finally, some friendly advice, take Sami Kuhmonen's advice and indent your code. It makes it easier to read and catch things like this.
EDIT: One more point, as R.k. Lohana mentioned, you probably want to pull these lines out of the loop too:
reader.close();
count_ones(matrix, rows,columns);
Like so:
for( int k = 0; k < rows; k++) {
for( int l = 0; l < columns; l++) /* { */
cout << matrix[k][l] << " ";
/* } */
cout << endl;
}
reader.close();
count_ones(matrix, rows,columns);
return 0;
Since you probably only want to do them once and not multiple times.

Triangle pattern

I am trying to get output like
*****
****
***
**
*
But my code is giving the wrong output.
My output is:
Please enter the size: 9
*********
********
*******
******
*****
****
***
**
*
and my code is:
#include<iostream>
using namespace std;
int main (void)
{
int row, column, size;
cout << "Please enter the size: ";
cin >> size;
cin.ignore(999,'\n');
for (row = size; row <= size; row--)
{
if (row <= 0)
{
break;
}
else if (row == size)
{
for (column = 1; column <= size; column++)
{
cout << "*";
}
}
else
{
for (column = row; column <= row; column--)
{
if (column <= 0)
{
break;
}
cout << ' ';
}
for (column = row; column <= row; column--)
{
if (column <= 0)
{
break;
}
cout << "*";
}
}
cout << endl;
}
cout << endl;
cout << "Please press enter to finish...";
cin.ignore(999,'\n');
return 0;
}
I don't know what's wrong and where it is but I am thinking the problem might be in the else loop.
What you are doing here is :
print *s for first line (in amount of size)
if not first line print size - loopCounter spaces then print size - loopCounter *s
As you can see this algorithm can't get you the shape you want. Also why you loop backward and check for none negative value? you don't need it. What you actually want is :
an outer loop to generate columns (prints new line)
an inner loop to generate data of each row
The only thing that important here is how to generate data of each row. as you can see the count of spaces in each row is equal to index of column (starting with 0).
Here's what you can try (I broke inner loop into two loops):
#include<iostream>
using namespace std;
int main(void)
{
int size;
cout << "Please enter the size: ";
cin >> size;
cin.ignore(999, '\n');
for(int column = 0; column < size; ++column)
{
for(int spaces = 0; spaces < column; ++spaces)
{
cout << " ";
}
for(int starts = 0; starts < size - column; ++starts)
{
cout << "*";
}
cout << endl;
}
cout << "Please press enter to finish...";
cin.ignore(999, '\n');
return 0;
}
Try to re-think your problem. You have a lot of complex code to achieve something simple. Your output should look like this:
*****
****
***
**
*
So some things to note about this:
The rows are all the same length!
The only difference is the number of spaces. If we have row, 0 we have 0 spaces, row 4 has 4 spaces.
So with this your code should be simple:
// PSEUDO CODE
for row = 0 to max_rows
for i = 0 to max_rows
if (i < row)
print a space
else
print a *
And that should do it.

Multiplying elements in 2d array

I'm having a problem with the last row of my program. I can't figure out how to multiply the last row by the first row in my program. The multiplication table
works by multiplying the first row by the second, second by third, and so on.
int main() {
int temp;
const int row = 10;
const int col = 5;
int arr[row][col];
int arr2[10][5];
srand(((unsigned)time(0)));
cout << "Original" << endl;
for (int i = 0; i<10; i++) {
for (int j = 0; j<5; j++) {
temp = 1 + rand() % 99;
arr[i][j] = temp;
int arr2 = arr[i][j];
cout << setw(4) << arr2<< setw(5) << " | ";
}
cout << endl;
}
cout << "\n\nMultiplied rows" << endl;
for (int i = 0; i<row; i++) {
for (int j = 0; j < col; j++) {
if (i < 9)
arr[i][j] *= arr[i + 1][j];
else if (i == 9)
cout << setw(4) << arr[i][j]<< setw(5) << " | ";
}
cout << endl;
}
return 0;
}
(it's the last else statement I'm having a problem with)
i tried arr[i][j]=arr[1][i]*arr[9][j]
but that didn't work
First, the answer to your question.
You cant really multiply the last row with the first one because you overwrote it already when arr[i][j] *= arr[i + 1][j]; line executed for i = 0 and j = 0 to 9
The naive solution would be to either store the multiplied numbers in a new array, or don't overwrite the old array and just print the computed values.
Even with that, you will have to make other fixes but I am not really going to do your homework for you.
Just FYI, if you are handing this to an instructor they will call out a number of issues, like the fact that you have const int row and col defined but you only use them once .You should just use those variables; so instead of typing things like 10 , 5 and 9 you should type row, col , row -1.
Also the first arr2 variable is unused and the one in the loop could just as easily not be there and your code would be cout << setw(4) << arr[i][j]<< setw(5) << " | ";
I could go on but I will leave you to find the rest...
Good luck.

C++ Program Debugging

I seem to be having some problems with my program. It compiles fine, but when I get to my first loop it asks me for a positive integer than it asks me again like its suppose too. Than it hops down a blank space and wont run any further until you enter another number which its not suppose to do. But than when you enter a number it goes back and asks me to enter an integer also like its suppose to the problem is, IT will do this infinite amount of times until I quit the program. Any suggestions as to why this is happening?
/* Search the entries of the n X n matrix mat in rowwise order for an entry to item */
#include <iostream>
using namespace std;
int main(void)
{
int n=10, item, row=3, col=3, mat[row][col];
bool found;
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
{
cout << "Enter Positive Integer : ";
cin >> row;
cout << " Enter Positive Integer : ";
cin >> mat[row][col];
}
cout << "Enter a positive integer you want to be searched: ";
cin >> item;
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(mat[row][col] == item)
found = true;
else
found = false;
}
}
if(found==true)
cout << "item found" ;
else
cout << "item found ";
return 0;
}
The line for (int cols = 0; cols < 5; col++) increments the variable col, not cols. Since cols is always 0, the loop will never terminate.
You've done the same in for (int rows = 0; rows < 5; row++). Infinite loops often occur due to typos in loop conditions ;)
I would also like to point out some logic errors during your search:
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(mat[row][col] == item)
found = true;
else
found = false;
}
}
When that loop ends, found will only be true if mat[row-1][col-1] == item (the very last element). Heck, row and col never change in the loop so you are repeatedly checking the exact same element every time! You should also expect even more funky program behavior if you don't get a grasp on your variable names. I strongly recommend adding debug statements to see how your variables are being modified throughout the program (aka: cout << "rows = " << rows << endl;, and cout << "i = " << i << endl;, etc). You're preparing a recipe for disaster when you reuse your variables.
Disclaimer: Reusing variables is not always a bad thing. However, it's best to avoid it until you have a stronger understanding of variables.
In your loop you are incrementing row and col not rows and cols.
It looks to me like you are using the same variable for the loop counter and the user input storage. That is doomed to not do what you want.
Do something like:
for (rowCounter = 0; rowCounter < 3; rowCounter++) {
for (colCounter = 0; colCounter < 3; colCounter++) {
cout << “Give me value for (“ << rowCounter << “,” << colCounter << “) :”;
cin >> mat[rowCounter][colCounter];
}
}
and then the rest of your code
It seems you had a couple of issues.
In the first for loop, you were incrementing the wrong variable (col instead of cols), you also went from 0 to 4 in a 3x3 matrix
you asked the user for 2 numbers then you asked the user to put in a number in the matrix, but its only a 3x3 matrix, the user could easy go out of bounds. I think what you were trying to do was populate the matrix with users number. So i made that change.
In the second for loop, you set found =true, but the loop will keep going, meaning the last number it searched, if it was false, then found = false, also changed it to mat[i][j] instead of mat[row][col], so it doesn't check the same one every time.
both found = true and found = false would return "item found", i think you left off the "not" in the second hard coded string.
I added a pause so you can read the output at the end.
I fixed them and I think this code should do what you want it to now.
#include <iostream>
using namespace std;
int main(void)
{
int n=10, item, row = 3, col = 3;
int mat[3][3];
bool found = false;
int j,k;
for (int rows = 0; rows < 3; rows++)
for (int cols = 0; cols < 3; cols++)
{
cout << "Enter row Integer: ";
cin >>j;
cout << "Enter col Integer: ";
cin >> k;
cout << "Enter Positive Integer : ";
cin >> mat[j][k];
}
cout << "Enter a poistive integer you want to be searched: ";
cin >> item;
int flag = 0;
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(mat[i][j] == item)
{
flag = flag + 1;
}
}
}
if(flag > 0)
found = true;
if(found==true)
cout << "item found" ;
else
{
cout << "item not found ";
}
system("PAUSE");
return 0;
}