Loading into array

I am having a bit of trouble trying to load a text file with various ip address into an array of strings. Several of these ip addresses repeat throughout the text file. My problem lies in figuring out an algorithm to check for a duplicate BEFORE loading into the string array. The ip address cannot repeat in a SEQUENCE but CAN repeat in another way. So basically I need to check and see if the IP address is already in the last index loaded, only the last..

Here's the function that is supposed to take care of loading the text into the array.

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
void LogData::get_weblog_data()
{

//myArray = new string[1];
numAllocated = 1;
numUsed = 0;




ifstream myfile("weblog.csc226"); //opening the file.

if (myfile.is_open()) //if the file is open
{
    while (!myfile.eof()) //while the end of file is NOT reached
  {
     getline (myfile, myArray[numUsed]);
     if(myArray[numUsed] == myArray[numUsed])

    cout << myArray[numUsed].substr(0, 15) << '\n';
   
    numUsed++;
    
if (numUsed == numAllocated)

   doubleCapacity();
    }

}

//cout << numUsed << endl;
}
Last edited on
1
2
// wrong!  This is one of the most common errors with while loops that I see posted in these example programs.    Take a look at the following link to find out why.
while (!myfile.eof())

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5

This following line confuses me. What do you think that this statement does?
myArray = new string[1];

Instead, make a temp string object to use with getline and a list or deque for the actual string objects.

std::string inputStr; // use with getline
std::deque<std::string> myArray; // use this as your array or use std::list if you prefer.

Keep in mind that once you successfully fill the inputStr, you'll need to do your test with the last element in the container prior to insertion.
http://www.cplusplus.com/reference/stl/list/
http://www.cplusplus.com/reference/stl/deque
kempofighter wrote:
wrong! This is one of the most common errors with while loops that I see posted in these example programs.
I won't say it's wrong since OP is using getline() instead of >> operator.

the tutorial itself uses this technique
http://cplusplus.com/doc/tutorial/files/
kempofighter- Sorry ignore that statement. It's leftover code

What I need help with however, is coming up with a algorithm to check if the last loaded string isn't a duplicate before loading it into the array. I'm not sure how to go about "testing" it.

And yes, I used the eof() because I saw it used in one of the tutorials here; otherwise I thought the file would not be completely read. I've now replaced it and seems to be working the same; thanks for letting me know. So, can anyone offer any help?
The tutorial is wrong. getline should be within the while loop otherwise the loop will print duplicate data. getline has to fail and set the EOF bit once before the loop can end.
Use std::string and make MyArray a deque of string objects as I already suggested. You can easily compare strings. You know how to find the last element of an array correct? The requirement seems very simple. After each read, compare the new string against the last element of the array using operator==. It is that simple.
http://cplusplus.com/reference/string/operators/
kempofighter +1
Also, looping against EOF is a bad idea because that can lead to an infinite loop when the file fails.
Loop against good(), and then determine why the loop terminated: eof() or fail().
So this code from the tutorial is the wrong way to do it? And using good() instead of eof() will make it correct? Well either way does not print duplicate data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("example.txt");
  if (myfile.is_open())
  {
    while (! myfile.eof() )
    {
      getline (myfile,line);
      cout << line << endl;
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("example.txt");
  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      getline (myfile,line);
      cout << line << endl;
    }
    myfile.close();
  }

  else cout << "Unable to open file";

  return 0;
}
...yes

Technically, this case only works when using getline(). The common error is to enter the loop (because the file is still 'good'), attempt to read it, and then use whatever was read (even though the reading may have failed).

1
2
3
4
5
6
// BAD CODE
while (myfile.good())
  {
  myfile >> fooey;
  foos.push_back( fooey );  // wait! what if line 4 failed?
  }

The example code in blackcoder41's post above does the same thing, but since a text file has, technically, n+1 lines (where n is the number of newlines in the file), the getline() function cannot fail if called when the file is good().

Unfortunately that is the only case where that is the correct way to do it.

The proper way to do things is to always check for failure immediately after attempting input. There are two ways you can do this:

1
2
3
4
while (myfile >> fooey)  // only continue if input is successful
  {
  foos.push_back( fooey );
  }
1
2
3
4
5
6
7
while (true)
  {
  myfile >> fooey;      // try to get input
  if (!myfile) break;   // only continue if input was successful

  foos.push_back( fooey );
  }

After the loop ends you can check to see if termination was due to eof() or some other fail()ure.

The method you choose depends on what you are doing, and how you enter the loop. Here is an example: http://www.cplusplus.com/forum/beginner/18258/#msg92955

Variations abound.

Hope this helps.
Followup question, why is this a valid syntax while (myfile >> fooey). Isn't is that the while loop expects a boolean, but >> operator here returns istream
When used in a condition, the istream is converted to a void*, which is NULL if the stream is bad(), and non NULL otherwise.

http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/

It is just a more syntax-friendly way of saying while ((myfile >> fooey).good()).

:-)
Duoas has explained it well but I do not know why getline example actually works in the above example. This is what bothers me about iostreams in c++ is that you get such inconsistent behavior depending on which method you use to extract data. getline should read and discard the \n of the last line like it does for any other line but I fail to see how the EOF is being properly set when it reads the last line. I thought that EOF is not supposed to be set until you attempt to read beyond the end of the file not when you read the last character. Therefore it does appear that my understanding was partially incorrect. At least in the case of getline somehow EOF is set when the last '\n' is read. That seems odd to me. How can it know that the end was reached without having attempted to read past the end? I don't understand that part.

HOWEVER, the tutorial is still bad in this case. It should not be encouraging people to write loops like that. It is a bad habit and we see posts on this message board with the aforementioned looping problem quite often.
Last edited on
I keep forgetting that getline() has fishy behavior depending on certain factors. That bothers me too.
Topic archived. No new replies allowed.