File pointer not going to right place

I am trying to convert between Arabic and Roman numerals based off of what the line in the file gives me. My problem is that the file get pointer is going to far after the second pass. I am using getline currently to go to the next line of the file. Is there a better way of going to the next line of the file without using getline in this case and what might be causing the pointer to be going to far?

Thanks in advance and if you need any more information please feel free to ask.

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
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int convertRoman(char romanNumeral[]);
string convertArabic(int num);

const int STRING_SIZE = 15;

int main()
{
    fstream file("numbers.txt", ios::in | ios::out | ios::binary);
    bool eof = false;
    int position = 0, sum, num;
    char romanNumeral[STRING_SIZE];
    string romanConversion, line;

    if(file.good())
    {
        while (!eof)
        {
            file.peek();
            eof = file.eof();

            if (file.peek() == ' ')
            {
                file.seekg(position+16, ios::beg);
                file >> num;
                file.seekp(position, ios::beg);
                romanConversion = convertArabic(num);
                file << romanConversion;
            }
            else
            {
                for (int i = 0; i <= STRING_SIZE; i++)
                {
                    romanNumeral[i] = file.get();
                    position++;
                }
                sum = convertRoman(romanNumeral);
                file << sum;
            }
            getline(file, line);
            position = file.tellg();
            file.seekg(position, ios::beg);
        }
        file.close();
    }
    return 0;
}


Here is the test sample I am using:

XXVII
123
MCLXV
1975

* there should be 20 characters per line with roman numerals on the left and numbers on the right

And here is what it should look like after:

XXVII 27
CXXIII 123
MCLXV 1165
MCMLXXV 1975

* there should be 20 characters per line

Last edited on
Hello kayo2,

First off do not loop on "eof" it will most times not work the way you are thinking. Usually by the time the while condition sees "eof" you will have processed the last read twice.

It looks to me like you are trying to read a textfile in binary mode which will make things difficult because a binary read is in chunks where "getline" will read a whole line up to and including the new line character.

It would be easier to just open the file in text mode and read each line with "getline". I would also recommend opening a separate file for output until you better understand using files.

Hope that helps,

Andy
Thanks for your help. If you don't mind me asking, what would you suggest using instead of eof in my loop?

Again thanks for the help.
Something like this, perhaps:

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
#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <iomanip>
#include <cstdio>

unsigned int roman_to_int( std::string roman ) ; // TO DO
std::string int_to_roman( unsigned int n ) ; // TO DO

std::string trim( std::string str ) // trim leading and trailing white spaces
{
    // get to the first non white space character
    std::size_t pos = 0 ;
    while( pos < str.size() && std::isspace( str[pos] ) ) ++pos ;

    // remove trailing white space characters
    while( !str.empty() && std::isspace( str[pos] ) ) str.pop_back() ;

    // return the tail starting at the first non white space character
    return str.substr(pos) ;
}

int main()
{
    const std::string in_file_name = "numbers.txt" ;
    const std::string out_file_name = "converted_numbers.txt" ;

    {
        std::ifstream in_file(in_file_name) ;
        std::ofstream out_file(out_file_name) ;

        std::string line ;
        // use this instead of looping on eof
        while( std::getline( in_file, line ) ) // for each line in the input file
        {
            unsigned int number = 0 ;
            std::string roman ;

            // 20 characters per line with roman numerals on the left and numbers on the right
            // ergo, if the first character is a space, this must be a number
            if( !line.empty() && line.front() == ' ' ) // this line contains a number
            {
                number = std::stoul(line) ; // convert the decimal digits in the line to a number
                roman = int_to_roman(number) ; // convert the number to roman
            }
            else // this line contains roman numerals
            {
                roman = trim(line) ; // get the roman numerals
                number = roman_to_int(roman) ; // convert roman numerals to number
            }

            // * there should be 20 characters per line
            static const std::size_t NCHARS_PER_LINE = 20 ;
            const auto nchars_roman = roman.size() ; // number of characters in the string
            const auto space_left_for_number = NCHARS_PER_LINE - nchars_roman ;

            // with roman numerals on the left and numbers on the right
            out_file << roman << std::setw(space_left_for_number) << number << '\n' ;
        }
    } // in_file and out_file are now closed

    // uncomment this if the contents of the original input file should be  replaced
    // with the contents of the output file
    /********************************************************************************

    // create a back up of the input file
    const std::string backup_file_name = in_file_name + ".bak" ;
    std::remove( backup_file_name.c_str() ) ; // remove a previous back up file if it is presemt
                     // we assume that this file won't be currently open in another process
    std::rename( in_file_name.c_str(), backup_file_name.c_str() ) ; // rename the input file

    // and rename the output file
    std::remove( in_file_name.c_str() ) ; // remove the input file
    std::rename( out_file_name.c_str(), in_file_name.c_str() ) ; // rename the output file
    ***********************************************************************************/
}
Last edited on
Topic archived. No new replies allowed.