Home > database >  String offset in constructor (C )
String offset in constructor (C )

Time:02-26

I get this assignment.

Implement a RAII Logger class that will print a line to a specified output stream in its constructor and destructor.

  • The class will receive an output stream and some text in its constructor.
  • It will print [start] in its constructor and [end] in its destructor to the specified output stream (std::ostream&).
  • Each logger will print its output with some indent (number of space characters printed before the actual content of the line).
  • When you create a logger with a constructor, it will have indent of 0 space characters.
  • The Logger will also have a method called sublogger, which will receive text to be printed.
    • It will return a new logger that will use the same output stream,
    • it will have its indent increased by 2
    • and it will print the provided text.
  • Make sure that the class cannot be copied or copy assigned.

Anyone to give me some advice how to get this? Thank you for any advice.

Example:

   {
   Logger logger(std::cout, "foo");     // prints "foo [start]"
   }                                    // prints "foo [end]"

{
   Logger l1(std::cout, "l1"); // prints "l1 [start]"
   {
       Logger l2 = l1.sublogger(); // prints "  l2 [start]"
   }                               // prints "  l2 [end]"
}                                  // prints "l1 [end]"

Now I am able to get this:

l1 [start]
l2 [start]
l3 [start]
l3 [end]
l4 [start]
l4 [end]
l2 [end]
l1 [end]

But I need this:

l1 [start]
  l2 [start]
    l3 [start]
    l3 [end]
  l4 [start]
  l4 [end]
  l2 [end]
l1 [end]

tasks.h

#pragma once

#include <string>
#include <iostream>

class Logger {
    std::ostream& a;
    std::string b;
    std::string strOffset;

public:
    Logger(std::ostream& a, std::string b);

    ~Logger();

    Logger sublogger(std::string sub);

};

tasks.cpp

#include "tasks.h"

Logger::Logger(std::ostream& a, std::string b) : a(a), b(b) {
    a << strOffset << b << " [start]" << std::endl;
}

Logger::~Logger() {
    a << b << " [end]" << std::endl;
}

Logger Logger::sublogger(std::string sub) {

    return Logger(a, sub);
};

This is how test case looks like:

TEST_CASE("Create subloggers") {
        std::stringstream ss;
        {
            Logger logger(ss, "l1");
            {
                auto logger2 = logger.sublogger("l2");

                {
                    auto logger3 = logger2.sublogger("l3");
                }

                auto logger4 = logger.sublogger("l4");
            }
        }
        std::string testString = ss.str();

        REQUIRE(ss.str() == R"(l1 [start]
  l2 [start]
    l3 [start]
    l3 [end]
  l4 [start]
  l4 [end]
  l2 [end]
l1 [end]
)");

Live test

CodePudding user response:

I don't know what a RAAI Logger is, so it might not be it, but it works for your test case:

tasks.cpp

#include "tasks.h"

Logger::Logger(std::ostream& a, std::string b) : a(a), b(b), offset(0) {
    a << b << " [start]" << std::endl;
}

Logger::Logger(std::ostream& a, std::string b, int offset) : a(a), b(b), offset(offset) {
    printOffset();

    a << b << " [start]" << std::endl;
}

Logger::~Logger() {
    printOffset();

    a << b << " [end]" << std::endl;
}

void Logger::printOffset() {
    for(int i = 0; i < offset; i  ) {
        a << "  ";
    }
}

Logger Logger::sublogger(std::string sub) {
    return Logger(a, sub, offset   1);
};

tasks.h

#pragma once

#include <string>
#include <iostream>

class Logger {
    std::ostream& a;
    std::string b;
    int offset;

    void printOffset();

public:
    Logger(std::ostream& a, std::string b);
    Logger(std::ostream& a, std::string b, int offset);

    ~Logger();

    Logger sublogger(std::string sub);

};

CodePudding user response:

class Logger {
    std::ostream& out;
    const std::string name;
    const std::string prefix;

public:
    Logger(std::ostream& stream, std::string name);
    ~Logger();
    Logger sublogger(std::string sub);

private:
    Logger(std::ostream& stream, std::string name, std::string prefix);

    Logger(const Logger&) = default;
    Logger(Logger&&) = default;
    Logger& operator=(const Logger&) = delete;
    Logger& operator=(Logger&&) = delete;
};

Logger::Logger(std::ostream& stream, std::string name, std::string prefix)
    : out(stream)
    , name(name)
    , prefix(prefix)
{
    out << prefix << name << " [start]" << std::endl;
}

Logger::Logger(std::ostream& stream, std::string name)
    : Logger(stream, name, {})
{
}

Logger::~Logger()
{
    out << prefix << name << " [end]" << std::endl;
}

Logger Logger::sublogger(std::string sub)
{
    return Logger(out, sub, prefix   "  ");
};

https://godbolt.org/z/K9f1Mzrvf

string_view version

  •  Tags:  
  • c
  • Related