taking input until end of file in c++ - c++

I am solving a graph problem where I have to take input from a file. Below is my input.txt file.
12
1 2
2 3
2 4
2 5
3 6
4 5
4 7
5 2
5 6
5 7
6 3
6 8
7 8
7 10
8 7
9 7
10 9
10 11
11 12
12 10
In the above input.txt file first input is no of vertices and the others till the end of the file are directed edge of Graph. The first one is the source and the second one is the destination. All the input will be read from the input.txt file.
#include <bits/stdc++.h>
#include <fstream>
using namespace std;
class Graph {
private:
int V;
list<int> *l;
public:
Graph(int V) {
this->V = V;
l = new list<int>[V];
}
void addEdge(int source, int destination) {
// As it is a directed graph edge will be source to destination only
l[source].push_back(destination);
}
void printAdjList() {
for(int i = 1; i <= V; i++) {
cout << "Vertex " << i << "-> " ;
for(int previous: l[i]) {
cout << previous << " " ;
}
cout << endl;
}
}
};
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ifstream inputFile;
inputFile.open("input.txt");
int noOfVertex, s, d, noOfEdge=20;
inputFile >> noOfVertex ;
// cout << noOfVertex << endl;
Graph g(noOfEdge);
// while(cin.eof()) {
// // cout << s << " " << d << endl;
// cin >> s >> d;
// g.addEdge(s, d);
// }
if(inputFile) {
while(inputFile >> s >> d) {
// cout << s << " " << d << endl;
g.addEdge(s, d);
}
inputFile.close();
}
else {
cout << "Error opening input file" << endl;
}
g.printAdjList();
return 0;
}
I am getting this result after running the code
Vertex 1-> 2
Vertex 2-> 3 4 5
Vertex 3-> 6
Vertex 4-> 5 7
Vertex 5-> 2 6 7
Vertex 6-> 3 8
Vertex 7-> 8 10
Vertex 8-> 7
Vertex 9-> 7
Vertex 10-> 9 11
Vertex 11-> 12
Vertex 12-> 10
Vertex 13->
Vertex 14->
Vertex 15->
Vertex 16->
Vertex 17->
Vertex 18->
Vertex 19->
I can not take the number of edge for this problem. The number of vetices and given directed edges will be taken one by one line from the file and it will show an adjacency list like that
Vertex 1-> 2
Vertex 2-> 3 4 5
Vertex 3-> 6
Vertex 4-> 5 7
Vertex 5-> 2 6 7
Vertex 6-> 3 8
Vertex 7-> 8 10
Vertex 8-> 7
Vertex 9-> 7
Vertex 10-> 9 11
Vertex 11-> 12
Vertex 12-> 10
How can I take input from the file so that I can get the above output? I have applied many methods but nothing is working.

Your code is wrong for 2 reasons:
you use a hardcoded number of edges when should use the number of vertex
you use an array with an index starting at 0 when the number of the vertex is read from file and does not start at 0
If you want to be safe, you should use a map (or unordered map) int -> list:
...
class Graph {
private:
int V;
unordered_map<int, list<int> > l; // change here
public:
Graph(int V) {
this->V = V;
l.reserve(V); // here
}
...
int noOfVertex, s, d, noOfEdge = 20;
inputFile >> noOfVertex;
// cout << noOfVertex << endl;
Graph g(noOfVertex); // and here
...
That is enough to get as expected:
Vertex 1-> 2
Vertex 2-> 3 4 5
Vertex 3-> 6
Vertex 4-> 5 7
Vertex 5-> 2 6 7
Vertex 6-> 3 8
Vertex 7-> 8 10
Vertex 8-> 7
Vertex 9-> 7
Vertex 10-> 9 11
Vertex 11-> 12
Vertex 12-> 10

I suggest you make your addEdge method more flexible and easier to use. As one problem, if the source input is larger than the size of list your program will crash. The logic should be:
if there is no source vertex, add it
if there is no destination vertex, add it
add link from source to destination.
Here is a more detailed description of the suggested procedure.
/// find vertex "n", returning vertex index, or -1 if missing
int find( int n )
{
loop over graph
if vertex is "n
return index
return -1
}
/// find vertex "n", or add it if not present
int findoradd( int n )
{
int i = find( n );
if( i >= 0 )
return i
return addvertex( n )
}
/// add link between vertices
void addLink( int u, int v )
{
addEdge(
findoradd( u ),
findoradd( v ) );
}

Related

Outputting Values from a 2D Array to a Text File

I am writing some C++ code and i currently have a function that reads in some numbers from a text file and stores them into a 2D array. I now need to output the same numbers i have stored into the 2D array back out into a new text file. I currently have some code in a function that can output the numbers however they are not in the same format as the input file. As you can see below.
Input File Format (space between each number)
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9 1
3 4 5 6 7 8 9 1 2
4 5 6 7 8 9 1 2 3
5 6 7 8 9 1 2 3 4
6 7 8 9 1 2 3 4 5
7 8 9 1 2 3 4 5 6
8 9 1 2 3 4 5 6 7
9 1 2 3 4 5 6 7 8
Output File Format Currently
123456789234567891345678912456789123567891234678912345789123456891234567912345678 (this is all on one line)
My function to read in from the text file.
void Grid::LoadGrid(const char filename[])
{
ifstream file(filename);
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
file >> m_grid[x][y];
}
}
file.close();
}
My function to read out to the text file. (m_grid is the 2D array)
void Grid::SaveGrid(const char filename[])
{
ofstream file(filename);
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
file << m_grid[x][y];
}
}
file.close();
}
If anyone can help me output it to the text file so it will appear the same as the input i'd be very grateful.
Edit: Question has been answered.
After your inner loop completes
file << endl;
Also in your inner loop might want to..
file << m_grid[x][y] << " ";
Update the way you write to the file like this:
void Grid::SaveGrid(const char filename[])
{
ofstream file(filename);
for (int y = 0; y < 9; y++) {
cout << endl;
for (int x = 0; x < 9; x++)
{
cout << m_grid[x][y];
cout << " ";
}
}
file.close();
}
In your output function you should write the spaces after each character. And the newline character when you reach the end of a row.
I believe this would work
void Grid::SaveGrid(const char filename[])
{
ofstream file(filename);
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 9; x++)
{
file << m_grid[x][y] << " ";//write a space after the character
if(x ==8) //at x ==8 is where this for loop would exit
{
file << "\n"
}
}
file.close();
}
The output you are seeing is exactly what you told the compiler to do. You are displaying each of your NxN matrix elements one right after another. You never added any white space to your output stream. To fix this, it is quite simple. Adjust your function as follows:
void Grid::SaveGrid(const char filename[])
{
ofstream file(filename);
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
file << m_grid[x][y] << " "; // and a space after each element
}
file << '\n'; // add a new line character after each row has been printed.
}
file.close();
}
Here's a simple working example that uses a std::vector<int> of your numbers and displays it to the console. The only difference here is that I'm using a 2D to 1D mapping for the indexing into the vector. Once you understand how this affects the formatting it should be trivial to convert it from an std::vector to a multidimensional array and to convert the iostream to a fstream output.
#include <iostream>
#include <vector>
int main() {
const std::vector<int> values{ 1,2,3,4,5,6,7,8,9,
2,3,4,5,6,7,8,9,1,
3,4,5,6,7,8,9,1,2,
4,5,6,7,8,9,1,2,3,
5,6,7,8,9,1,2,3,4,
6,7,8,9,1,2,3,4,5,
7,8,9,1,2,3,4,5,6,
8,9,1,2,3,4,5,6,7,
9,1,2,3,4,5,6,7,8
};
const int size = 9;
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
std::cout << values[col + size*row] << " ";
}
std::cout << '\n';
}
return 0;
}
-Ouput-
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9 1
3 4 5 6 7 8 9 1 2
4 5 6 7 8 9 1 2 3
5 6 7 8 9 1 2 3 4
6 7 8 9 1 2 3 4 5
7 8 9 1 2 3 4 5 6
8 9 1 2 3 4 5 6 7
9 1 2 3 4 5 6 7 8

Sorting a text file which contains integers, sorting has to be done line by line

I want to sort a file which contains integers but wanted to sort only line by line. I tried, but I am sure what I am doing below isn't in-place.
void sort_file_in_place(const char* filename) {
fstream sort_file;
sort_file.open(filename, ios::out | ios::in);
vector <vector <int> > input_vect;
string line;
std::string delimiter = " ";
int vect_index = 0;
while (getline(cin, line)) {
//store into vector of vectors
//tokenise string
size_t pos = 0;
int value = 0;
int count = 0;
while ((pos = line.find(delimiter)) != std::string::npos) {
string token = line.substr(0, pos);
line.erase(0, pos + delimiter.length());
value = std::atoi(token.c_str());
count++;
}
input_vect.resize(vect_index++, vector<int>(count));
}
//sort vector of vectors
for (int i = 0; i < input_vect.size(); i++) {
sort(input_vect[i].begin(), input_vect[i].end(), std::less<int>());
//print the sorted vectors and alos verify the content
for (auto v : input_vect[i]) cout << v << " ";
}
//write back into the file
//Todo
}
The above code isn't complete but I hope you get what I wanted to ask.
Please suggest a better solution.
Also I want to sort these lines using different threads, for example:
If the file content is:
13 38 13 100 4 234 85 34 0 100 88
1 4 5 3 8 9 1 10
111 10 112 3 4 098 194
5 4 8 3 9 13 24 78 09 99
I want to create four threads to sort each line in-place.
I cannot see how to do it "in-place". Perhaps with some black magic we could sort elements without having them somewhere in memory but I don't have knowledge about such an occult science :)
Joking aside, if storing the lines into a std::vector does not suit your needs, you can use any other container you may want, even a raw array or a custom one. But in any case, you have to store the lines somewhere to handle them (to sort them in this case).
I have written an example to achieve what you want:
#include <vector>
#include <fstream>
#include <algorithm>
#include <thread>
std::vector<std::string> split(const std::string & s, char c)
{
std::vector<std::string> splitted;
std::string word;
for(char ch : s)
{
if((ch == c) && (!word.empty()))
{
splitted.push_back(word);
word.clear();
}
else
word += ch;
}
if(!word.empty())
splitted.push_back(word);
return splitted;
}
bool read_data(const std::string & file_path, std::vector<std::vector<int>> & data)
{
data.clear();
std::ifstream in_s(file_path);
if(!in_s)
return false;
std::string line;
std::vector <int> row;
while(std::getline(in_s, line))
{
if(!line.empty())
{
for(auto s : split(line, ' '))
row.push_back(std::stoi(s));
data.push_back(row);
row.clear();
}
}
in_s.close();
return true;
}
bool write_data(const std::string & file_path, const std::vector<std::vector<int>> & data)
{
std::ofstream out_s(file_path);
if(!out_s)
return false;
for(const auto & row : data)
{
for(size_t i = 0; i < row.size(); ++i)
{
if(i == 0)
out_s << row[i];
else
{
out_s << ((row[i] < 0) ? (" ") : (" ")) << row[i];
}
}
out_s << std::endl;
}
out_s.close();
return true;
}
void sort_line(std::vector<int> & line)
{
std::sort(line.begin(), line.end(), [](const int & i, const int & j){return i<j;});
}
void sort_data_lines(std::vector<std::vector<int>> & data)
{
std::vector<std::thread> thread_mem;
for(auto & row : data)
{
thread_mem.push_back(std::thread(sort_line, std::ref(row)));
}
for(auto & t : thread_mem)
t.join();
}
I have separated the code in three main functions, read_data() to read data from a file, sort_data_lines() to sort the data and write_data() to write data into a file.
It may be used as follows:
int main()
{
const std::string in_file_path("path/to/the/input_file.txt");
const std::string out_file_path("path/to/the/output_file.txt");
std::vector<std::vector<int>> data;
if(!read_data(in_file_path, data)) // Read the data
return -1;
sort_data_lines(data); // Sort the data
if(!write_data(out_file_path, data)) // Write the sorted data
return -2;
return 0;
}
I have multi-threaded the sorting of each line (as asked) but I think it may be important to notice that it is not a good idea if your file contains a lot of lines (and consequently, a lot of simultaneously running threads).
Usually, fix a limit at between 4 and 8 running threads is a good choice.
Of course, if your file is supposed to contain only four lines, there is no problem since you'll only have 4 running threads :)
I've made the test with the following input file:
5 2 4 3 1 -3 8 -4 -1 0 1 0 6
6 9 3 1 5 2 6 8 -7 -1 0 0 -3
2 7 9 3 4 5 -5 6 -1 0 2 -2 3
0 -6 -2 8 5 -1 4 5 -6 7 2 2 0
And I obtained the following output file:
-4 -3 -1 0 0 1 1 2 3 4 5 6 8
-7 -3 -1 0 0 1 2 3 5 6 6 8 9
-5 -2 -1 0 2 2 3 3 4 5 6 7 9
-6 -6 -2 -1 0 0 2 2 4 5 5 7 8
Hope it can help a bit.

depth first search c++

Hello i am working on this project on depth first search, the program uses a linkedlist for each adjacent vertex and use a stack. The program has two structures a Vertex Struct that has two fields a linkedlist pointer and a boolean variable called visted marked as false. The second struct is a Graph that has two fields an array of Vertex Struct and an integer for the number of vertices. The problem i have if when the depth first search function is called it never stops even if the stack is empty the depth first function prints each vertices that is visited. Can someone help me with finding a way to make the program stop ones the stack is empty;
#include <iostream>
#include "linklist.h"
#include "Stack.h"
using namespace std;
typedef int vertexNum;
Stack S;
struct Vertex
{
List p;
bool visted;
Vertex()
{
p = NULL;
visted = false;
}
};
struct Graph
{
int numVert;
Vertex* vertArr;
Graph(int num)
{
numVert = num;
vertArr = new Vertex[numVert+1];
}
};
void readGraph(Graph& G)
{
cout << "Enter adjacent vertices, enter 0 to stop" << endl;
vertexNum v1, v2;
cin >> v1;
while (v1 != 0)
{
cin >> v2;
insertTail(v2,G.vertArr[v1].p);
insertTail(v1,G.vertArr[v2].p);
//G.vertArr[v1].p = cons(v2,G.vertArr[v1].p);
//G.vertArr[v2].p = cons(v1,G.vertArr[v2].p);
cin >> v1;
}
}
void printGraph(Graph& G)
{
for (int i = 1; i <= G.numVert; i++)
{
cout << "Vertex "<< i << " Adjacent list ";
printList(G.vertArr[i].p);
}
}
void DFS(int x,Graph& G)
{
push(x,S);
printList(S.p);
G.vertArr[x].visted = true;
if (!G.vertArr[head(G.vertArr[x].p)].visted)
{
DFS(head(G.vertArr[x].p),G);
}
else
{
cout << ""<< endl;
List temp = tail(G.vertArr[x].p);
if(isEmpty(temp))
{
pop(S);
G.vertArr[peek(S)].visted = false;
DFS(pop(S),G);
}
else if(!G.vertArr[head(temp)].visted)
{
DFS(head(temp),G);
}
else
{
int num =0;
for (List pp = temp; !isEmpty(pp); pp = tail(pp))
{
if(!G.vertArr[head(pp)].visted)
{
num = head(pp);
break;
}
}
if (num == 0)
{
pop(S);
G.vertArr[peek(S)].visted = false;
DFS(pop(S),G);
}
else
DFS(num,G);
}
}
}
int main()
{
int x,y;
cout << "Enter the number of vertices" << endl;
cin >> x;
Graph p(x);
readGraph(p);
printGraph(p);
cout << "\nEnter start vertex" << endl;
cin >> y;
DFS(y,p);
}
The program outputs
Enter the number of vertices
13
Enter adjacent vertices, enter 0 to stop
1 4
1 5
1 2
1 3
2 7
2 8
8 13
8 7
11 12
10 9
13 12
9 6
6 5
0
Vertex 1 Adjacent list 4 5 2 3
Vertex 2 Adjacent list 1 7 8
Vertex 3 Adjacent list 1
Vertex 4 Adjacent list 1
Vertex 5 Adjacent list 1 6
Vertex 6 Adjacent list 9 5
Vertex 7 Adjacent list 2 8
Vertex 8 Adjacent list 2 13 7
Vertex 9 Adjacent list 10 6
Vertex 10 Adjacent list 9
Vertex 11 Adjacent list 12
Vertex 12 Adjacent list 11 13
Vertex 13 Adjacent list 8 12
Enter start vertex
5
5
1 5
4 1 5
1 5
2 1 5
7 2 1 5
8 7 2 1 5
13 8 7 2 1 5
12 13 8 7 2 1 5
11 12 13 8 7 2 1 5
12 13 8 7 2 1 5
13 8 7 2 1 5
8 7 2 1 5
7 2 1 5
2 1 5
1 5
3 1 5
1 5
5
6 5
9 6 5
10 9 6 5
9 6 5
6 5
5
Here is the stack and linkedlist h files
#ifndef LINKLIST_H_
#define LINKLIST_H_
#include <cstdlib>
#include <iostream>
using namespace std;
struct listCell
{
int head;
listCell* tail;
listCell(int h, listCell* t)
{
head =h;
tail = t;
}
};
typedef listCell* List;
typedef const listCell* constList;
List emptyList = NULL;
int head(List L)
{
return L->head;
}
List tail(List L)
{
return L->tail;
}
bool isEmpty(List L)
{
return L == emptyList;
}
List cons(int h, List t)
{
return new listCell(h,t);
}
int listLength(List L)
{
if (isEmpty(L))
{
return 0;
}
else
{
return 1 + listLength(tail(L));
}
}
void printList(List L)
{
List k = L;
while (!isEmpty(k))
{
int val = head(k);
k = k->tail;
cout << val << " ";
}
cout << "\n";
}
here is the stack file
#ifndef STACK_H_
#define STACK_H_
#include "linklist.h"
struct Stack
{
List p;
Stack()
{
p = NULL;
}
};
void push(int x, Stack& list)
{
list.p =cons(x,list.p);
}
int peek(Stack& list)
{
return head(list.p);
}
int pop(Stack& list)
{
return delHead(list.p);
}
bool isEmpty(Stack& list)
{
return isEmpty(list.p);
}
int size(Stack& list)
{
return listLength(list.p);
}
#endif /* STACK_H_ */

print a table of decremented numbers

I want to write a code that print a table like this:
5 5 5 5 5 5 5 5 5
5 4 4 4 4 4 4 4 5
5 4 3 3 3 3 3 4 5
5 4 3 2 2 2 3 4 5
5 4 3 2 1 2 3 4 5
5 4 3 2 2 2 3 4 5
5 4 3 3 3 3 3 4 5
5 4 4 4 4 4 4 4 5
5 5 5 5 5 5 5 5 5
I wrote a code to print a table as said above, but it just print 5's.
I know that I have to use a condition to print such a table. What's the condition to print it ?
int main () {
int number = 5;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (condition)
...
else
cout << number << " ";
}
cout << endl;
}
return 0;
}
As I mentioned in comments, what you want to print is the Chebyshev distance to the center +1. I dont know what condition can make your code work, but instead I would use a simple formula to calculate each value:
#include <iostream>
using namespace std;
int main() {
for (int i=0;i<9;i++){
for (int j=0;j<9;j++){
cout << std::max(abs(i-4),abs(j-4)) +1 << " " ;
}
cout << endl;
}
}
/*To make boxes and inside box and so on
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
void main()
{
int a[100][100],n,i,j,k=0,l;
clrscr();
cout<<"Enter the outside No. n \n";
//like for your answer it is 5;
//i and j are loop element for 2D array
//k is used for making n boxes
cin>>n;
l=n;
n=2*n-1;
while(k<n)
{
if(k%2==0)
{
for(i=k;i<n-k;i++)
{
a[0+k][i]=l;
a[i][0+k]=l;
a[n-1-k][i]=l;
a[i][n-1-k]=l;
}
k++;l--;
}
else
{
for(i=k;i<n-k;i++)
{
a[0+k][i]=l;
a[i][0+k]=l;
a[n-1-k][i]=l;
a[i][n-1-k]=l;
}
k++;l--;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
cout << a[i][j];
if(a[i][j]>9)
cout<<" ";
else
cout<<" ";
}
cout<<endl;
}
getch();
}

graph levelization using BGL

Can you please post example code to levelize a directed graph using BGL?
Definition of levelization: Vertex has a property "int level". During BFS traversal of the graph, when a vertex is being "examined", look at its predecessor vertices' levels, take max of these, increment, and assign this to the "level" of this vertex.
If you mean the BFS depth then this is already built in to boost BFS and can be gotten easily.
Just use a vector to store the depths and a depth BFS visitor like this example I made:
#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/breadth_first_search.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list < vecS, vecS, directedS,
property< vertex_index_t, size_t> ,
property< edge_index_t, size_t > > Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;
int main(int argc, char* argv[]){
Graph G;
vector<Vertex> verts;
for(size_t i = 0; i < 9; ++i){
Vertex v = add_vertex(G);
verts.push_back(v);
}
/*
0 0
/ \
1 1 4
/ \
2 2 5
/ \
3 3 6
\
4 7
\
5 8
*/
add_edge(verts.at(0),verts.at(1),G);
add_edge(verts.at(1),verts.at(2),G);
add_edge(verts.at(2),verts.at(3),G);
add_edge(verts.at(0),verts.at(4),G);
add_edge(verts.at(4),verts.at(5),G);
add_edge(verts.at(5),verts.at(6),G);
add_edge(verts.at(6),verts.at(7),G);
add_edge(verts.at(7),verts.at(8),G);
cout << "vertices " << num_vertices(G) << endl;
cout << "edges " << num_edges(G) << endl;
//store depths
vector<size_t> d(num_vertices(G));
//get an index map, from Graph definition property< vertex_index_t, size_t>
typedef boost::property_map< Graph, boost::vertex_index_t>::type VertexIndexMap;
VertexIndexMap v_index = get(boost::vertex_index, G);
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d_map(d.begin(), v_index);
//Start at 0
boost::breadth_first_search(G, verts.at(0),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d_map, boost::on_tree_edge())
)));
cout << "Starting at 0" << endl;
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d.at(i) << endl;
}
vector<size_t> d2(num_vertices(G));
cout << "Starting at 4" << endl;
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d2_map(d2.begin(), v_index);
//start at 4
boost::breadth_first_search(G, verts.at(4),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d2_map, boost::on_tree_edge())
)));
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d2.at(i) << endl;
}
}
Output should look like this:
vertices 9
edges 8
Starting at 0
vertex 0 0
vertex 1 1
vertex 2 2
vertex 3 3
vertex 4 1
vertex 5 2
vertex 6 3
vertex 7 4
vertex 8 5
Starting at 4
vertex 0 0
vertex 1 0
vertex 2 0
vertex 3 0
vertex 4 0
vertex 5 1
vertex 6 2
vertex 7 3
vertex 8 4
When you start at 4 the other vertices are not reachable (directed) so the vector contains default values (0 in this case). This should work for undirected too.