Getting to the begining of the line.

Hello.
My qustion is, in a text file, if i know how many lines are there, is it possible to set position to begining of a certain line?
The line length differs.
My idea was like, to first of all count how many lines are inside the file.
Then count bytes of each line, like:

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
fstream file("Binary.bin", ios::out);
int lines = 82;//Just for example. The amount of lines inside the file.
    int line2 = 0, linecounter = 0, counter = 0, middle = lines/2;
    int pos = 0;
    char b;
    file.get(b);
   while(file)
    {
        if(line2 == middle)
        {
            pos = file.tellg();
            file.seekp(0 , ios::cur);
            //Should print out the word thats in the middle line.
            cout << "Position: "<< endl;
            line2 = 0;
            break;
        }
        if(b == '/n')
        {
            line2++;
            counter++;
        }
        else counter++;
        file.get(b);
    }


So basicly, if i had to find line 60 inside the file, i could know how many symbols are there till line 60, so that i can put the seekp after the lst symbol.

At least thats how i imagined it.

There must be an easier way to do this.
Also, how do i print out the line? I mean after ive set the position?
yeah, you could ignore the letters till the next endline 59 or 60 times, then get the position and then get back to the beginning.

First of all you have to be able to read the file, otherwise that does not work.

is it really a binary file you want to read?
windows ends his lines with \r\n, linux just with \n, do you want to count this \r?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <limits>

//...

fstream file("Binary.bin", ios::out | ios::in);
// line number if you start to count at 1
int line = 60;

if(file.is_open())
{
    // get to the position 0 in line 61
    for(int i = 0; i < line; ++i)
        file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

    int position = file.tellg(); // thats the position of the 1st character in line 61
}
Thanks, this helped alot.
I'm almost done with the task.
Ive got just one question left.


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
       


    file.open( filename.c_str());
    int first = 0, last = Lines, middle = 0, position;
    bool found = false;
    string s;

while (first <= last)
    {
        middle = (first+last)/2;
        cout << "middle: "<< middle<< endl;
        for(int i = 0; i <middle; ++i)
        file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
        file.seekg(0, ios::cur);
        getline(file, s);
        cout << s << endl;
        if(s == SearchVal)
        {
            found = true;
            break;
        }
        else if(s > SearchVal)
        {
            cout << s << " is greater then "<< SearchVal << endl;
            first = middle +1;
        }
        else
        {
            cout << s << " is smaller then "<< SearchVal << endl;
            last = middle -1;
        }
    }
//Some output etc...
    file.close ();


So, in the first run it finds the middle value and does everything just fine.
In all the next runs, middle index does change like it should, but the position is right where it was.
Like, the middle word in my text file is "mutable". When it performs the binary search, the middle index changes, but the string s value is always mutable. It just stays the same. What am i doing wrong here?
Last edited on
Line 15 does nothing due to ios::cur.
Alright so, did few edits.

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
    file.open( filename.c_str());
    int first = 0, last = Lines, middle = 0, position;
    bool found = false;
    string s;

while (first <= last)
    {
        middle = (first+last)/2;
        cout << "middle: "<< middle<< endl;
        for(int i = 0; i <middle-1; ++i)/*-1 so that it finds the exact same line, thats index is 
equal to middle.*/
        file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
        position = file.tellg();
        file.seekg(position, ios::beg); /*So it finds the position and starts counting the bytes
 from begining of the file. Like this it should go to the begining of the line with index 
middle. Shouldnt it? but it doesnt....*/
        getline(file, s);
        cout << s << endl;
        if(s == SearchVal)
        {
            found = true;
            break;
        }
        else if(s > SearchVal)
        {
            cout << s << " is greater then "<< SearchVal << endl;
            first = middle +1;
        }
        else
        {
            cout << s << " is smaller then "<< SearchVal << endl;
            last = middle -1;
        }
    }



Something is still not working as expected.
So the middle value is 42. The word inside my text file @ line 42 is "mutable".
Now it returns last 2 symbols of the word thats @ line 43 "namespace".
Last edited on
full 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
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
#include <fstream>
#include <iostream>
#include <limits>
using namespace std;

void Binary_Search(const string& filename, string SearchVal)
{
    std::fstream file;
    file.open( filename.c_str());
    if (file.is_open())
    {
        cout << "The file is opened"<< endl;
    }
    else
    {
        cout << "Error opening file"<< endl;
    }
    //This part of code below finds how many lines are inside the text file.
    int Lines = 0;
    char c;
    file.get(c);
    while(file)
    {
        if(c == '\n')
        {
            Lines++;
        }
        file.get(c);
    }
    cout << "\n"<<Lines<< endl;
    file.close ();

    file.open( filename.c_str());
    int first = 0, last = Lines, middle = 0, position;
    bool found = false;
    string s;

    while (first <= last)
    {
        middle = (first+last)/2;
        cout << "middle: "<< middle<< endl;
        for(int i = 0; i < middle-1; ++i)
        file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
        position = file.tellg();
        file.seekg(position, ios::beg);
        getline(file, s);
        cout << s << endl;
        if(s == SearchVal)
        {
            found = true;
            break;
        }
        else if(s > SearchVal)
        {
            cout << s << " is greater then "<< SearchVal << endl;
            first = middle +1;
        }
        else
        {
            cout << s << " is smaller then "<< SearchVal << endl;
            last = middle -1;
        }
    }
    if(found == true)
    {
        cout << "Tas ir c++ rezervetais vards"<< endl;
    }
    else cout << "Tas nav c++ rezervetais vards"<< endl;
    file.close ();

}

int main ()
{
    char c;
    fstream fin ("rezervetie.txt", ios::in);
    fin.close ();
    string ievade;
    cout << "Input the word to compare with the list: ";
    cin >> ievade;
    Binary_Search("rezervetie.txt", ievade);
    return 0;
}


This is how my reservetie.txt looks http://pastebin.com/eySrLP5B
Line 45 has no effect. I'd suggest that you cout the position.

Your current logic is so that it requires a file.seekg(0, ios::beg); at the beginning of each iteration.

Take a closer look at the evaluation of line 53...
Alright so, i guess i found the mistake @ line 53. Replaced the comparision with strncmp.
That position seems to be working at the first time. Rest of the times its equal to -1.
My idea was that, with the ignore thing it goes to the correct line, the it gets the position of the starting symbol, then with file.seekg(position, ios::beg) id set the position where it should be. And then id just get the string of that line by getline. I dont realy get it...
It seems that in the first time it finds the value just fine. It also sets the value of string s correct. Rest of the times position goes to -1...

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
void Binary_Search(const string& filename, string SearchVal)
{
    std::fstream file;
    file.open( filename.c_str());
    if (file.is_open())
    {
        cout << "The file is opened"<< endl;
    }
    else
    {
        cout << "Error opening file"<< endl;
    }
    int Lines = 0;
    char c;
    file.get(c);
    while(file)
    {
        if(c == '\n')
        {
            Lines++;
        }
        file.get(c);
    }
    cout << "\n"<<Lines<< endl;
    file.close ();

    file.open( filename.c_str());
    int first = 0, last = Lines, middle = 0, position;
    bool found = false;
    string s;

    while (first <= last)
    {
        middle = (first+last)/2;
        cout << "middle: "<< middle<< endl;
        for(int i = 0; i < middle-1; ++i)
        file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
        position = file.tellg();
        cout <<"Position: " <<position << endl;
        getline(file, s);
        cout << s << endl;
        if(strncmp(s.c_str(), SearchVal.c_str(),30)==0)
        {
            found = true;
            break;
        }
        else if(strcmp(s.c_str(), SearchVal.c_str())>0)
        {
            cout << s << " is greater then "<< SearchVal << endl;
            first = middle +1;
        }
        else if (strcmp(s.c_str(), SearchVal.c_str())<0)
        {
            cout << s << " is smaller then "<< SearchVal << endl;
            last = middle -1;
        }
    }
    if(found == true)
    {
        cout << "Not a c++ reserved word."<< endl;
    }
    else cout << "Is a c++ reserved word."<< endl;
    file.close ();

}


Thats what i did with the function.
Well, you can basically see the finish line, but you keep turning left, right, backward...

Alright so, i guess i found the mistake @ line 53. Replaced the comparision with strncmp.
For heaven's sake no.

Rest of the times its equal to -1.
This indicates an error. You should not see that.

This is the working 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
26
27
    while (first <= last)
    {
        middle = (first+last)/2; // Note: This calculates the index from the top
        file.seekg(0, ios::beg); // So you must set the read pointer to the top

        cout << "middle: "<< middle<< endl;
        for(int i = 0; i < middle-1; ++i)
        file.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
        cout << "position = "<< file.tellg() << endl; // Note: for debugging, might be removed that later
        getline(file, s);
        cout << s << endl;
        if(s == SearchVal)
        {
            found = true;
            break;
        }
        else if(s > SearchVal)
        {
            cout << s << " is greater then "<< SearchVal << endl;
            last = middle -1; // Note: exchanged
        }
        else
        {
            cout << s << " is smaller then "<< SearchVal << endl;
            first = middle +1; // Note: exchanged
        }
    }
Topic archived. No new replies allowed.