I am trying to read the contents of a text file into 2D array in C++. The file contains 125 rows with 21 columns of integers (a table of integers). I'm to read this into an array that is 125 rows of 20 columns, skipping column 21 of the file.
I defined the size of the array with variables, but it just reads column 21 into the next row, ignoring the new line. I need it to start each row in the array at the start of the new line from the file but ignore the last item in the table.
I'm not sure if I'm looking for it to skip column 21, or if I'm looking for it to start reading each column at a new line (or both?)
Text file looks like (is this called a matrix?) and it's number separated by 1 space and \n at end.
(The text file was generated by a program to generate rows of 20 numbers and the sum.)
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 93
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 93
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 93
" etc
Other solutions I've found can be difficult for me to understand because people write their variables and functions non-descriptively. Some solutions require advanced methods I'm not supposed to use as well, such as vectors and string manipulation. I have currently learned everything before "pointers" so I can only use solutions I've learned in class. I've learned functions, arrays, search/sort, and basics like operators, loops, variables, etc. I'm not supposed to use vectors for this or string manipulation.
I will (eventually) have to sum the numbers in the array (after I extract the first 20 of each row from the file) so to compare the sum from the array final column to the last integer in each row of the file (which is a sum).
My function is (note: We are using namespace std)
void readArray() {
ifstream infile("tableofintegers.txt");
for (int rowcount = 0; rowcount < ROWS; rowcount++) // row loop
{
for (int colcount = 0; colcount < COLS; colcount++) // column loop
{
infile >> twoDArray[rowcount][colcount]; // read to array
}
}
}
These are variables:
const int ROWS = 125;
const int COLS = 20;
I tried this but got a runtime error
file >> array[row][col];
file.ignore(10, '\n');
The error when I tried file.ignore
C:\path\matrix.exe (process 27316) exited with code -2147483645.
Not only is there an error, but it still "wraps" the read starting line two with the sum (last digit) of line 1.) As you can imagine, as this iterates, it keeps pushing the data over further and further.
I expected for the program to stop reading when it reached the limit of the array columns (20) then continue at the next line, but it didn't. My brain tells me something's not logical about that expectation, yet I have a dissonance or something going on. I can't really wrap my head around it. I also tried file.ignore which I expected would ignore 10 characters after the 20th column up to new line, but it just kicked an error and still wrapped.
Note: I'm printing the array to the console. Here is my code for that.
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
cout << setw(5) << dataArray[row][col];
}
cout << endl;
}
Related
So I encountered this problem of not knowing how to display my random numbers from an array. The display should have 6 columns and I don’t know how about the rows. It is up to the user to enter amount of numbers in the array. Then, rand() will generate the numbers and display them in 6 columns like that (IF USER ENTERED 26 NUMBERS)
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1
I know how to generate the numbers and all that, my problem is only in displaying 1d array in that format. (the output has to compatible with other numbers entered as well not only 26) Any help or pointing in the right direction would be much appreciated.
Thanks,
uszy 123345.
Since you worry about just the output, you can insert a newline character every 6 numbers printed and just stop when you get at the end of the array.
Very often in c++ programming you can make use of extra variables to accomplish something every X number of iterations in a loop. In your case it looks like you want to insert a newline after every 6 numbers. Here is an example of how you would do that in code:
//I am assuming an array called arr with 26 elements already exists
for(int x = 1, i = 0; i < 26; ++i)
{
std::cout << arr[i] << ' ';
x++;
if(x == 6)
{
std::cout << std::endl;
x = 0;
}
}
I'm having trouble figuring out the thought process behind grabbing adjacent vertical elements in a grid. Say I have a 5x5 grid:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
I want to find all adjacent horizontal and vertical adjacent elements and place them into an array. The size of the array is given by the possible number of walls between each element (not counting the outside) e.g.
1 | 2 | 3
--- --- ---
4 | 5 | 6
A graph of 2x3 has 7 walls so the array would look like
1 2
2 3
4 5
5 6 //end of horizontal walls
1 4 //beginning of vertical walls
2 5
3 6
now I've figured out how to find all horizontal walls given rows and cols, where walls is the array I will be storing the result in:
//find all horizontal walls in grid
//2-d array to store the element between the wall (0 1) (1 2)
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols-1; c++){
int s = r > 0 ? -1*r : 0; //after first row always write over last space
walls[r*rows+c+s][0] = r*rows+c;
walls[r*rows+c+s][1] = r*rows+c+1;
}
}
but I'm just getting lost on figuring out how to determine all vertical walls, in a grid of 5x5 for example the vertical walls would be
0 5
5 10
10 15
15 20
1 6
6 11
etc...
here's what I'm currently trying:
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols; c++){
//just print the values at the moment, setting walls properly is easy
std::cout << r*rows+c*cols << " " << r*rows+c*cols+5 << std::endl;
}
}
only problem is this does not reset after the first column to 1, instead it continues on like:
0 5
5 10
10 15
15 20
20 25 //nope, should be 1 6
and suggestions? pseudo-code is much appreciated I would prefer an explanation over code
Ok, just figured out the solution so I'll post all I did:
the problem I had was rows did not recent back to 1 when the inner for loop left and started again, this was because I was still multiplying r by rows, this was actually a really simple fix:
r*rows+c*cols << " " << r*rows+c*cols+5 <<
becomes
r+c*cols << " " << r+c*cols+5 <<
I also was running the inner for loop one too many times so, changing
c < cols should become c < cols-1 and now my output is:
0 5
5 10
10 15
15 20
1 6
6 11
11 17
etc...
Each line of my file consists of an unknown number of integers, which are separated by spaces. I would like to read in each line as a vector of those integers.
Here is an example of such file:
11 3 0 1
4 5 0 3
2 3 4 1
23 4 25 15 11
0 2 6 7 10
5 6 2
1
11
I've been able to read in small amounts of data successfully using the following method (Note that outer_layers is a vector that contains these vectors I'm trying to populate):
for (int i = 0; i < outer_layers.size(); i++)
{
while (in >> temp_num)
{
outer_layers[i].inner_layer.push_back(temp_num);
if (in.peek() == '\n')
break;
}
}
However, when I'm trying to read in larger amounts of data, sometimes it'll read in two lines under one vector. In one of the files, out of 24 lines, it read two-liners on two occasions, so last two vectors did not have any data.
I can't wrap my head around it. Any ideas what I'm doing wrong?
EDIT: Something interesting I've noticed in some of the lines of the trouble-maker file is this:
Let's say there are three lines.
23 42 1 5
1 0 5 10
2 3 11
Line #1 reads in just fine as 23 42 1 5; however, line #2 and #3 get read together as 1 0 5 10 2 3 11.
In Notepad++ they look just fine, each on their own lines. However, in Notepad, they look like this:
23 42 1 51 0 5 10 2 3 11
If you notice, the 5 (last integer of line #1) and 1 (first integer of line #2) are not separated by spaces; however, 10 and 2 are separated by a space.
I've noticed that behavior on any double-read-in lines. If they are separated by a space, then they're both read in. Not sure why this is occurring, considering there should still be a new line character in there for Notepad++ to display the on separate lines, am I right?
I'm not sure how your outer_layers and inner_layers is setup, but you can use std::getline and std::stringstream to fill your vectors something like this :
std::vector< std::vector<int> > V ;
std::vector <int> vec;
std::ifstream fin("input.txt");
std::string line;
int i;
while (std::getline( fin, line) ) //Read a line
{
std::stringstream ss(line);
while(ss >> i) //Extract integers from line
vec.push_back(i);
V.push_back(vec);
vec.clear();
}
fin.close();
for(const auto &x:V)
{
for(const auto &y:x)
std::cout<<y<<" ";
std::cout<<std::endl;
}
I'm trying to transpose a sparse matrix in c++. I'm struggling with the traversal of the new transposed matrix. I want to enter everything from the first row of the matrix to the first column of the new matrix.
Each row has the column index the number should be in and the number itself.
Input:
colInd num colInd num colInd num
Input:
1 1 2 2 3 3
1 4 2 5 3 6
1 7 2 8 3 9
Output:
1 1 2 4 3 7
1 2 2 5 3 8
1 3 2 6 3 9
How do I make the list traverse down the first column inserting the first element as it goes then go back to the top inserting down the second column. Apologies if this is two hard to follow. But all I want help with is traversing the Transposed matrix to be in the right place at the right time inserting a nz(non zero) object in the right place.
Here is my code
list<singleRow> tran;
//Finshed reading so transpose
for (int i = 0; i < rows.size(); i++){ // Initialize transposed matrix
singleRow trow;
tran.push_back(trow);
}
list<singleRow>::const_iterator rit;
list<singleRow>::const_iterator trowit;
int rowind;
for (rit = rows.begin(), rowind = 1; rit != rows.end(); rit++, rowind++){//rit = row iterator
singleRow row = *rit;
singleRow::const_iterator nzit;
trowit = tran.begin(); //Start at the beginning of the list of rows
trow = *trowit;
for (nzit = row.begin(); nzit != row.end(); nzit++){//nzit = non zero iterator
int col = nzit->getCol();
double val = nzit->getVal();
trow.push_back(nz(rowind,val)); //How do I attach this to tran so that it goes in the right place?
trowit++;
}
}
Your representation of the matrix is inefficient: it doesn't use the fact that the matrix is sparse. I say so because it includes all the rows of the matrix, even if most of them are zero (empty), like it usually happens with sparse matrices.
Your representation is also hard to work with. So i suggest converting the representation first (to a regular 2-D array), transposing the matrix, and convert back.
(Edited:)
Alternatively, you can change the representation, for example, like this:
Input: rowInd colInd num
1 1 1
1 2 2
1 2 3
2 1 4
2 2 5
2 3 6
3 1 7
3 2 8
3 3 9
Output:
1 1 1
2 1 2
3 1 3
1 2 4
2 2 5
3 2 6
1 3 7
2 3 8
3 3 9
The code would be something like this:
struct singleElement {int row, col; double val;};
list<singleElement> matrix_input, matrix_output;
...
// Read input matrix from file or some such
list<singleElement>::const_iterator i;
for (i = matrix_input.begin(); i != matrix_input.end(); ++i)
{
singleElement e = *i;
std::swap(e.row, e.col);
matrix_output.push_back(e);
}
Your choice of list-of-list representation for a sparse matrix is poor for transposition. Sometimes, when considering algorithms and data structures, the best thing to do is to take the hit for transforming your data structure into one better suited for your algorithm than to mangle your algorithm to work with the wrong data structure.
In this case you could, for example, read your matrix into a coordinate list representation which would be very easy to transpose, then write into whatever representation you like. If space is a challenge, then you might need to do this chunk by chunk, allocating new columns in your target representation 1 by 1 and deallocating columns in your old representation as you go.
I need to count the frequencies of different integers together in a binary file, how can I do this? I do not wish to convert to string, because that would slow down my program down.. I think...
vector<uint32_t> buf(2);
map<uint32_t, uint32_t> mymap;
if(file.is_open())
{
while (file.read(reinterpret_cast<char*>(&buf[0]), sizeof(uint32_t)*numcols))
{
for(size_t i = 0; i < numcols; ++i)
{
mymap[buf[i]]++; // **---> I need help here**
}
}
}
file.close();
How can I make the key to the map so that it always counts those integers together
Yep.. how many times I see integer pairs consecutively, like how many times (1,2), or (8, 14), or (7,3).
1 2
1 2
7 3
8 14
8 14
8 14
1 2 --> 2 times
7 3 --> 1 time
8 14 --> 3 times
numcols == 2 correct.
One option might be to have the map use pair<uint32_t, uint32_t>s as keys. That way you're explicitly mapping from pairs of uint32_ts to the frequency with which they appear.