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.
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.
#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <iomanip>
#include <cstdio>
unsignedint roman_to_int( std::string roman ) ; // TO DO
std::string int_to_roman( unsignedint 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
{
unsignedint 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
staticconst std::size_t NCHARS_PER_LINE = 20 ;
constauto nchars_roman = roman.size() ; // number of characters in the string
constauto 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
***********************************************************************************/
}