HW Help - Reading from file character by character C++ - c++

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 '*'.

Related

How do I pass a textfile into a 2D array in c++?

I am required to pass a textfile that contains comma separated integers into a 2D array in c++.
eg if the textfile looks like:
2,3,56,4
3,5,7,1
0,23,9,87
2,4,5,2
I need to put this into a 2D array so that I may later perform calculations (which I do know how to do).
I have the following code, but I am struggling very much. Any help would be appreciated. Thank you.
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
const int row =4;
const int col =4;
int array[row][col];
int r =0;
int c =0;
ifstream inputfile("numbers.txt");
if (!inputfile.is_open())
{
cout<<"error"<<endl;
}
string line,num;
int number;
while(get line(inputfile,line))
{
string stream ss(line);
getline(ss,num,',');
number = stoi(num);
for (int r=0; r<row;r++)
{
for (int c=0; c<col; c++)
{
array[row][col] =number;
}
}
inputfile.close();
return 0;
}
Here is a simple example:
static const int MAX_ROWS = 4;
static const int MAX_COLUMNS] = 4;
int matrix[MAX_ROWS][MAX_COLUMNS];
//...
for (int row = 0; row < MAX_ROWS; ++ row)
{
std::string row_text;
std::getline(inputfile, row_text);
std::istringstream row_stream(row_text);
for (int column = 0; column < MAX_COLUMNS; ++column)
{
int number;
char delimiter;
row_stream >> number >> delimiter;
matrix[row][column] = number;
}
}
The above assumes that the text file contains the exact quantity of numbers.
Since the separators differ at the end of a line, each line is read as a string, then use std::istringstream to treat the stream as a file.

Reading the specific data from the file using Vector function C++

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;

Reading bidemensional char array from file C++

So I need to read a grid from a file,the grid's width and lengths is always the same.The problem is when I try to cout it on the last line it only shows about a half of it.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
ifstream TestIn("test");
int main()
{
char Grid[1000][1000],s[1000];
int LungimeX,LungimeY,i,j;
TestIn.getline(s,1000);
//finding the length
LungimeX=strlen(s);
cout<<LungimeX<<endl;
//finding the width
while (!TestIn.eof()) {
TestIn.getline(s,1000);
LungimeY++;
}
cout<<LungimeY;
//reset .eof
TestIn.clear();
TestIn.seekg(0, TestIn.beg);
//get the grid into the array
for(i=1;i<=LungimeY;i++) {
for(j=1;j<=LungimeX;j++) {
TestIn.get(Grid[i][j]);
}}
for(i=1;i<=LungimeY;i++){
for(j=1;j<=LungimeX;j++){
cout<<Grid[i][j];
}}
return 0;
}
So yeah,any ideas how to fix this?
LungimeY isn't initialized
Need to read (to skip) the header line after the file rewind
Need to skip CR and/or LF characters after each line read when filling the array
You were not ignoring the newline character LungimeX is the length of the line not including the new line character. a simple solution could be when reading the file if newline character is encountered read the next character.
#include
#include
#include
using namespace std;
ifstream TestIn("test");
int main()
{
char Grid[1000][1000],s[1000];
int LungimeX,LungimeY,i,j;
TestIn.getline(s,1000);
//finding the length
LungimeX=strlen(s);
cout<<LungimeX<<endl;
//finding the width
while (!TestIn.eof()) {
TestIn.getline(s,1000);
LungimeY++;}
cout<<LungimeY;
//reset .eof
TestIn.clear();
TestIn.seekg (0, TestIn.beg);
//get the grid into the array
for(i=1;i<=LungimeY;i++){
for(j=1;j<=LungimeX;j++){
TestIn.get(Grid[i][j]);
if(Grid[i][j] == '\n') //check new line character
TestIn.get(Grid[i][j]);
}}
for(i=1;i<=LungimeY;i++){
for(j=1;j<=LungimeX;j++){
cout<<Grid[i][j];
}
cout<<endl;
}
return 0;
}
And yes Please use 0 indexing in C++ you are wasting memory this way.
What about this kind of more C++ approach ?
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string fname("test.txt");
std::ifstream f(fname.c_str());
std::vector<std::string> lines;
std::string line;
while(std::getline(f, line))
lines.push_back(line);
unsigned long int num_rows = lines.size();
unsigned long int num_cols = 0;
if(num_rows > 0)
num_cols = lines[0].length();
std::cout << "num_rows = " << num_rows << std::endl;
std::cout << "num_cols = " << num_cols << std::endl;
for(unsigned long int i = 0; i < num_rows; ++i)
{
for(unsigned long int j = 0; j < num_cols; ++j)
std::cout << lines[i][j];
std::cout << std::endl;
}
return 0;
}

For-Loop - value of i is not 0 even if code says 'int i = 0'. i = BIG number, why? How to fix?

I'm designing a program to clean up a text file that contains code. It removes comments, excess spaces/lines, and creates a new line for lines in the file with multiple semi-colons.
I actually got this program to work, but it used arrays. Since I am working on another program that builds on this, except with a more diverse size of data inputs, I'm converting it to use vectors instead of standard arrays so I can re-purpose the program...which is kind of the point.
My problem is that after the program iterates through the first for-loop, the rest of the for-loops initialize the iterator with a value of '3435973836', regardless of proper declaration ('int i = 0', 'int k = 0', etc). I declare them unsigned and omitting singed/unsigned still initializes the value incorrectly (-858993460).
This does 1 of 2 things:
unsigned the loop never starts as the value is too high to start the loop.
omitting makes the loop run for a long, long time.
Any thoughts? I've posted the code below. Please ignore any other errors I've made other than this, as I have been unable to get past this to debug anything else.
EDIT --> SOLVED: the problem that I was passing the vectors by value. But even when I changed it to pass by reference the program would still not work. The actual problem was with Microsoft Visual Studio 2012. Once I PBV once, it corrupted my project. I had to start a new VS project and insert the code. If you do this, be careful you don't run the program while still PBV or you'll have to do it again. I don't know why this happens. Maybe somebody who knows MS Visual Studio could answer that.
Thanks again community!
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void removeComments(vector<string> row, ifstream & myfile);
void sortLines (vector<string> row);
//void cleanCode (vector<string> row);
int main()
{
vector<string> row;
ifstream myfile;
//Open txt file
myfile.open("newdata.txt");
if(myfile.is_open())
{
//Remove comments, create proper lines, and remove/add spaces.
removeComments(row, myfile);
sortLines(row);
//cleanCode(row);
}
else
{
cout<< "ERROR: No file was able to open. Check the file name or location and try again."<< endl << endl;
}
for (unsigned int i = 0; i < row.size(); i++)
{
cout<< row[i] << endl;
}
cout<< endl;
myfile.close();
system("PAUSE");
return 0;
}
//FUNCTIONS
//Removes all comments.
void removeComments(vector<string> row, ifstream & myfile)
{
string line;
while(getline(myfile, line))
{
string tempString;
for(unsigned int i = 0; i < line.length(); i++)
{
//Copy characters to row string array until "//".
//All character following and including "//" will be ignored.
if(line.at(i) == '/' && line.at(i+1) == '/')
{
break;
}
else
{
tempString += line.at(i);
}
}
row.push_back(tempString);
}
}
//Creates a new line after every semi-colon.
void sortLines (vector<string> row)
{
vector<string> tempRow;
string tempLine;
string tempString;
for (unsigned int i = 0; i < row.size(); i++)
{
tempLine = row [i];
for (unsigned int j = 0; j < tempLine.length(); j++)
{
tempString += tempLine[j];
if (tempLine[j] == ';')
{
tempRow.push_back(tempString);
}
}
}
//Revalue row array elements.
//DEBUGGING OUTPUT
for (unsigned int i = 0; i < tempRow.size(); i++)
{
cout<< tempRow[i] << endl;
}
row.clear();
row = tempRow;
}
Okay, this is my by-reference edit:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void removeComments(vector<string> &row, ifstream & myfile);
void sortLines (vector<string> &row);
//void cleanCode (vector<string> &row);
int main()
{
vector<string> row;
ifstream myfile;
//Open txt file
myfile.open("newdata.txt");
if(myfile.is_open())
{
//Remove comments, create proper lines, and remove/add spaces.
removeComments(row, myfile);
sortLines(row);
//cleanCode(row);
}
else
{
cout<< "ERROR: No file was able to open. Check the file name or location and try again."<< endl << endl;
}
for (unsigned int i = 0; i < row.size(); i++)
{
cout<< row[i] << endl;
}
cout<< endl;
myfile.close();
system("PAUSE");
return 0;
}
//FUNCTIONS
//Removes all comments.
void removeComments(vector<string> &row, ifstream & myfile)
{
string line;
while(getline(myfile, line))
{
string tempString;
for(unsigned int i = 0; i < line.length(); i++)
{
//Copy characters to row string array until "//".
//All character following and including "//" will be ignored.
if(line.at(i) == '/' && line.at(i+1) == '/')
{
break;
}
else
{
tempString += line.at(i);
}
}
row.push_back(tempString);
}
}
//Creates a new line after every semi-colon.
void sortLines (vector<string> &row)
{
vector<string> tempRow;
string tempLine;
string tempString;
for (unsigned int i = 0; i < row.size(); i++)
{
tempLine = row [i];
for (unsigned int j = 0; j < tempLine.length(); j++)
{
tempString += tempLine[j];
if (tempLine[j] == ';')
{
tempRow.push_back(tempString);
}
}
}
//Revalue row array elements.
//DEBUGGING OUTPUT
for (unsigned int i = 0; i < tempRow.size(); i++)
{
cout<< tempRow[i] << endl;
}
row.clear();
row = tempRow;
}
As others have noted you're:
Passing vectors by value
Using something possibly uninitialized out-of-my-scope (this is nowhere declared/defined in your question) as increment variable
//Creates a new line after every semi-colon.
void sortLines (vector<string> row)
{
vector<string> tempRow;
string tempLine;
string tempString;
for (unsigned int i = 0; i < row.size(); k++) // <-- what is k??
{
Why pass "string line" to removeComments? It should be local to that function cos you don't use it outside. It looks dodgy for the same reason that the passed vectors did.

C++ I/O numbers in text file

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