How to read this format of integers from file

I am doing a prim algorithm minimum spanning tree


int arr[30];
ifstream is("data.txt");
int cnt= 0;
int x;

while (cnt < arr[30] && is >> x)

arr[cnt++] = x;

cout<<"The integers are:"<<"\n";
for (int i = 0; i < cnt; i++) {
cout << arr[i] <<' ';
}

is.close();

I only know how to read them if just a line of int like above
How do i read from file with this text file format

6
1 2 4
1 3 2
1 5 3
2 4 5
3 4 1
3 5 6
3 6 3
4 6 6
5 6 2
0 0 0

The first row shows an integer, being the number of nodes in the graph.
The remaining rows show a sequence of sets of three integers, where the first two are node numbers and
the third number is a weight.
Input of edges is terminated by the sequence 0 0 0.
Note: the graph is undirected so an edge from i to j is also an edge from j to i.
Last edited on
This will read the set sequence into a vector and display the data:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <fstream>
#include <iostream>
#include <vector>

struct Seq {
	int node1 {};
	int node2 {};
	int weight {};
};

std::istream& operator>>(std::istream& os, Seq& seq)
{
	return os >> seq.node1 >> seq.node2 >> seq.weight;
}

std::ostream& operator<<(std::ostream& os, const Seq& seq)
{
	return os << seq.node1 << "  " << seq.node2 << "  " << seq.weight;
}

int main()
{
	std::ifstream ifs("data.txt");

	if (!ifs.is_open()) {
		std::cout << "Cannot open file\n";
		return 1;
	}

	int noNodes {};
	std::vector<Seq> nodes;

	ifs >> noNodes;

	for (Seq seq; (ifs >> seq) && seq.node1 != 0; nodes.push_back(seq));

	std::cout << "No nodes: " << noNodes << '\n';

	for (const auto& n : nodes)
		std::cout << n << '\n';
}



No nodes: 6
1  2  4
1  3  2
1  5  3
2  4  5
3  4  1
3  5  6
3  6  3
4  6  6
5  6  2

Hi seeplus,thank you!I roughly get an idea but I haven't learn vector yet ,is there a way without using< vector>
lychee, if you define an array as
int arr[30];
then valid indices are 0 through 29.

In other words, your while loop's while (cnt < arr[30]) condition makes no sense, because 30 itself is not a valid array index.
You probably just meant while (cnt < 30 && is >> x)

If you wish to avoid vectors, then just make sure your array is big enough to store the necessary data, and make
Seq nodes[30]; (based off seeplus' code)
and access nodes[some_index] instead of calling push_back.

again, modifying seeplus's code, not tested...
1
2
3
4
5
6
7
Seq nodes[10];
Seq seq;
int count = 0;
while (count < 10 && ifs >> seq && seq.node1 != 0)
{
    nodes[count++] = seq;
}
Last edited on
lychee,

A vector is just a dynamic array that can grow to what ever size you need. You can replace it with an ordinary array but you need to be careful to stay in the bounds of the array. And that is exactly the problem you are having. ar[30] is out of bounds because indexing starts at zero and ends at 29. Just changing int ar[30] to int ar[31] would fix this particular problem. Learning to use a dynamic array will make sure you never make this mistake again.
Hello lychee,

What you have to deal with is the first (6) in the file. After that Ganado's point about the while loop needs to be addressed.

To start with: int arr[30]; this creates an uninitialized array of 30 elements. Each element may likely have the value of (-858993460), this could be different on your computer or any given time the program runs, but not a usable value.

So when you use while (cnt < arr[30] && is >> x) Not only is 30 past the end of the array and you have not idea what is stored there, it will most likely be garbage to the program, it will turn that garbage value into an int before it compares it "cnt". Even changing it to (29) you will still be using a garbage value.

Having very little to work with I put this together:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
//#include <iomanip>  // <--- Not needed at this time, but could be useful.
#include <string>
#include <limits>

#include <fstream>

int main()
{
    int arr[30]{};  // <--- Initializes each element of the array to the type of zero the compiler deems appropriate.

    std::ifstream is("data.txt");
    // <--- How do you know that the file is open?

    int cnt = 0, numberOfNodes{};
    int x{};

    is >> numberOfNodes;  // <--- Reads first number in the file, first line.

    while (cnt < 30 && is >> x)
    {  // <--- A good idea in case you want to add more. Not a problem for just 1 line. Can be left out if you want
        arr[cnt++] = x;
    }

    std::cout <<
        "\n The number of nodes is: " << numberOfNodes << "\n\n"
        " The integers are:" << "\n";


    for (int i = 0; i < cnt; i++)
    {
        std::cout << "   " << arr[i] << ((i + 1) % 3 ? "" : "\n");
    }

    //is.close();  // <--- Not necessary as the dtor will close the file stream when the function looses scope.


	// <--- Keeps console window open when running in debug mode on Visual Studio. Or a good way to pause the program.
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
	//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue: ";
	std::cin.get();

	return 0;  // <--- Not required, but makes a good break point.
}


Andy
@lychee,
Wouldn’t you be better working out how you you are going to implement Prim’s algorithm first? Then you would know what sort of structure to read into.

There are, after all, a huge number of ways of representing graphs computationally. However, a 1-d integer array isn't one of them.
Last edited on
Using an array rather than a vector:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <fstream>
#include <iostream>
#include <vector>

struct Seq {
	int node1 {};
	int node2 {};
	int weight {};
};

std::istream& operator>>(std::istream& os, Seq& seq)
{
	return os >> seq.node1 >> seq.node2 >> seq.weight;
}

std::ostream& operator<<(std::ostream& os, const Seq& seq)
{
	return os << seq.node1 << "  " << seq.node2 << "  " << seq.weight;
}

int main()
{
	std::ifstream ifs("data.txt");

	if (!ifs.is_open()) {
		std::cout << "Cannot open file\n";
		return 1;
	}

	const size_t maxLines {10};

	int noNodes {};
	Seq nodes[maxLines] {};
	size_t numLines {};

	ifs >> noNodes;

	for (Seq seq; (ifs >> seq) && seq.node1 != 0 && numLines < maxLines; nodes[numLines++] = seq);

	std::cout << "No nodes: " << noNodes << '\n';

	for (size_t n = 0; n < numLines; ++n)
		std::cout << nodes[n] << '\n';
}


But note @lastchance's comment re an appropriate data structure. This is just example code of reading the file and checking that the data has been read OK.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <set>
#include <limits>
using namespace std;

using NodeType = int;

struct Edge
{
   NodeType dest;
   double wt;
};
bool operator < ( Edge a, Edge b ) { return a.dest < b.dest; }

using Graph = map< NodeType, set<Edge> >;

//======================================================================

void read( istream &in, Graph &graph )
{
   int n;
   in >> n;           // ignored in my code, as node number isn't fixed
   NodeType a, b;
   double wt;
   while( in >> a >> b >> wt && !( a == 0 && b == 0 ) )    // messy
   {
      graph[a].insert( { b, wt } );
      graph[b].insert( { a, wt } );
   }
}

//======================================================================

void write( ostream &out, const Graph &graph )
{
   for ( const auto &pr : graph )
   {
      for ( const Edge &edge : pr.second )
      {
         if ( pr.first < edge.dest ) out << pr.first << '\t' << edge.dest << '\t' << edge.wt << '\n';
      }
   }
}

//======================================================================

double dist( const Graph &graph )
{
   double d = 0;
   for ( const auto &pr : graph )
   {
      for ( const Edge &edge : pr.second ) 
      {
         if ( pr.first < edge.dest ) d += edge.wt;
      }
   }
   return d;
}

//======================================================================

bool Prim( Graph &graph, Graph &MST )
{
   MST.clear();

   set<NodeType> available;
   for ( auto &pr : graph ) available.insert( pr.first );

   NodeType start = *available.begin();
   available.erase( start );
   MST[start] = {};

   while( !available.empty() )
   {
      // Find shortest distance from a node in current MST to a node outside current MST
      double minDist = numeric_limits<double>::max();
      NodeType minNode;
      Edge minEdge;
      bool found = false;
      for ( auto &pr : MST )
      {
         for ( Edge edge : graph[pr.first] )
         {
            if ( available.find( edge.dest ) != available.end() && edge.wt < minDist )
            {
               minNode = pr.first;
               minEdge = edge;
               minDist = edge.wt;
               found = true;
            }
         }
      }
      if ( !found ) return false;
      available.erase( minEdge.dest );
      MST[minNode].insert( minEdge );
      MST[minEdge.dest].insert( { minNode, minDist } );
   }

   return true;
}

//======================================================================

int main()
{
// ifstream in( "data.txt" );
   istringstream in( "6    \n"
                     "1 2 4\n"
                     "1 3 2\n"
                     "1 5 3\n"
                     "2 4 5\n"
                     "3 4 1\n"
                     "3 5 6\n"
                     "3 6 3\n"
                     "4 6 6\n"
                     "5 6 2\n"
                     "0 0 0\n" );

   Graph G;
   read( in, G );
   cout << "Original graph:\n";
   write( cout, G );

   Graph P;
   if ( Prim( G, P ) )
   {
      cout << "\nMinimum spanning tree (size " << dist( P ) << ")\n";
      write( cout,  P );
   }
}


Original graph:
1	2	4
1	3	2
1	5	3
2	4	5
3	4	1
3	5	6
3	6	3
4	6	6
5	6	2

Minimum spanning tree (size 12)
1	2	4
1	3	2
1	5	3
3	4	1
5	6	2
Last edited on
Thank you everyone!!
Topic archived. No new replies allowed.