I am a new in C++ and have difficulties in importing specific data (numbers) from the file.
My input looks like:
Open High Low Close
1.11476 1.11709 1.10426 1.10533
1.10532 1.11212 1.10321 1.10836
1.10834 1.11177 1.10649 1.11139
1.09946 1.10955 1.09691 1.10556
1.10757 1.11254 1.09914 1.10361
1.10359 1.12162 1.10301 1.11595
1.09995 1.10851 1.09652 1.10097
I use the following code which works fine for me to read the second column entirely, however I need to read specific data only. For example the third row/ third column which is 1.10649How can I read specific data? Do I need to use the string to get the row/column and then convert it to int in order to read it in a vector? I am open for any suggestions and would be greatly appreciated if any could help me with this issue.
// Data import 2nd Column
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
int main()
{
const int columns = 4;
vector< vector <double> > data;
ifstream market_data("market_data.txt");
if (market_data.is_open()) {
double num;
vector <double> line;
while (market_data >> num) {
line.push_back(num);
if (line.size() == columns) {
data.push_back(line);
line.clear();
}
}
}
vector <double> column;
double col = 2;
for (double i = 0; i < data.size(); ++i) {
column.push_back(data[i][col - 1]);
cout << column[i] << endl;
}
system ("pause");
return 0;
}
You need to use a integer value for indexing (size_t to be precise), change
for (double i = 0; i < data.size(); ++i) {
to
for( size_t i = 0; i < data.size(); ++i) {
// ^^^^^^
Otherwise everything seems fine from your code sample.
If your numbers will always contain 7 characters (i assume it's not binary file), then you could make this simple.
Use seekg() method of ifstream.
Each number fills 10 characters (7 of number, 3 spaces). So, if you have table ROWS x COLUMNS, then to get specific number, you can do this:
const int ROW_LEN = 4
const int DATA_LEN = 10
...
int row,column;
double num;
std::cin >> row; //assume first row is 0
std::cin >> column //assume first column is 0
marked_data.seekg((column*ROW_LEN + row)*DATA_LEN);
marked_data >> num // here is your number
Thank you for replies.. I have solved the issue. So instead of:
vector <double> column;
double col = 2;
for (double i = 0; i < data.size(); ++i) {
column.push_back(data[i][col - 1]);
cout << column[i] << endl;
}
enough to write:
cout << data[2][2] << endl;
Related
So, I need to make a function that is going to return the chromatic number of a graph. The graph is given through an adjecency matrix that the function finds using a file name. I have a function that should in theory work and which the compiler is throwing no issues for, yet when I run it, it simply prints out an empty line and ends the program.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
int Find_Chromatic_Number (vector <vector <int>> matg, int matc[], int n) {
if (n == 0) {
return 0;
}
int result, i, j;
result = 0;
for (i = 0; i < n; i++) {
for (j = i; j < n; j++) {
if (matg[i][j] == 1) {
if (matc[i] == matc[j]) {
matc[j]++;
}
}
}
}
for (i = 0; i < n; i++) {
if (result < matc[i]) {
result = matc[i];
}
}
return result;
}
int main() {
string file;
int n, i, j, m;
cout << "unesite ime datoteke: " << endl;
cin >> file;
ifstream reader;
reader.open(file.c_str());
reader >> n;
vector<vector<int>> matg(n, vector<int>(0));
int matc[n];
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
reader >> matg[i][j];
}
matc[i] = 1;
}
int result = Find_Chromatic_Number(matg, matc, n);
cout << result << endl;
return 0;
}
The program is supposed to use an freader to convert the file into a 2D vector which represents the adjecency matrix (matg). I also made an array (matc) which represents the value of each vertice, with different numbers corresponding to different colors.
The function should go through the vector and every time there is an edge between two vertices it should check if their color value in matc is the same. If it is, it ups the second vale (j) by one. After the function has passed through the vector, the matc array should contain n different number with the highest number being the chromatic number I am looking for.
I hope I have explained enough of what I am trying to accomplish, if not just ask and I will add any further explanations.
Try to make it like that.
Don't choose a size for your vector
vector<vector<int> > matg;
And instead of using reader >> matg[i][j];
use:
int tmp;
reader >> tmp;
matg[i].push_back(tmp);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Starting with an input file that looks like this:
2 3
2 3 4
4 3 2
I am trying to read this data into a 2D array in C++ (the first row specifying number of rows / cols).
My code currently looks like:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream fin;
fin.open ("dataset.in");
// a matrix
int a_numrows;
int a_numcols;
int a[a_numrows][a_numcols];
fin >> a_numrows >> a_numcols;
cout << a_numrows << " " << a_numcols << endl;
for (int i = 0; i<a_numrows; i++)
{
for (int j = 0; j<a_numcols; j++)
{
fin >> a[i][j];
}
}
cout << a[0][0] << endl;
fin.close();
return 0;
}
However it seems as though in each row of the 2D array, the last row is being stored. Thus when a[0][0] is outputted, it returns 4. This behavior is not how I think things should work coming from other languages.
You must permute these lines:
int a[a_numrows][a_numcols];
fin >> a_numrows >> a_numcols;
to
fin >> a_numrows >> a_numcols;
int a[a_numrows][a_numcols];
I guess this is a mistake of inattention.
That's said, there are safer/better ways to declare/use 2D arrays. Here is a possible example:
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::ifstream fin("dataset.in");
size_t n_rows, n_cols;
fin >> n_rows >> n_cols;
using T = int;
std::vector<T> array(n_rows * n_cols);
array.assign(std::istream_iterator<T>(fin), std::istream_iterator<T>());
fin.close();
//-----
for (size_t i = 0; i < n_rows; i++)
{
for (size_t j = 0; j < n_cols; j++)
{
std::cout << array[i * n_cols + j] << "\t";
}
std::cout << endl;
}
return 0;
}
Output:
g++ reader.cpp; ./a.out
2 3 4
4 3 2
Remember that when doing numerical computations it is generally better to store all the numbers into a contiguous memory chunk (like it is done in std::vector). In this situation it is easier for the compiler to vectorize your code.
To access components use:
[i*n_cols+j]: row-major (C-style) -> the given example,
more efficient to loop in this order: for i { for j ... } }
[j*n_rows+i]: column-major (Fortran-style) -> compatible with Blas & Lapack,
more efficient to loop in this order for j { for i ... } }
To declare an array in C++, the size has to be known at compile time. I.e. you can't pass a_numrows and a_numcols as array-dimensions as these are runtime values. For such an approach I would use a std::vector:
vector<vector<int>> a;
//... read a_numrows and a_numcols
a.resize(a_numrows); //resize creates #a_numrows empty columns
for(int i = 0; i < a_numrows; ++i)
{
for(int j = 0; j < a_numcols; ++j)
{
int value; fin >> value;
a[i].push_back(value); //access the ith row and add a new column with value inside
}
}
For a project I am currently working on, I have to read from a file and depending on the certain character in the file, output either a 1 or 0 to an array.
So here is an example of file input:
* * *
* * *
** ** **
*** *
And here is the function I have written to handle this:
void input (int cellGrid[][MAX]) //takes info from a .txt and puts it into an array
{
ifstream infile; //declare a file variable
int row;
int column;
int number;
infile.open("life.txt"); //open a file
while(infile>>row>>column) { //inserts bacteria places into array
cout << row << " " << column << endl;
cellGrid[row][column]=1; //makes it equal one if bacteria is present
}
infile.close(); //closes file
}
My thinking was that the function needs to see if there is a character that exists and if so, place a 1 in its respective position ([row][column]) in the array. However with this current code, nothing is input into my array.
Generally in C++ use std::vector wherever possible.
Array example:
You have to go through the file and record position of each *. Then set it to 1 for that position. Something like the following (we use getline and i as counter for rows, then we loop through the line using j as counter for columns):
#include <fstream>
#include <string>
using namespace std;
void input(int cellGrid[][100]) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
Vector example #1:
Here you can find a solution using std::vector. It will be always in a size rows x columns. One thing it requires is to pass default constructed vector and not constructed with vector(size_type count); c-tor. You can write your own version that doesn't have this problem:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void input(vector<vector<int>> &cellGrid) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
cellGrid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
int main() {
vector<vector<int>> cellGrid;
vector<vector<int>> cellGrid2(100);
input(cellGrid);
//input(cellGrid2); - THIS WILL THROW AN EXCEPTION
return 0;
}
Vector example #2:
It would be even better for you function to return a newly created and populated vector:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<vector<int>> input() {
ifstream infile;
infile.open("life.txt");
vector<vector<int>> cell_grid;
int i = 0;
for (string line; getline(infile, line); ++i)
{
cell_grid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cell_grid[i][j] = 1;
}
}
}
infile.close();
return cell_grid;
}
int main() {
auto vec = input();
return 0;
}
My thinking goes like this:
set row to 0
while can read a line from file
set column to 0
for each character on line
if character is '*'
set cellGrid(row,column) to 1
else
set cellGrid(row,column) to 0
increment column
increment row
You may want additional logic to trap row or column trying to go out of bounds or characters that aren't ' ' or '*'.
I have a file that stores a number matrix of unknown shape in format like
-1,4,12,5.7
2.1,3,-10,3.3
7.1,1.11,12,10
I attempt to store the matrix in a dynamically allocated array because I cannot hard code the number of row and column. For this part, I used pointer-to-pointer and a demo is as below,
#include <iostream>
using namespace std;
int main()
{
// Rather than user input, I need to change this part to deciding the shape of the matrix myself
int row, col;
cout << "Enter row number and column number, separated with a space:\n";
cin >> row >> col;
int** p_p_grid = new int* [row];
for(int i = 0; i < row; i++)
{
p_p_grid[i] = new int[col];
}
// Fill in the entries
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
// (i + 1) * (j + 1) needs to be replaced by true entries in the matrix
p_p_grid[i][j] = (i + 1) * (j + 1);
}
}
return 0;
}
But what is an efficient way to decide the shape of a comma separated number block before assigning the number one by one? And also how do I import a CSV-structured matrix in C++? (For some reason, I don't want to use a vector type, so please focus on an array)
what is an efficient way to decide the shape of a comma separated
number block before assigning the number one by one?
Assuming you're reading from a file stream, the easiest way, would be to read the file twice: one for counting rows and commas, on for doing the real input.
Here an example of how to detect the end of the matrix, stoping when the number of elements of a new line don't match the format of the matrix:
int nrows=1, ncols=0;
string line;
while (getline(ifs, line)) {
int n=1;
for (auto x: line) // count commas in the line
if (x==',')
n++;
if (!ncols)
ncols = n; // first line sets th enumber of columns
else if (n == ncols) // subsequent lines increase the row count
nrows++;
else break; // unless the format does'n match anymore
}
ifs.clear(); // remove eof
ifs.seekg (0, ifs.beg); // rewind
Online demo
What causes lack of efficiency in this approach, is that you read the file twice. For this reason, by the way, you can't use this approach for reading cin: you can't rewind.
You can optimize this either by caching the lines read (but you'd need to manage a rowing array of strings, as you're not allowed to use vectors), or by letting the matrix grow dynamically (which no longer correspond to your question as this would not provide the matrix size upfront).
how do I import a CSV-structured matrix in C++
Within each line, just read the doubles, followed by a char (which should be the ','):
char forget_me;
for (int i=0; i<nrows; i++)
for (int j=0; j<ncols; j++) {
cin >> p_p_grid[i][j];
if (j<ncols-1)
cin>>forget_me;
}
I know you didn't want a vector-based solution, but here's one anyway
int main() {
ifstream input("input.txt");
if(!input) {
cerr << "couldn't open file" << endl;
exit(1);
}
double number;
vector<vector<double>> matrix;
vector<double> current_row;
while(input >> number) { // loop once for each number in the file
current_row.push_back(number);
int next_char = input.get(); // should be ',' or '\n'
if(next_char == '\n') {
// current row is finished
matrix.push_back(current_row);
current_row.clear();
}
}
// now print the matrix back out again
for(auto const & one_row : matrix) {
for(auto one_number : one_row) {
cout << "\t," << one_number;
}
cout << endl;
}
}
It a bit fiddly. Use either C++ iostream or C stdio.h, and read in a whole line. So if using getline / fgets, you need a very big buffer, say 8k. Now for the first line, parse into fields. For a first attempt, simply count the commas, but the actual rules are more complicated than that.
The go through line by line, extracting the data. Since you've no say over the number of rows, you've no choice other than to dynamically grow the buffer for each line. An STL vector makes this easy for you - just push it back and the buffer will grow. However if you want you can use this structure
int **p_p_grid = 0;
int Nrows = 0;
int Ncolumns = 0;
/* ( for first line, fill the number of columns) */
/* for each line */
p_p_grid = realloc((Nrows + 1) * sizeof(int *));
if(!p_p_grid)
memory_failure();
p_p_grid[Nrows] = malloc(Ncolums * sizeof(int));
if(!p_p_grid[Nrows])
memory_failure();
for(i=0;i<Ncolumns;i++)
p_p_grid[Nrows][i] = /* parse logic here */
Nrows++;
As noted, I would use std::vector instead. Considering that each row have a fixed number of elements, I would also be using std::array. Perhaps doing something like this:
#include <vector> // For std::vector
#include <array> // For std::array
#include <string> // For std::string and std::getline
#include <fstream> // For std::ifstream
#include <sstream> // For std::isstream
int main()
{
std::vector<std::array<double, 4>> grid;
std::ifstream input{"input.txt"};
std::string line;
// Outer loop reads the rows
while(std::getline(input, line))
{
int i = 0;
std::istringstream iss{line};
std::array<double, 4> values;
double value;
// Inner loop extracts the values on each row
while (iss >> value)
{
values[i] = value;
// Skip over the comma
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
}
grid.push_back(values);
}
// Now print the values
int row_number = 1;
for (auto const& row : grid)
{
std::cout << "Row " << row_number++ << ": ";
for (auto const value : row)
{
std::cout << value << ' ';
}
std::cout << '\n';
}
}
Note that I haven't actually tested the code above. It compiles cleanly though.
I'm trying to read numbers from a test file and display them in a matrix. In the text file, there is one number per line. The first two lines are the dimensions of the matrix.(3 and 4) I'm having trouble assigning the actual data values of these numbers to the matrix. In this case Values 2 through 14.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
using namespace std;
#include "Matrix.h"
int main()
{
CMatrix A(10,10); //set to arbitrary size
int x;
int i = 0;
int number;
int rowsFile;
int columnsFile;
while ( myFile.good()&& myFile.is_open() )
{
myFile>>x;
if (i==0){ //for row dimension
rowsFile = x;
}
if (i==1){ //for column dimension
columnsFile = x;
}
cout<<"Value "<<i<<": "<<x<<endl; //displays the values
if (i>=2){
for (int r = 0; r < rowsFile; r++)
{
for (int c = 0; c < columnsFile; c++)
{
A.Value(r,c) = x;
myFile>>x;
}
}
myFile.close();
}
i=i+1;
}
myFile.close();
CMatrix A(rowsFile, columnsFile);
cout<<endl<< "Rows: "<<A.getNumberOfRows()<<endl;
cout<< "Columns: "<<A.getNumberOfColumns()<<endl;
cout<<endl<<A.ToString();
}
Here is a display of my output.
For some reason my commented out loop doesn't seem to be working.
Any help would be appreciated. Thank you!
While I can't offer you a complete solution due not completely understanding what you're trying to do, I recommend reading the contents of the file line wise and storing them in a vector, as in this example:
std::ifstream ifs("file.txt");
std::string line;
std::vector<std::string> lines;
if (ifs.good()) while (getline(ifs, line)) lines.push_back(line);
else throw std::runtime_error("An error occurred while trying to read from file.");
This makes it easier to work with the data.
I suggest you reorganize this code to place doubles into matrix elements immediately after reading them.
The file io code may not be perfect, but I would separate the reading of the number of rows and columns from the loop that handles the element values.
// do not declare i here
int numRows;
int numCols;
std::fstream inputFile("filename", std::in);
if ! (inputFile >> numRows >> numCols)
{
// Handle error
}
// Check that numRows and numCols are acceptable (positive)
// [not shown]
CMatrix A(numRows, numCols);
if (inputFile)
{
int elementsRead = 0;
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numCols; j++)
{
double x;
if (inputFile >> x)
{
A.Value(i,j) = x;
++elementsRead;
} else {
// probably an error from too-short file,
// token could not be converted to double, etc.
// handle appropriately
break;
}
}
}
}
if (elementsRead != numRows * numCols)
{
// handle error
}
// Use matrix A