Hello Orion98,
I have been working on your program for awhile.
coder777 wrote: |
---|
So the loop on line 31 is wrong.
|
I agree and for 2 reasons:
First the ".size()" function returns a "size_t" type variable. If you accept 1 guarantee that would be that "size_t" is an "unsigned" type. After that the actual type is implementation defined. So a "size_t" could be and "unsigned int" or "unsigned long" or maybe some other type. It all depends on your header files and compiler.
Second after working with it for awhile I realized that the for loop is not necessary as the following code and output will show.
Trying to keep with what you have done, for the most part, I came up with this. For now some of the original code I have left. Mostly as an idea of what is wrong. Other parts I have changed or added.
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
|
int main()
{
ifstream inFile("Shapes.input.txt");
ofstream outFile("Shapes.output.txt");
//inFile.open("Shapes.input.txt");
//outFile.open("Shapes.output.txt");
// <--- How do you know that the files are open and usable?
std::cout << std::fixed << std::showpoint << std::setprecision(3); // <--- "showpoint" is optional if "setprecision" is > 0.
outFile << std::fixed << std::showpoint << std::setprecision(3);
//cout.precision(2);
//cout << fixed;
//outFile.precision(2);
//outFile << fixed;
string s; // <--- Had to move up to here, so the while loop would work.
//while (!inFile.eof()) // <--- Does not work the way that you are thinking. Does not catch "eof" when it should.
while (std::getline(inFile, s))
{
//getline(inFile, s);
if (s == "") // <--- Accounts for blank lines in the input file.
continue;
vector<string> tokens = parseString(s);
constexpr size_t MIN_VEC_SIZE{ 2 }; // <--- Added.
double length{}, width{}, height{}, area{}, peri{}, volume{}; // <--- Changed.
const enum { OBJECT, LENGTH, WIDTH, HEIGHT }; // <--- Added.
for (size_t i = 0; i < tokens.size(); i++)
{
// cout << "token["<< i <<"] = " << tokens[i] << '\n';
if (tokens[OBJECT] == "SQUARE") // <--- This does not work when "i" becomes 1. Same for the "else if"s.
{
if (tokens.size() < MIN_VEC_SIZE)
{
std::cout << "\n No length given. Set to (1).\n\n"; // <--- Just thought of this. Optional at your discretion.
length = 1.0;
}
else
{
try
{
length = stod(tokens[LENGTH]);
}
catch (const std::exception& e)
{
std::cerr <<
"\n " << tokens[OBJECT] <<
": " << e.what() << ". For length.";
std::cerr << "\n"; // <--- Used as a break point, but should be at the end of the above line.
length = 1.0;
}
}
area = length * length;
peri = 4.0 * length;
cout
<< tokens[OBJECT] << ":\n side = " << length
<< "\n area = " << area
<< "\n perimeter = "
<< peri << "\n\n";
outFile << tokens[OBJECT] << ":\n side = " << length << "\n area = " << area
<< "\n perimeter = " << peri << '\n';
break;
}
|
Line 37 is the first example why the for loop does not work.
Given the input line of
SQUARE 14.5 344
. First time through the loop "i" is (0) zero and everything is fine. You are comparing "SQUARE" to "SQUARE". 2nd time through the loop "i" is (1) and you are comparing "14.5" to "SQUARE". This will bypass everything until you reach the else at the end and display
cout << tokens[i] << ": invalid object" << "\n\n";
.
Notice the use of the new line (\n)s over the "endl"s. Try to avoid using the "endl"s as this is a function that takes time to process.
Line 39 is to determine if the vector is large enough to hold a number that can be changed from a "string" to a "double". If not it sets "length" to (1) for the calculations.
I do not use the "try/catch" much, but with function like "sto?" it is very useful in preventing a runtime crash of the program. The "catch" part allows you to deal with the problem and then continue with the program.
As
coder777 pointed out your if/else if statements never have a value for the variables "length", "width" and "height". This is a way of giving these variables a proper value to use.
B4 I forget I should mention it is always a good idea to initialize
ALL your variable when defined. It saves on headaches later.
Not sure if you have studied "enum"s yet, but it is a way to give a number a name to help the code be more readable and understandable. The above code is 1 example of this.
The "break" statement on line 75 leaves the for loop when you are finished and ends up back at the while condition. Having to add this line is why the for loop is not needed.
This is part of the output I have managed so far:
SQUARE:
side = 14.500
area = 210.250
perimeter = 58.000
SQUARE:
side = 1.000
area = 1.000
perimeter = 4.000
RECTANGLE:
length = 14.500
width = 4.650
area = 67.425
perimeter = 38.300
14.5: invalid object
4.65: invalid object
DIMENSIONS: invalid object
|
In the first Square you are using the numbers from the file. In the 2nd Square it is using (1) because there is nothing from the input file to use.
For the Rectangle the "14.5: invalid object" is what happens when the for loop is allowed to continue. I missed the "break" for this the first time around.
The last line is what you should get when the "object" type does not match anything in the "if/else if" statements.
Another part I noticed is in the input file you have "CIRCLE", but your else if is:
else if (tokens[OBJECT] == "Circle")
. Only the "C" is a match. After that it fails. Be careful of how you spell words. Case usually matters.
The only other object type I worked on is "BOX".
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
|
else if (tokens[i] == "BOX")
{
try
{
length = std::stod(tokens[1]);
}
catch (const std::exception& e)
{
std::cerr <<
"\n " << tokens[0] <<
": " << e.what() << ". For length.";
std::cerr << "\n\n";
length = 0;
}
try
{
width = std::stod(tokens[2]);
}
catch (const std::exception& e)
{
std::cerr <<
"\n " << tokens[0] <<
": " << e.what() << ". For width.";
std::cerr << "\n";
width = 0;
}
try
{
height = std::stod(tokens[3]);
}
catch (const std::exception& e)
{
std::cerr <<
"\n " << tokens[0] <<
": " << e.what() << ". For height.";
std::cerr << "\n";
height = 0;
}
//area = 2.0 * (length * width) + (length * height) + (width * height);
area = (2.0 * (length * width)) + (2.0 * (length * height)) + (2.0 * (width * height));
|
I am not sure what you were thinking for line 48, but it does not work. Line 49 is the way I interpret the the formula that I found, which is
SA = 2lw + 2lh + 2hw
which seems to be correct.
I used 3 try/catch here, but you could combine it all into just 1 if you want, but that would be more difficult to figure out which variable is the problem.
It would be easy to remove the for loop and the break statements.
That should give you something to think about.
Andy