Reading size from text file

I have to read in this order, an int and then a string on a text file which contains multiple lines

My issue is: I'm guessing eof counts as a char to read? So when my program is reading the elements and storing them into their appropriate variables, it will read the eof, putting a complete int junk onto my array. I think this is crashing my program

For example, if the text file contains:

1 fox
2 dog
3 cat

My program will output:

1 fox
2 dog
3 cat
-29394818484

size: 4


My code:
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
void CopyData(string Fname, int &cap)
{
	PriorityQueue Data;
	string names[50];
	int pq[50];
	int size = 0;

	fstream f;
	f.open(Fname, ios::in);

	while (!f.eof() && pq[size] != NULL) //as long as we are not at end of file
	{
		
		f >> pq[size];
		getline(f, names[size]);
		Data.insert(names[size], pq[size]);
		cout << pq[size] << " " << names[size] << endl;
		size++;
		
	}
	f.close();
	cout << size; //to account for end of flag char
	delete[] names;
	delete[]pq;
}
You either can read a line, or not. Accept no partials.

While macro NULL does expand to 0, is it really the intuitive way to compare against an int?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
constexpr size_t N {50};
int pq[N];
std::string names[N];
size_t size {0};
int num;
char dummy;
std::string text;
std::ifstream f( Fname );
while ( size < N && f >> num >> dum && std::getline( f, text ) ) {
  // we get into loop if and only if the read of both num and text was a success
  // and there is room to write them to
  pq[size] = num;
  names[size++] = text;
}
The problem is also because you are looping on EOF.

The correct loop should always be functionally equivalent to:

1
2
3
4
5
6
loop
{
  attempt to read from file;  // 1
  if (failed to read) break;    // 2
  do stuff;
}

C++ tends to make this very easy, since things like getline(...) and cin >> foo return the stream as a result of their function, so they do both 1 and 2.

1
2
3
4
while (getline( f, s ))  // 1: read into s, 2: break on fail
{
  ...
}
1
2
3
while (cin >> x)  // 1: read into x, 2: break on fail
{
}

You can typically design input classes or functions to do it just as conveniently.
Otherwise you must write the loop out in all its gory detail. For example, this reads a bunch of integers, each on its own line with nothing else, and complains if anything went wrong:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vector <int> ns;
while (true)
{
  int n;
  string s;
  if (!getline( f, s )) break;

  istringstream ss( trim( s ) );
  ss >> n;
  if (!ss.eof())
  {
    f.setstate( ios::failbit );
    break;
  }
  
  ns.push_back( n );
}

if (!f.eof())
{
  cout << "Something went wrong.\n";
  return 1;
}

Meh. Hope this helps.
Hm, I don't really understand.

The condition for my loop is correct no? As long as the file doesn't read the eof flag...

I am still confused
If your condition were correct, then you would have no problem.

Even though your line 11 would evaluate to true, either of lines 14 or 15 could fail, but don't check that. Hence the garbage.
Topic archived. No new replies allowed.