let's say we have a matrix in a matrix.txt file, stored like this:
and we want to transform it into:
Number 8 (first number) means how big will 2D array be. After that it means:
1 is connected to 2 (value of connection is 1, it will always be 1)
1 is connected to 8
3 is connected to 4
And when transformed into 2D dynamical array, we want the value 1 in ARRRAY 0,1...0,7...2,3 and soo on (i didnt use square brackets because stackoverflow read them as links).
int number;
int **a = new int*[number];
for (int i = 0; i<number; i++) {
a[i] = new int[number];
}
for (int i = 0; i<number; i++) {
delete[]a[i];
}
delete[]a;
string line;
ifstream myfile("matrix.txt");
if (myfile.is_open())
{
getline(myfile, line);
istringstream(line)>> number;
while (getline(myfile, line)){
cout << line << '\n';
//HERE I SHOULD TURN THOSE NUMBERS INTO VALUES IN 2D ARRAY
}
myfile.close();
}
So my question is: How do i turn this numbers into matrix in 2d array?
Thank you
The easy way, but possibly not the fastest way, is to write the line into a std::stringstream, then read back out of the stringstream into row, column, and value variables. If you are reading from a file the cost of reading the file in the first place usually dwarfs the cost of parsing the file the slow way. If it matters in your case (and profile the code first to make sure it does) look into manually parsing the file. That said, this basic logic will hold.
while (getline(myfile, line)){
cout << line << '\n';
std::stringstream linestream(line);
int row;
int column;
int value;
if (linestream >> row >> column >> value)
{
a[row-1][column-1] = value;
a[column-1][row-1] = value;// mirror
}
else
{
// handle file formatting error
}
}
Off topic, consider using a matrix class to manage a for you rather than a raw 2D Array. The matrix class here at isocppp.org is good and fast, as well as wrapped in some very good general-purpose advice.
The above code with the isocpp matrix looks like:
while (getline(myfile, line)){
cout << line << '\n';
std::stringstream linestream(line);
int row;
int column;
int value;
if (linestream >> row >> column >> value)
{
a(row-1,column-1) = value;
a(column-1,row-1) = value;// mirror
}
else
{
// handle file formatting error
}
}
Nearly identical and a lot easier to use because you don't have to worry about managing the memory yourself, passing the array dimensions around, or a bit of bad code (such as a[4] = 0;) nuking a row of your array.
Addendum
This code
int number;
int **a = new int*[number];
for (int i = 0; i<number; i++) {
a[i] = new int[number];
}
for (int i = 0; i<number; i++) {
delete[]a[i];
}
delete[]a;
has two serious problems:
a is sized with number, and number hasn't been assigned yet. number could be anything from an instantly fatal negative number (can't have an array with a negative size) to a potentially fatal huge number (Your computer have 9,223,372,036,854,775,807 squared bytes of RAM? Didn't think so.)
It deletes the storage immediately after allocating it. Freeing the memory is a great habit to get into, but it's best to free the memory after using it, not before.
So:
// define `a` here
string line;
ifstream myfile("matrix.txt");
if (myfile.is_open())
{
getline(myfile, line);
istringstream(line)>> number;
// allocate storage for `a` here
while (getline(myfile, line)){
cout << line << '\n';
//line reading code goes here
}
myfile.close();
}
// delete `a` somewhere down here after it's been used.
I suggest you use C++ vector from the STL instead of 2d C array which are unsafe.
You could do something like :
ifstream myfile("matrix.txt");
// Read matrix size
size_t matrix_size = 0; myfile >> matrix_size;
vector<vector<int> > matrix(matrix_size);
for(size_t i=0; i < matrix.size(); ++i) matrix[i].resize(matrix_size);
while( myfile.good() )
{
// Read row,col,val and set matrix value
int row=0, col=0, val=0; myfile >> row >> col >> val;
--row; --col; // Since your indices go from 1 to N
if(row < matrix_size && row >= 0 && col < matrix_size && col >= 0) {
matrix[row][col] = val; matrix[col][row] = val;
}
}
Related
I just started a small project which reads a txt file like this:
4
XSXX
X X
XX X
XXFX
So my question is how to read this and put the labyrinth to 2D char array in C++. I tried to use 'getline' but I just make my code more complex. Do you know if there is an easy way to solve this problem ?
char temp;
string line;
int counter = 0;
bool isOpened=false;
int size=0;
ifstream input(inputFile);//can read any file any name
// i will get it from user
if(input.is_open()){
if(!isOpened){
getline(input, line);//iterater over every line
size= atoi(line.c_str());//atoi: char to integer method.this is to generate the size of the matrix from the first line
}
isOpened = true;
char arr2[size][size];
while (getline(input, line))//while there are lines
{
for (int i = 0; i < size; i++)
{
arr2[counter][i]=line[i];//decides which character is declared
}
counter++;
}
Your error is due to the fact that you are trying to declare an array with a size that is a non-constant expression.
In your case size representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
To solve it you could either leave the array with empty brackets and the size will be automatically deduced by the number of elements you place in it or
you could use std::string and std::vector and then to read the .txt file you could write something like:
// open the input file
ifstream input(inputFile);
// check if stream successfully attached
if (!input) cerr << "Can't open input file\n";
string line;
int size = 0;
// read first line
getline(input, line);
stringstream ss(line);
ss >> size;
vector<string> labyrinth;
// reserve capacity
labyrinth.reserve(size);
// read file line by line
for (size_t i = 0; i < size; ++i) {
// read a line
getline(input, line);
// store in the vector
labyrinth.push_back(line);
}
// check if every character is S or F
// traverse all the lines
for (size_t i = 0; i < labyrinth.size(); ++i) {
// traverse each character of every line
for (size_t j = 0; j < labyrinth[i].size(); ++j) {
// check if F or S
if (labyrinth[i][j] == 'F' || labyrinth[i][j] == 'S') {
// labyrinth[i][j] is F or S
}
if (labyrinth[i][j] != 'F' || labyrinth[i][j] != 'S') {
// at least one char is not F or S
}
}
}
As you can see this vector is already "a kind of" 2D char array only with a lot of additionally provided facilities that allow a lot of operations on its content.
I am trying to read integers from a text file and put them into a dynamic array that will be represented as vectors and matrices for an assigment.
An example of a few lines from the input file:
3#456
33#123456789
The numbers before the pound sign represent the elements of the vector or matrix, so 3# would mean a three element vector and 33# would mean a matrix with 3 rows and 3 columns.
Reading those isn't really a problem as we were told we can assume we know which lines are matrices and which are vectors, however, I have never working with C++ file I/O so I don't know how to iterate through the numbers 4,5,6 and put them into a 3, 9, 12, etc, element dynamically created array. Here's somewhat of a sample of what I'm working with.
int *a;
int size_a;
char x;
ifstream infile("input.txt");
if (infile.is_open())
{
infile >> size_a;
// The x is basically a junk variable used to go past the '#'
// when reading the file
infile >> x;
a = new int[size_a];
}
After that, I have no real idea of how to loop until the end of the line and put the remaining elements in the array. For example in this line, the numbers 4, 5, and 6 would need to be put into the a array, then break from adding elements and go to the next line to work on the next array, which I don't know how to do either. Any ideas?
The below code will do this for you. Note that you do not need to use new here - you should just use a std::vector. In that case, the number before the '#' is unneeded as you do not need to specify the size of the array when you create it.
For that reason I have used new here anyway to show you how to read both parts of the file.
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream file("input.txt");
if(file.good()) {
std::string line;
std::getline(file, line);
std::string::size_type pos = line.find('#');
std::string strSize = line.substr(0, pos);
std::string strValues = line.substr(pos + 1);
int size = 0;
for(char c : strSize) {
if(size == 0)
size = static_cast<int>(c - '0');
else
size *= static_cast<int>(c - '0');
}
int* values = new int[size];
for(int i = 0; i < size; ++i) {
values[i] = static_cast<int>(strValues[i] - '0');
}
std::cout << "Array of size " << size << " has the following values:" << std::endl;
for(int i = 0; i < size; ++i) {
std::cout << values[i] << std::endl;
}
delete[] values;
}
}
I'm getting the following error when I run my code:
Unhandled exception at 0x00F66754 in KSU.CIS308.Project5.exe: 0xC0000005: Access violation writing location 0xFDFDFDFD.
I assume it is due to having memory for the pointer but not what it is pointing too. I have no clue how to assign it though. Here is the code, it is the constructor method for the Matrix objects:
Matrix::Matrix(int row, int col)
{
this->rows = row;
this->cols = col;
this->arr = new int*[row];
for (int i = 0; i < row; i++)
{
this->arr[i] = new int[col];
}
}
The this->arr = new int*[row]; is what is throwing it. It is a pointer to a pointer so that I can store the matrix like a 2-d array. Any help is much appreciated.
I think it is also being thrown later but if I can figure one out the rest should be easy to fix as well.
Arr is declared like this in the header file:
int **arr;
Okay so when debugging I found that col is getting passed 0 which might explain the error.
I thought I calculated the right value for passing it. Here is the main file. I use to strtok's to put everything into a Vector. User input format is: "1 2 3 // 3 2 1" Where "//" is row break.
int main() {
vector<int> v1;
int rowCountA = 1;
int colCountA = 0;
cout << "Enter First Matrix (put // to denote row breaks): ";
char buff[200];
char *token;
char *tok;
scanf("%s", buff);
token = strtok(buff, "//");
while (token != NULL)
{
tok = strtok(token, " ");
while (tok != NULL)
{
v1.push_back(atoi(tok));
tok = strtok(NULL, " ");
colCountA++;
}
token = strtok(NULL, "//");
rowCountA++;
}
A = new Matrix(rowCountA, colCountA/(rowCountA+1));
for (int i = rowCountA; i > 0; i--)
{
for (int k = colCountA; k < 1; k--)
{
A->setElem(i, k, v1.back());
v1.pop_back();
}
}
}
As you've found out, the problem is passing 0 as one of the dimensions, the 2D-array creation is otherwise correct. You shouldn't ever allow col to be 0, worst case scenario (let's say empty input), make it be 1.
Anyway you aren't parsing the input correctly:
scanf("%s") is returning only the first number, because it stops at the first space. Your code should use fgets() instead.
Using C string functions, you should replace your scanf("%s", buff); with:
fgets(buff, sizeof(buff)/sizeof(char), stdin);
But, you can't nest calls to strtok(). When you split the string on // and then call strtok on each token, you can no longer retrieve the next row because it forgets about the tokenizing based on //.
Here is a rough equivalent to the parsing you're doing using C++ i/o (although the code does have some other errors):
string sbuff;
getline(cin, sbuff);
stringstream ss(sbuff); // header file <sstream>
while (ss >> sbuff) {
if (sbuff == "//") {
rowCountA++;
}
v1.push_back(atoi(sbuff.c_str()));
colCountA++;
}
I'm trying to create a mini function using dynamically allocated arrays instead of vectors because I'm trying to figure out how they work exactly.
So basically, the user enters how many number of lines they want, and then after that, they enter in a group of integers/doubles separated by a space. Then, I want the function to calculate the total sum of integers in each line, allocate it into the array.
For example:
3
1 2 3 4
3 2 2 1 //assume each line has the same # of integers (4)
1 4 4 1
Then, if I implemented my function the total of sum would then be 10, 8, 10.
So far, I have this:
int* total //is there a difference if I do int *total ??
int lines;
std::cout << "How many lines?;
std::cin >> lines;
total = new int[lines];
for (int i=0;i<lines;i++)
{
for (int j=0;j<4;j++)
{
total[i] = ? //i'm confused how you add up each line and then put it in the array, then go onto the next array..
}
}
If anything does not make sense, please feel free to ask! Thank you!
you probably will want to set total[i] to 0 right before the inner loop, and then just use operator+= to add anything you get from the std::cin stream.
// ...
total[i]=0;
for (int j=0;j<4;j++)
{
int temp;
cin >> temp;
total[i] += temp;
}
// ...
It could be a bit easier to understand if you first allocated an array to store the values and then added them together.
First of all you need to allocate an array of arrays to store numbers of each line. For example
const size_t COLS = 4;
size_t rows;
std::cout << "How many lines? ";
std::cin >> rows;
int **number = new int *[rows];
for ( size_t i = 0; i < rows; i++ )
{
number[i] = new int[COLS];
}
int *total = new int[rows];
// or int *total = new int[rows] {}; that do not use algorithm std::fill
std::fill( total, total + rows, 0 );
After that you should enter numbers and fill each row of number.
There really isn't any difference between doing int* total and int *total (in your example anyways). Personally, I prefer the second one.
As for your question, you would need to set your total to an initial value (in this case you would set it to zero) and then from there just add onto it after getting the value from cin.
With cin, since you have the spaces, it will get each individual number (as you know, I'm assuming) however you probably should (I would) store that number into another variable and then add that variable onto the total for that row.
I think that all makes sense. Hope it helps.
IMHO you can do it using a 2 dimensional array:
int** total;
// ...
total = new int*[lines];
for(int i = 0; i < lines; ++i)
{
total[i] = new int[4]; // using magic number is not good, but who cares?
for(int j = 0; j < 4; ++j)
{
int tmp;
std::cin>>tmp;
total[i][j] = tmp;
}
}
// do sth on total
for(int i = 0; i < lines; ++i)
delete[] total[i];
delete[] total;
I have read columns from a .txt file (the file has at the beginning the number of columns (nCol)) and put the values into an array (float values[nCol][nLin]).
Now, I want to copy the values (ex.: values[0][nLin], values[1][nLin]...) into different float arrays depending on the number of columns.
How can I crate float arrays for each column if the number of columns my change depending on the file I am reading?
//------ Declares Array for values ------//
const int nCol = countCols;
float values[nCol][nLin];
// Fill Array with '-1'
for(int c=0; c<nCol; c++){
for(int l=0; l<nLin; l++) {
values[c][l] = -1;
}
}
//------ Skips the reading of line of values file ------//
getline(inFile, dummyLine);
// reads file to end of *file*, not line
while(!inFile.eof()) {
for(int y=0; y<nLin; y++){
for (int i=0; i<nCol; i++) {
inFile >> values[i][y];
}
i=0;
}
}
const int nValues = countLines;
float Col1[nValues]=-1,
Col2[nValues]=-1,
Col3[nValues]=-1,
Col4[nValues]=-1,
Col5[nValues]=-1;
//------ Put values in specific Arrays ------//
for(int v=0; v<nValues; v++) {
Col1[v] = values[0][v];
Col2[v] = values[1][v];
Col3[v] = values[2][v];
Col4[v] = values[3][v];
Col5[v] = values[4][v];
}
cout << endl;
I want that float Col1[] to be from 1 to nCol, the last one to be float ColnCol[]
The best way IMO would be to use std::vector< std::vector<float> >
You do not need to make different 1D columns as you can manipulate this vector of vector as you want.
Instead you should use std::vector. It is a better choice for dynamic size allocation of a data type.