I am trying to write a rutine for C++ that reads an input file like the following,
1 12 13 0 0 1 0 INLE
2 1 12 0 0 1 0 INLE
3 11 2 0 0 1 0 INLE
4 13 11 0 0 1 0 INLE
5 2 8 0 0 2 0 OUTL
6 8 9 0 0 2 0 OUTL
7 9 10 0 0 2 0 OUTL
8 10 3 0 0 2 0 OUTL
9 4 5 0 0 3 0 SYMP
10 5 6 0 0 3 0 SYMP
11 6 7 0 0 3 0 SYMP
12 7 1 0 0 3 0 SYMP
13 14 4 0 0 4 0 WALL
14 16 14 0 0 4 0 WALL
15 15 16 0 0 4 0 WALL
16 3 15 0 0 4 0 WALL
In this case, I must asign the values of the second and third column to the condition specified on the last column of the right.
Something like,
read the last column;
if it reads the word INLE
{
asign the values of COLUMN2 and COLUMN3 to the pointer &p_InflowNode[i];
}
if it reads the word OUTL
{
asign the values of COLUMN2 and COLUMN3 to the pointer &p_NonrefNode[i];
}
etc...
So my main question is, how can I make C++ to read first the last column, and then decide what to do with the values of the second and third columns?
Thaks
I suggest you do this
struct CData
{
int nC1;
int nC2;
int nC3;
int nC4;
int nC5
int nC6;
int nC7;
string sMode;
friend ifstream& operator >>(ifstream&, struct& CData);
}
You just need to overload the input operator and then
declare an object of the struct and work on it:
struct CData cObj;
ifstream ifIn;
ifIn.open("yourfile.txt");
while(ifIn)
{
ifIn>>cObj;
//now you can use the nested if and else structure here
}
I would suggest if line breaks are consistent to read the file line by line (std::getLine) in a buffer, and check the ending string.
Check line ending
I ended up solving it like this,
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
ifstream myfile("ramp.bnd");
string Point1;
string Point2;
string Boundary;
string line,temp;
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
istringstream iss(line);
iss >> temp >> Point1 >> Point2 >> temp >> temp >> temp >> temp >> Boundary;
if (Boundary == "INLE") {
cout << "Inlet condition!!"; //To add more code
}
cout << " \n";
}
myfile.close();
}
else std::cout << "Unable to open file";
myfile.close();
return 0;
}
Related
I want to read a file called maze.txt which contains 0s and 1s (indicated blocked or not), and store every element in the file into 2 dimensionals array called maze[17][17].
maze.txt be like :
11111111111111111
10000000000101001
10100111111001101
10101100001010101
10111010100000001
10000011011111001
11111000010001001
10110010000100101
10110100101110111
10000111000100001
10110011000100101
10110010000011101
10111001111110101
10110010000010001
10010111110101111
10010000000000001
11111111111111111
What I've searched the closest answer is using getline() plus istringstream()
(refer to : Read from file in c++ till end of line?)
But above solution only applies when I put a whitespace between each of them, like :
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1
1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 1
1 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 1
1 0 1 1 1 0 1 0 1 0 0 0 0 0 0 0 1
1 0 0 0 0 0 1 1 0 1 1 1 1 1 0 0 1
1 1 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1
1 0 1 1 0 0 1 0 0 0 0 1 0 0 1 0 1
1 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 1
1 0 0 0 0 1 1 1 0 0 0 1 0 0 0 0 1
1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 0 1
1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 1
1 0 1 1 1 0 0 1 1 1 1 1 1 0 1 0 1
1 0 1 1 0 0 1 0 0 0 0 0 1 0 0 0 1
1 0 0 1 0 1 1 1 1 1 0 1 0 1 1 1 1
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
My code:
void read_maze(int map[17][17]) {
ifstream read_file("D:/maze.txt", ios::in);
if (read_file.good()){
string str;
int i = 0;
while (getline(read_file, str) {
int j = 0;
istringstream ss(str);
int num;
while (ss >> num)
{
map[i][j] = num;
j++;
}
i++;
}
}
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
cout << map[i][j];
}
cout << endl;
}
read_file.close();
}
output is like original maze.txt
So, what should I do to store each of the element in maze.txt into an array without modifying the content of it?
I believe there might be some easier solutions to it, but since I'm a newbie to C++, I can't find any of similar situations like me.
Hope someone can provide detailed code based on above code.
Thanks a lot!
You can do it like this :
#include <array>
#include <iostream>
#include <string>
#include <sstream>
std::istringstream file{
"11111111111111111\n"
"10000000000101001\n"
"10100111111001101\n"
"10101100001010101\n"
"10111010100000001\n"
"10000011011111001\n"
"11111000010001001\n"
"10110010000100101\n"
"10110100101110111\n"
"10000111000100001\n"
"10110011000100101\n"
"10110010000011101\n"
"10111001111110101\n"
"10110010000010001\n"
"10010111110101111\n"
"10010000000000001\n"
"11111111111111111\n"
};
auto load(std::istream& is)
{
// use std::array, you can actually return that from functions
// and avoids the pain of having to work with double pointers
// and manual memory managment.
std::array<std::array<char, 17>, 17> map{};
// loop over all rows in the map
for (auto& row : map)
{
// loop over all the values in a row
for (auto& value : row)
{
// read one value from the file
is >> value;
}
// newlines will be skipped.
}
// and return your map (2d array)
return map;
}
int main()
{
// file is a stringstream now but
// is easily replaced by a filestream
// (stringstream just makes testing more easy)
auto map = load(file);
// just another range based for loop
// to display the map we read from file.
for (const auto& row : map)
{
for (const auto& value : row)
{
std::cout << value;
}
std::cout << "\n";
}
}
Your code would work with a slight modification. Like this:
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
void read_maze(int map[17][17]) {
ifstream read_file("maze.txt", ios::in);
if (read_file.good()){
string str;
int i = 0;
while (getline(read_file, str)) {
// read line and process each digit
for (int j=0; j < str.size(); j++) {
map[i][j] = str[j] - '0';
}
i++;
}
}
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
cout << map[i][j] << " ";
}
cout << endl;
}
read_file.close();
}
int main() {
int map[17][17] = {};
read_maze(map);
}
Suppose, I have a file with 3 column. first 2 column is index of matrix and 3rd column is value of that position in a matrix.
0 0 1
0 1 0
0 2 2
1 0 0
1 1 0
1 2 3
2 0 0
2 1 0
2 2 4
Now i want to search in this file everytime by this loop
for(int a=0; a<8;a=a+2){
for(int b=0; b<8;b=b+2){
for(int c=a; c<2;c++){
for(int d=a; d<2;d++){
//check here c and d is exist in file. if exist then return the 3 column value of that index position and if not then return 0
}
}
}
}
I can not search the value in the whole file every time because it hold the position before the file read in past.please help me I stack on a huge problem in my academia.
Possible solution with std::map for your problem:
First we write every value with the index as key and the value as the mapped value in the map and then we can search for any index:
#include <iostream>
#include <map>
#include <sstream>
#include <string>
int main()
{
std::stringstream stream(
"\
0 0 1\n\
0 1 0\n\
0 2 2\n\
1 0 0\n\
1 1 0\n\
1 2 3\n\
2 0 0\n\
2 1 0\n\
2 2 4\n\
");
std::map<std::pair<int,int>,int> map;
int x, y, value;
while(stream >> x >> y >> value)
{
map.insert({{x, y}, value});
}
int c = 0, d = 2;
auto pos = map.find({c, d});
if(pos != map.end())
{
std::cout << "Value of searched index: " << pos->second << std::endl;
}
return 0;
}
The following code is supposed to find the minimum spanning tree from a adjacency matrix:
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <conio.h>
#include <vector>
#include <string>
using namespace std;
int i, j, k, a, b, u, v, n, ne = 1;
int min, mincost = 0, cost[9][9], parent[9];
int find(int);
int uni(int, int);
int find(int i)
{
while (parent[i]) // Error occurs at this line
i = parent[i];
return i;
}
int uni(int i, int j)
{
if (i != j)
{
parent[j] = i;
return 1;
}
return 0;
}
int main()
{
cout << "MST Kruskal:\n=================================\n";
cout << "\nNo. of vertices: ";
cin >> n;
cout << "\nAdjacency matrix:\n\n";
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
cin >> cost[i][j];
if (cost[i][j] == 0)
cost[i][j] = 999;
}
}
cout << "\nMST Edge:\n\n";
while (ne < n)
{
for (i = 1, min = 999; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
if (cost[i][j] < min)
{
min = cost[i][j];
a = u = i;
b = v = j;
}
}
}
u = find(u);
v = find(v);
if (uni(u, v))
{
cout << ne++ << "th" << " edge " << "(" << a << "," << b << ")" << " = " << min << endl;
mincost += min;
}
cost[a][b] = cost[b][a] = 999;
}
cout << "\nMinimum cost = " << mincost << "\n" << endl;
system("PAUSE");
return 0;
}
It works for 6 number of vertices and the following matrix:
0 3 1 6 0 0
3 0 5 0 3 0
1 5 0 5 6 4
6 0 5 0 0 2
0 3 6 0 0 6
0 0 4 2 6 0
however for 13 vertices and with the following matrix:
0 1 0 0 0 2 6 0 0 0 0 0 0
1 0 1 2 4 0 0 0 0 0 0 0 0
0 1 0 0 4 0 0 0 0 0 0 0 0
0 2 0 0 2 1 0 0 0 0 0 0 0
0 4 4 2 0 2 1 0 0 0 0 4 0
2 0 0 1 2 0 0 0 0 0 0 2 0
6 0 0 0 1 0 0 3 0 1 0 5 0
0 0 0 0 0 0 3 0 2 0 0 0 0
0 0 0 0 0 0 0 2 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0 1 3 2
0 0 0 0 0 0 0 0 1 1 0 0 0
0 0 0 0 4 2 5 0 0 3 0 0 1
0 0 0 0 0 0 0 0 0 2 0 1 0
this error occurs:
Unhandled exception at 0x00ED5811 in KruskalMST.exe: 0xC0000005: Access violation reading location 0x00F67A1C.
The error occurs at line 17: while (parent[i])
VS Autos:
Name Value Type
i 138596 int
parent 0x00ee048c {2, 999, 999, 999, 999, 999, 999, 999, 2} int[9]
[0] 2 int
[1] 999 int
[2] 999 int
[3] 999 int
[4] 999 int
[5] 999 int
[6] 999 int
[7] 999 int
[8] 2 int
You've defined your 'parent' array to have a size of 9 (assuming you have a maximum of 9 vertices, so max number of parents is 9). Six vertices will work because it's less than 9. With thirteen vertices you MAY be accessing elements passed your parent array size; thus, you should try and define your array size depending on the number of vertices.
P.S In general you don't want to have magic numbers in your code.
while (parent[i])
{
i = parent[i];
}
First of all, please use braces to enclose the while statement. Anyone adding another line to it would likely cause undesired behavior.
Your problem is likely that parent[i] assigns a value to i that is outside of the bounds of the parent array.
Try this to see what it's assigning to i:
while (parent[i] != 0)
{
cout << "parent[i] is " << parent[i];
i = parent[i];
}
Since the parent array has a size of 9, if i is ever set to 9 or greater (or less than 0 somehow), you may get an access violation when using parent[i].
Unrelated: It's good to be explicit about what condition you're checking in the while. Before I saw that parent was an int[], I didn't know if it might be an array of pointers, or booleans, I didn't know what the while condition was checking for.
If you want to be safe, bounds check your parent array:
static const int parentSize = 9;
int parent[parentSize];
while (parent[i] != 0 && i > 0 && i < parentSize)
{
cout << "parent[i] is " << parent[i];
i = parent[i];
}
You likely need to increase the parentSize to something larger. If you want something that is more dynamic you might considering using std::vector instead of an array, it can be resized at runtime if you run into a case where the container isn't large enough.
I'm writing a program for a c++ data structures class that reads in a space separated file and I wrote a small function so that I could pipe in different files and work with them, but I would also like to take user input using cin and it seems that the buffer is just looping. I'm sort of beyond my depth here, but here's my input function. I'm running the program by $ cat filename | ./compiledexec. I was hoping someone might know why using cin in other places doesn't wait for user input and perhaps help with a solution?
void catchPipe(int dataArray[][9]);
int main(){
int inArray[9][9];
int column;
catchPipe(inArray);
cout << "Which column would you like to check?";
cin >> column; // This input is skipped totally.
functionChecksIfInCol(column); //Function called with garbage value
cout << "end program" << endl;
return 0;
}
void catchPipe(int dataArray[][9]){
int i;
int n=0;
int pos=0;
string mystring;
while(cin){
getline(cin, mystring);
if( n < 9 ){
for(i = 0; i < mystring.length(); i++){
if( (int)mystring[i] != 32 ){
dataArray[n][pos] = mystring[i] - '0';
pos++;
}
}pos =0;
++n;
}
}
}// end catchPipe()
//Sample File input:
0 8 0 1 7 0 0 0 3
0 2 0 0 0 0 0 0 9
0 9 0 0 3 0 5 4 8
0 0 4 0 9 0 0 0 0
0 0 0 7 0 3 0 0 0
0 0 0 0 1 0 4 0 0
6 1 9 0 8 0 0 5 0
7 0 0 0 0 0 0 8 0
2 0 0 0 6 4 0 1 0
Thanks!
The program fills in my inArray, but it skips the next call to cin. I'm assuming this is because stdin has been redirected from the keyboard to the pipe from linux? Maybe I can declare another istream object and direct it to the keyboard or something? I'm not sure what to do here
Use a vector:
void cachePipe(std::vector<std::vector<int>> data)
{
std::string line;
while (std::getline(std::cin, line))
{
std::istringstream iss(line);
std::vector<int> fill((std::istream_iterator<int>(line)),
std::istream_iterator<int>());
data.push_back(fill);
}
}
i am doing read file in c++ and this is my code :
#include <iostream>
#include <fstream>
#include <algorithm>
#include <climits>
using namespace std;
int main()
{
int row=0;
int col=0;
ifstream inputFile;
int arr[16][5];
inputFile.open("hdtt4req.txt");
if(inputFile.is_open()) {
inputFile >> arr[row][col];
for (row = 0; row < 16; row++) {
for (col = 0; col < 5; col++) {
cout <<"hi"; //arr[row][col];
cout << endl;
}
}
}
return 0;
}
and this is the file that i want to read:
1 2 2 1 2
2 1 1 1 2
3 1 1 1 6
4 2 2 3 2
1 2 5 1 2
2 0 4 3 2
3 1 2 1 0
4 2 2 1 2
1 2 1 1 2
2 0 0 5 1
3 2 1 4 1
4 6 1 2 1
1 3 1 2 1
2 1 4 1 4
3 3 3 2 1
4 2 0 1 1
after i compile , i get this kind of result. can anyone tell me what is the error ? thanks
row and col start start undefined, so the statement inputFile >> arr[row][col]; will give you undefined behavior. Make sure you set these values to zero before performing any operations
row = col = 0;