HTML table with C++

Hi!
I'm trying to use C++ to print HTML code for a table to a file, then open it for viewing (in a web browser or something that can read HTML). Here's what I've written so far:
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* 
This program creates a file in HTML, writes a table to the file, and opens it for viewing

Notes:

*/
#include <iostream> 
#include <fstream>
#include <string>
#include <vector>
using namespace std;

// This class allows a 2-dimensional table expressed as
// a vectors of vector of strings to be transformed into
// HTML form.
class HTMLTable
{
private:
   vector<string> headers;
   vector<vector<string> > rows;
   // Helper method for writing an HTML row in a table
   void writeRow (ostream &out, string tag, vector<string> row);
public:
   // Set headers for the table columns
   void setHeaders (const vector<string> &headers)
   {
      this->headers = headers;
   }
   // Add rows to the table
   void addRow(const vector<string> &row)
   {
      rows.push_back (row);
   }
   // Write the table into HTML form onto an output stream
   friend ostream &operator << (ostream &out, HTMLTable htmlTable);
};

//************************************************************
// Writes a row of the table, using the given tag for the    *
// table data. The tag may be td for table data or th for    *
// table header.                                             *
//************************************************************
void HTMLTable::writeRow (ostream &out, string tag, 
                                       vector<string> row)
{
   out << "<tr>\n";
   for (unsigned int k = 0; k < headers.size (); k++)
   {
      out << "<" << tag << "> "
         << row[k] << " </" << tag << "> ";
   }
   out << "\n</tr>\n";
}

//******************************************************
// Overloaded stream output operator <<                *
//******************************************************
ostream & operator << (ostream &out, HTMLTable htmlTable)
{
   out << "<table border = \"1\">\n";
   
   // Write the headers
   htmlTable.writeRow(out, "th", htmlTable.headers);
   
   // Write the rows of the table
   for (unsigned int r = 0; r < htmlTable.rows.size(); r++)
   {
      htmlTable.writeRow(out, "td", htmlTable.rows[r]);
   }
   // Write end tag for table
   out << "</table>\n";
   return out;
}

int main()
{
   // Definition for table column headers   
   vector<string> headers {"Name", "Address", "Phone"};

   // Definitions for the first two rows of the table
   vector<string> person1 {"Mike Sane", "1215 Mills St", "630-728-1293"};
   vector<string> person2 {"Natasha Upenski", "513 Briarcliff Ln", "412-672-1004"};
   
   // Create the HTML table object and set its members
   HTMLTable hTable;
   hTable.setHeaders(headers);
   hTable.addRow(person1);
   hTable.addRow(person2);

   // Open a file and write the HTML code to the file
   ofstream outFile("c:\\temp\\table.html");
   outFile << hTable;
   outFile.close();

   // Write the same HTML code to the screen for ease of viewing
   cout << hTable;
   // Use the default browser to view generated HTML table
   system("c:\\temp\\table.html");

   return 0;
}


My issue is that when I try to compile it, I get these 3 errors:
htmltable.cc:79:26: error: expected ';' at end of declaration
   vector<string> headers {"Name", "Address", "Phone"};
                         ^
                         ;
htmltable.cc:82:26: error: expected ';' at end of declaration
   vector<string> person1 {"Mike Sane", "1215 Mills St", "630-728-1293"};
                         ^
                         ;
htmltable.cc:83:26: error: expected ';' at end of declaration
   vector<string> person2 {"Natasha Upenski", "513 Briarcliff Ln", "412-672-1004"};
                         ^
                         ;

I always thought that this was the proper way to initialize a vector of strings? Any advice you have would be appreciated.
Thanks!
max

Edit:
@dutch mentioned that it may be because my compiler uses an older version of C++ (older than C++11). If this is true, how would I initialize the vectors with the older version?
C++11 is a decade old at this point. What is your compiler + version? You may be able to set a flag like -std=c++0x or -std=c++11 to allow it to still compile.

Anyway, to answer your question:
vector<string> headers {"Name", "Address", "Phone"};
is equivalent to
1
2
3
4
vector<string> headers;
headers.push_back("Name");
headers.push_back("Address");
headers.push_back("Phone");
Thanks, I'll try using those flags! And, I see what you're talking about, I haven't used push_back or pop_back, but I'll try them and see if they work.

For a compiler I use LLVM's clang. It's the compiler in the Terminal application on my Mac. The version is pretty old I think...
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0

That's what I get when I enter c++ -v into the command line. I'm no expert but I think it's pretty old version. Im not sure how old exactly.

Anyway, thanks!
max
It doesn't appear to be that old. Was that the compiler that came with Xcode, or did you install it separately? Regardless, I don't know much about Mac development environments so I probably can't help you. I would try to compile a simple test program via command-line like
1
2
3
4
5
#include <vector>
int main()
{
    std:: vector<int> vec { 3, 1, 4 };
}
Hello agent max,

When I compiled your code with Windows 10 and MSVS 2017 using the 2014 standards it compiled with no errors or warnings. I do not know enough about a Mac to know the differences or why your compiler did not work.

What I did see:

Line 91 defines a file stream and opens the file. But how do you know it is open. Your path may work for you, but may not for everyone. Also using a path if something is misspelled or you might have an extra character or space could through the whole path off.

Always a good idea to check if the file opened properly.

When the program it produced the file:

table.html
<table border = "1">
<tr>
<th> Name </th> <th> Address </th> <th> Phone </th> 
</tr>
<tr>
<td> Mike Sane </td> <td> 1215 Mills St </td> <td> 630-728-1293 </td> 
</tr>
<tr>
<td> Natasha Upenski </td> <td> 513 Briarcliff Ln </td> <td> 412-672-1004 </td> 
</tr>
</table>

This worked producing the a table in my browser. Unfortunately I could not copy the whole table to show here. But it has a nice border around everything and a border around each cell.

A number of years age I did something similar to produce a html table. What I added to my program was reading a text file containing everything from "<!DOCTYPE html>" down to "<body>". I just read this file and wrote it to the output file then let the program create the table ending with reading a text file for what is needed to finish the the html page.

I found this useful because it let me make use of some java scripts that are dealt with in the opening code and the use of style sheets to set how the page looks.

Just a thought if you are interested.

One last note: Calling "close" on outFile" is not as necessary as it use to be. When the program ends and just before loosing scope it will call the dtor on the file stream object thus closing the stream.

Andy
Hello agent max,

While going over your program I did make 1 change to:
1
2
3
4
5
6
7
8
9
10
11
12
13
void HTMLTable::writeRow(ostream &out, string tag,
                         vector<string> row)
{
    out << "<tr>\n";

    for (unsigned int k = 0; k < headers.size(); k++)
    {
        out << "<" << tag << ">&nbsp;"
            << row[k] << "&nbsp;</" << tag << "> ";
    }

    out << "\n</tr>\n";
}

Your use of the space does not always work in html code. When it does not you need to use the "&nbsp;" to show a non breaking space. This makes the cells of the table slightly wider. Or you could use a style sheet or "<style>" tags in the opening of the html code to set the size of the table and the "th" and "td" tags.

Andy
@Ganado,
Thanks, that sounds like a good idea! The compiler is actually in the Terminal application on my Mac, I don't use Xcode.

@Handy Andy,
Hmm. I must have an older version than I thought. My mac is about 12 years old, though, so that might be it. And that's a good idea about using Java and CSS to modify it, I have done that in the past with HTML programs, and it comes really in handy (no pun intended) when you want to do something that HTML doesn't do.

Edit:
I tried using push_back() function like Ganado suggested, and I get this result now.
sh: c:temptable.html: command not found

But, it created the file, so that's all right. I think that the system() function is a Windows-specific thing, is that correct?

Edit 2:
I tried your suggestion, @Ganado, and I got the same problem-I think my compiler just doesn't accept that kind of vector initialization.
Last edited on
Hello agent max,

For the most part I do believe the "system()" I see used more with Windows, but I seem to remember seeing this with the "*inx" operating systems. The difference is tha t"*inx" uses different commands in the (). I do not know if Mac has anything like the "system" call.

Based on what you posted the message looks like you did not put the (\\) or (/) around the "temp" sub directory. If not them it might come back to using a pre2011 standard that may not know about "vectors" or some parts that you are using.

Andy
And that's a good idea about using Java and CSS

"Java" has nothing to do with it. It's "javascript". "Javascript" is not even remotely related to "Java", except for the stolen name.

sh: c:temptable.html: command not found

system() is part of C and C++, so it definitely works on you Mac. The problem is that you can't just "run" an html file. You need to run your browser, passing the html file as an argument. So if your browser is firefox, you would say:

system("firefox table.html");
I have no idea what the c: is doing in front of your filename since that's a windows thing. And you shouldn't be using the double backwards slashes since that's a windows thing, too. Don't bother with the "temp" directory, though. Just say table.html.

And you need to pass -std=c++11 (or c++14 or c++17) to your compiler to use modern C++.
@Handy Andy,
I see, thanks!

@dutch,
Oops, my mistake. I meant to say JavaScript, thanks for correcting.
And, I was just copying and pasting from an example off of the Internet for the system("c:\\temp\\table.html");, so I didn't really know what it did. Thanks for clarifying that.

How would I pass -std=c++11 to the compiler? Through the command line, or in the program itself? (I don't have an IDE, so I have to use the command line for basically everything).

Thanks!
max

Edit:
I tried your suggestion, I tried Safari and Google Chrome, BUT...
1
2
3
// my default browser is Safari
// I also tried google chrome
 system("safari table.html");
.
Neither of those worked.
Any other ideas?

Edit 2:
What do you know?
After my first edit, I got to thinking, well, all its doing is opening the file, right? So, I tried using "open" like so:
 
system("open table.html");

And what do you know, it worked!

@dutch, @Ganado, @Handy Andy, thanks guys!
max

P.S.
If you want to run it for yourselves, copy and paste ofstream outFile("table.html"); into line 91 of my original code, and then copy and paste system("open table.html"); into line 98 of the original code. Actually, I'm kind of curious to see if my edit will work on Windows or Linux.
Last edited on
Works fine on Windows 7.

If this is more than a simple exercise have a quick look at
https://www.youtube.com/watch?v=TNM6okwAiig to see a different way to build HTML.
Thanks @thmm!
It was just an experiment really, but that video was a big help!

max
Topic archived. No new replies allowed.