If nothing else, there is a problem with the error detection. I'd start with changing that first: Parse the entire string and make sure its only correct input characters first. |
Error handling has been a big problem for me, but mainly because the Bjarne Stroustrup's header stopped working for me, and I had to come up with my own method to circumvent using the file. So I'm not surprised if I've handled it less than optimally. This is what my error handling function looks like:
1 2 3 4 5 6 7 8 9 10
|
void error_throw(string s1, string s2, double d)
{
ostringstream convert;// stream used for the conversion ( output string stream )#include <sstream>
convert << "ERROR: ";
if (s1 != no_string) convert << s1;
if (s2 != no_string) convert << s2;
if (d != no_int) convert << d;
throw convert.str(); //return content of stream
}
|
I'm not completely sure what you mean, do you want me to insert every argument immediately into the ostringstream? I did notice that the error message sometimes seems to have a line skip, but didn't know what the cause was.
Are you sure what you posted is the original code? |
I'm not sure actually, I think I may have made some changes shortly before I made the post. In any case, I went through the code again and came up with a lot of changes.
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
|
int get_1s(istream& is)
{
char ch;
string s;
is.get(ch);
if (!isalpha(ch)){ is.unget(); return 0; }
s = ch;
while (is.get(ch) && isalpha(ch)) s += ch;
is.unget();
for (Roman_int ri : roman_ones) if (s == ri.roman) return ri.arabic;
error_throw(s, " is not a roman numeral", no_int);
}
//------------------------------------------------------------------------------
int get_10s(istream& is)
{
string s;
char ch;
is.get(ch);
if (!isalpha(ch)){ is.unget(); return 0; }
s = ch;
switch (ch) {
case roman_10:
while (is.get(ch) && (ch == roman_10 || ch == roman_50 || ch == roman_100)) s += ch;
is.unget();
break;
case roman_50:
while (is.get(ch) && ch == roman_10) s += ch;
is.unget();
break;
default: { is.unget(); return get_1s(is); }
}
for (Roman_int ri : roman_tens) if (s == ri.roman) return ri.arabic + get_1s(is);
error_throw(s, " is not a roman numeral", no_int);
}
//------------------------------------------------------------------------------
int get_100s(istream& is)
{
string s;
char ch;
is.get(ch);
if (!isalpha(ch)){ is.unget(); return 0; }
s = ch;
switch (ch) {
case roman_100:
while (is.get(ch) && (ch == roman_100 || ch == roman_500 || ch == roman_1000)) s += ch;
is.unget();
break;
case roman_500:
while (is.get(ch) && ch == roman_100) s += ch;
is.unget();
break;
default: { is.unget(); return get_10s(is); }
}
for (Roman_int ri : roman_hundreds) if (s == ri.roman) return ri.arabic + get_10s(is);
error_throw(s, " is not a roman numeral", no_int);
}
//------------------------------------------------------------------------------
int get_1000s(istream& is)
{
string s;
char ch;
is.get(ch);
s = ch;
while (is.get(ch) && ch == roman_1000) s += ch;
is.unget();
for (Roman_int ri : roman_thousands) if (s == ri.roman) return ri.arabic + get_100s(is);
error_throw(s, " is not a roman numeral", no_int);
}
|
The reason that roman 20 and probably 200 failed was because it wasn't roman 50, 100, 500, or thousand and the if statement would return it to the stream.
Then the next function would find it and throw and error.
I guess it is basically the same solution as yours, except that I choose to simply check every legal character, as I concluded that a real number wouldn't affect the following steps.
I'm was able to run through a list of every roman numeral from 1 to 3999, which is the reason that main reads from a file:
https://pastebin.com/FUmaPWcp
Output file:
https://pastebin.com/jbGM2Kbr
The current code:
main.cpp v. 2
https://pastebin.com/avZLk6Cz
Roman_int.cpp v. 2
https://pastebin.com/FsQLEk3E
The headers should be identical.