This is as much of a question about algorithm as it is about code.
I’m training monkeys to input data into a keyboard in the form of a table. I have created a special keyboard with nothing on it but numbers 0 - 9, a period, tab key and a return key. The goal is to get them to input data in rows and columns. However, I have been unsuccessful so far, as I am unable to get them to input a consistent number of columns. The input I get looks like this:
443 3439 3.932
4 55 9.99.9 12 293837493892
1 . 000.441893 78 74939.392938 4421229
8 77 .0 4.4 78909
…and so on.
Part of the problem is that as a reward for entering a consistent number of columns, I give them Jello shots. They really love the red ones.
As a programmer, I feel it’s my job to handle whatever erratic input might come my way, and so I have decided to try to deal with this input and create a table anyway. Much of this could be handled by simply throwing an exception or two, but this is an exercise and I believe it’s good for me. And since research monkeys are not cheap, I’m going to have to stick with the same ones. Besides, we’ve sort of bonded, I guess you could say. Some obvious concerns:
How do I code for various column widths? I can attempt to set the table to the number of rows present (incrementing by one for each “row”). Using the same procedure, I could then set the columns to the largest width. For example, in row three of the “table” above, there are possibly six values, giving it the greatest number of columns. Thus, I would have a table with four rows and six columns (depending on how the lone dot is handled). So far, the code to read the input and set the number of rows and columns looks like this:
1. string endLine;
2. double value = 0; //using this as placeholder so that something can be read. Nothing else done with this value.
3. while(fin.good())
4. {
5. for(int r = 0; r < numRows; r++)
6. {
7. fin>>value;
8. fout << value << "\t";
9. for(int c = 0; c < numCols; c++)
10. {
11. fin >> value;
12. fout << value << "\t";
13. if(!(getline(fin, endLine)))
14. numCols++;
15. }
16. if(getline(fin, endLine))
17. numRows++;
18. fout << endl;
19. }
20. }
21.
22. cout << "Number of rows: " << numRows << ".\n";
23. cout << "Number of columns: " << numCols << ".\n";
The idea is to read to the end of the line, remaining in the same row, until the code reads the end of line character, then add to the number of columns. However, simply incrementing numCols by one isn’t the answer because any given row might have more than one extra value. For example, row x might have two values (and thus two columns) and row x + 1 might have four values (and thus four columns). The answer would seem to be to count white spaces and add those up to get the total number of columns for the row (actually, I think it would be total number of whitespaces +1).
Assume that I get all this read and that I have a table of numRows number of rows and numCols number of columns. I then build that table and attempt to read the values from the same set of data:
double **table;
int numRows;
int numCols;
table = new double*[numRows];
for(int r = 0; r < numRows; r++)
{
table[r] = new double[numCols];
for(int c = 0; c < numCols; c++)
in >> table[r][c];
}
What will this table do when it tries to read a column that doesn’t have a value? Does it get to the endline marker and just read in the next value? And then what if it simply runs out of values to read? So far, my best idea has been to simply read in all the values in one stream, so to speak, and then find the two factors closest to the middle of the range of values to create a table. For example, if I read in 24 values, set the rows to 6 and columns to 4.
And finally, what’s the function to ignore that lone (or the extra) dot? Is it in.ignore(‘.’)?
Wait until I try to teach them to drive……………..