Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

  1. Create a directory Lab14/ with the following structure:

Lab14/
├── csv-utils/
│    ├── include/
│    │   └── csv-utils.h
│    ├── source/
│    │   └── csv-utils.cpp
│    ├── compile_flags.txt   
│    └── makefile
├── LICENSE
└── README.md
  1. Fill the following files.

csv-utils.h
csv-utils.cpp
compile_flags.txt
makefile
#ifndef CSV_UTILS_H
#define CSV_UTILS_H

#include <map>
#include <string>
#include <vector>
#include <fstream>

using CsvRow = std::map<std::string, std::string>;
using CsvTable = std::vector<CsvRow>;

class CsvUtils {
public:
    static CsvTable readFile(const std::string& filePath);
    static void writeFile(const std::string& filePath, const CsvTable& table);
    static std::vector<std::string> getColumnNames(const CsvTable& table);
    static std::string getValue(const CsvTable& table, int rowIndex, const std::string& columnName);

private:
    static constexpr char SEPARATOR = ';';
    static constexpr char QUOTE = '"';

    static std::vector<std::string> splitLine(const std::string& line);
    static void checkColumnCount(const std::vector<std::string>& headers, const std::vector<std::string>& values);
    static void checkColumnNames(const std::vector<std::string>& expectedColumns, const std::vector<std::string>& actualColumns);
    static CsvRow buildRow(const std::vector<std::string>& headers, const std::vector<std::string>& values);
    static void writeHeaders(std::ofstream& file, const std::vector<std::string>& headers);
    static void writeValues(std::ofstream& file, const CsvRow& row, const std::vector<std::string>& headers);
    static void checkQuotes(const std::string& value);
};

#endif

We are going to learn how to document a small project called CsvUtils, a C++ library that allows users to read, write, and query simple CSV files.

Reading the code

First, let us try to understand the code before adding comments and documentation.

  1. Look at the contents of csv-utils.h.

  1. Look at the implementation of checkQuotes.

  1. Look at the implementation of readFile. Do you understand why the first line is handled separately?

  1. Look at the implementation of splitLine. Do you understand why we call values.push_back(currentValue) after the for (char character : line) loop?

  1. Look at the implementation of buildRow and then checkColumnCount.

  1. Look at the implementation of writeFile, then getColumnNames and checkColumnNames.

  1. Finally, look at the implementations of writeHeaders, writeValues, and getValue.

Commenting

  1. After understanding the code, add comments to clarify or emphasize the importance of different parts of the implementation.

Documenting

  1. Document the CsvUtils class as shown in class.

README

  1. Fill in your README.md starting with the title and a general description of the project.

  2. Add a Main Features section with a short description of the four main features.

  3. Add a Documentation section with a link or path to the documentation from the root of the project, which will be located at /csv-utils/docs/html/index.html after generating the documentation with Doxygen in the next section.

  4. Add an Installation section with the following instructions.

  1. Create the directory Lab14/my-app/ with the following structure.

Lab14/my-app/
└── external/csv-utils/
    ├── include/
    │   └── csv-utils.h
    ├── lib/
    │   └── libcsvutils.a
    ├── main.cpp
    ├── compile_flags.txt
    └── makefile
  1. Copy the following contents into the corresponding files.

main.cpp
compile_flags.txt
makefile
#include "csv-utils.h"

#include <iostream>

int main() {
    CsvTable table = {
        {{"name", "Alice"}, {"grade", "20"}},
        {{"name", "Bob"}, {"grade", "19"}}
    };

    CsvUtils::writeFile("students.csv", table);

    CsvTable loadedTable = CsvUtils::readFile("students.csv");

    std::cout << CsvUtils::getValue(loadedTable, 0, "name") << '\n';
    std::cout << CsvUtils::getValue(loadedTable, 0, "grade") << '\n';

    return 0;
}
  1. Test the code in my-app/ yourself using make and make run.

  2. Add a Usage section where you provide examples demonstrating the main features of the library.

  3. Add a Limitations subsection to Usage where you explain the limitations of the CSV files that can be read or written by the library.

  4. Add a License section stating that this mini-project is distributed under the MIT License, then copy the MIT License provided in the course material (after modifying the header) into the LICENSE file.

Doxyfile

To generate the documentation with Doxygen, we first need to generate a Doxyfile configuration file.

  1. Generate the Doxyfile by running the following command inside csv-utils/:

doxygen -g
  1. Modify the following settings in the Doxyfile:

  1. Generate the documentation by running the following command inside csv-utils/:

doxygen Doxyfile

You should now see a docs/ directory inside csv-utils/ containing the generated documentation.

  1. View the generated documentation by opening csv-utils/docs/html/index.html in a web browser.

Key Takeaways
  • Document classes and their public methods in header files (syntax).

  • Remember the main elements that should be included in a README (README guidelines).

  • Write clean code and only comment the parts that genuinely need clarification (principles of good comments).