Hello TheJast,
Sorry this took me longer than I expected.
Working with the program I did change some things around.
To start with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <chrono> // <--- Optional.
#include <thread> // <--- Optional.
using namespace std; // <--- Best not to use.
// A recent post that is worth reading. http://www.cplusplus.com/forum/beginner/258335/
enum stateType { newToken, resWord, variable, integer, real, delimiter, endState };
enum charType { letter, digit, period, delim, blank, pod, eoln, illegal, endChar };
constexpr int ROW{ 6 }; // Or constexpr int ROW{ endState };
constexpr int COL{ 8 }; // Or constexpr int COL{ endChar};
// <--- I would suggest using the uncommented part.
const std::string ACTION_HEADINGS{ " Letter Digit Period Delimiter Blank POD EOLN Illegal" };
const std::string STATE_HEADINGS{ " Letter Digit Period Delimiter Blank POD EOLN Illegal" };
template <typename x>
|
At the moment I do not see any problem with "enum"s, but I am not making use of all the functions.
I would prefer using lines 15 and 16 when dealing with arrays. If anything in the "enum"s change it will affect the arrays and other parts of the program,
Lines 19 and 20 Your program uses a for loop and the loop counter to call a function to change a number into a word. This is nice, but the "setw" in the for loop does not allow for the best positioning of the heading. These lines allow the adjustment of the headings as needed by varying the spaces between words.
The "readEmAction" function for the most part works fine as best as I can tell although I did change some of it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
void readEmAction(int action[ROW][COL])
{
const std::string inFileName{ "action.dat" };
std::ifstream inFile(inFileName);
if (!inFile)
{
std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3)); // <--- Needs header files chrono" and "thread". Optional as is the header files.
/*return 1;*/ exit(1); // If not in "main".
}
for (int row = 0; row < ROW; row++)
{
for (int col = 0; col < COL; col++)
{
inFile >> action[row][col];
}
}
}
|
Lines 3 - 12 I added. When dealing with an input file you need to check that the file stream is open and usable before you proceed. Otherwise you could reach the for loops and it would not be able to read from the file, but still store something in the array. Depending on which C++ standard you are using will determine what is stored in the array. Either way it would be something that you do not want.
Notice how I used "row", "ROW", "col" and "COL" in the function. What you started with works, but this makes it easier to read and understand. You do not have to change what you have since it works, but keep this in mind for the future.
I set "row" and "col" to (0) zero because if the "enum" changes this could be off and not what you want. I do give you credit for what you were thinking about.
One last note: Line 11. Notice how there are two choices. Use "return" if this is used in "main" and "exit" if used in a function since "return" would return from the function back to where the function was called from. Also (0) zero means that there was no problem and it is a normal return. Any number greater than (0)zero means that there is a problem. Using different numbers greater than (0) zero can help to track down where the problem is.
"std::quoted" is from the "<iomanip>" header file. This is a function that is not mentioned very often and you only learn about it when someone uses it or tells you about it. All it does is put double quotes around whatever is in the (). This could be a variable or a string in quotes.
The "writeEmAction" function I did this way:
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
|
void writeEmAction(int action[ROW][COL])
{
std::string outFileName{ "Action Out.txt" };
std::ofstream outFile(outFileName);
if (!outFile)
{
std::cout << "\n File " << std::quoted(outFileName) << " did not open" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3)); // <--- Needs header files chrono" and "thread". Optional as is the header files.
/*return 1;*/ exit(3); // If not in "main".
}
outFile << endl;
outFile << std::string(46 - 6, ' ') << "Action Table\n";
outFile << std::string(46 - 12, ' ') << "Character Classification\n";
outFile << std::string(92, '-') << '\n' << std::endl;
outFile << setw(15) << " ";
outFile << ACTION_HEADINGS;
outFile << right << endl; // <--- "right" only needs done once.
//std::cout << right << endl; // <--- Used for testing. Comment or remove when finished.
outFile << std::string(92,'-') << endl;
for (int row = 0; row < ROW; row++)
{
if (row > 0)
{
outFile << endl << setw(10) << stateToString((stateType)row) << " |";
//std::cout << endl << setw(10) << stateToString((stateType)i) << " |"; // <--- Used for testing. Comment or remove when finished.
}
else
{
outFile << setw(10) << stateToString((stateType)row) << " |";
//std::cout << setw(10) << stateToString((stateType)i) << " |"; // <--- Used for testing. Comment or remove when finished.
}
for (int col = 0; col < COL; col++)
{
outFile << /*right <<*/ setw(9) << action[row][col];
//std::cout << right << setw(9) << action[i][j]; // <--- Used for testing. Comment or remove when finished.
}
}
outFile << endl;
outFile << std::string(92, '-') << /*right <<*/ endl;
}
|
The lines 3 - 12 are not as necessary for the output file stream as it is for the input file stream. When opening an output stream if the file does not exist it will be created. Should you use a path to the file then these line have more use.
In lines 15 and 16 the "std::string(46 - 6, ' ')" is a way to center the string that follows. the 46 is based on using a width or line length of 92 and dividing this by 2. The 6 is the length of the string divided by 2. In the end the first parameter is how many characters to put in the string and the second parameter is what character to print. I have found this to be the easiest way to print spaces to position something on the screen.
Line 17 replaces your for loop and prints 92 "-" on the screen.
Line 20 replaces your for loop which is not adjustable with a string that you can adjust as needed.
Lines 32, 37 and 43 as the comment says I used when first testing the program. You can comment the lines as I did or delete them if you do not need them. to the compiles a commented line is not included in the object code that is generated.
Line 22 I used "right" here. You only need to do this once and it affects every "setw()" until it is changes. No need to do "left" or "right" every time you think that you need it.
There is something to get you started. Understand this is only a suggestion and not something that you have to do. Some of the concepts are worth understanding.
I will deal with the "readEmState" next as I am running out of room here.
Hope that helps,
Andy