feat(cmat): add cmake build for course material
Add a CMakeLists.txt to each exercise directory, included from cmat/CMakeLists.txt, so every exercise and solution becomes a buildable target. GUI exercises link the curses-based DOS_Unix implementations on Unix-like systems; the Windows-specific DOS variants are not compiled. Exercises without a portable path or with missing dependencies (Boost) are reported as not available at configure time. Targets are excluded from the default build and built by name, e.g. `cmake --build build --target Ex11`, so intentionally buggy exercises such as Ex21 do not break the default build. Also fix two portability issues: rename Ex11bug/pole.h to Pole.h for case-sensitive filesystems and drop the extra Light:: qualification in SolutionEx71A/Light.h. Document build commands and layout in AGENTS.md. Co-authored-by: Qwen 3.8 27B <qwen3.8_27b-q3_k_xl@lmstudio.local>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
# SolutionEx71Bonus
|
||||
|
||||
cmat_add_exercise(SolutionEx71Bonus
|
||||
SOURCES
|
||||
CompanyEntry.cpp
|
||||
CountVisitor.cpp
|
||||
FindVisitor.cpp
|
||||
GroupEntry.cpp
|
||||
main.cpp
|
||||
PersonEntry.cpp
|
||||
PrintVisitor.cpp
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "CompanyEntry.h"
|
||||
#include "EntryVisitor.h"
|
||||
|
||||
CompanyEntry::CompanyEntry(std::string name, std::string category, std::string phone)
|
||||
: Entry(name), _category(category), _phone(phone) {}
|
||||
|
||||
void CompanyEntry::print(std::string indent) const {
|
||||
|
||||
std::cout << indent << "Company: " << getName() << " <" << _category << "> " << _phone << '\n';
|
||||
}
|
||||
|
||||
std::string CompanyEntry::getPhone() const { return _phone; }
|
||||
|
||||
std::string CompanyEntry::getCategory() const { return _category; }
|
||||
|
||||
void CompanyEntry::accept(EntryVisitor &v) const { v.visit(*this); }
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
#ifndef COMPANYENTRY_H
|
||||
#define COMPANYENTRY_H
|
||||
|
||||
#include "Entry.h"
|
||||
|
||||
class CompanyEntry : public Entry {
|
||||
public:
|
||||
CompanyEntry(std::string name, std::string category, std::string phone);
|
||||
|
||||
void print(std::string indent = "") const;
|
||||
std::string getPhone() const;
|
||||
std::string getCategory() const;
|
||||
|
||||
void accept(EntryVisitor &) const;
|
||||
|
||||
private:
|
||||
std::string _category;
|
||||
std::string _phone;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "CountVisitor.h"
|
||||
#include <iostream>
|
||||
|
||||
CountVisitor::CountVisitor() : nPerson(0), nCompany(0), nGroup(0) {}
|
||||
|
||||
void CountVisitor::printCounts() {
|
||||
std::cout << "Persons: " << nPerson << " Companies: " << nCompany << " Groups: " << nGroup << "\n";
|
||||
}
|
||||
|
||||
void CountVisitor::visit(const PersonEntry &p) { nPerson++; }
|
||||
|
||||
void CountVisitor::visit(const CompanyEntry &c) { nCompany++; }
|
||||
|
||||
void CountVisitor::visit(const GroupEntry &g) { nGroup++; }
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "EntryVisitor.h"
|
||||
class CountVisitor : public EntryVisitor {
|
||||
int nPerson, nCompany, nGroup;
|
||||
|
||||
public:
|
||||
CountVisitor();
|
||||
|
||||
void printCounts();
|
||||
|
||||
void visit(const PersonEntry &);
|
||||
void visit(const CompanyEntry &);
|
||||
void visit(const GroupEntry &);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
// Entry.cpp
|
||||
|
||||
#include "Entry.h"
|
||||
|
||||
Entry::Entry(std::string name) : _name(name), _phone(phone) {}
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
#ifndef ENTRY_H
|
||||
#define ENTRY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class EntryVisitor;
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
Entry(std::string name) : _name(name) {}
|
||||
|
||||
std::string getName() const { return _name; }
|
||||
|
||||
virtual void print(std::string indent = "") const = 0;
|
||||
|
||||
virtual void accept(EntryVisitor &) const = 0;
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
// EntryVisitor.h
|
||||
|
||||
#ifndef ENTRYVISITOR_H
|
||||
#define ENTRYVISITOR_H
|
||||
|
||||
class PersonEntry;
|
||||
class CompanyEntry;
|
||||
class GroupEntry;
|
||||
|
||||
class EntryVisitor {
|
||||
public:
|
||||
virtual void visit(const PersonEntry &) = 0;
|
||||
virtual void visit(const CompanyEntry &) = 0;
|
||||
virtual void visit(const GroupEntry &) = 0;
|
||||
|
||||
virtual void unVisit(const GroupEntry &) {
|
||||
} // In some cases, the composite node may need special processing after delegation to children
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<ProjectGuid>{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeaderOutputFile>.\Release/Ex71A.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
|
||||
<ObjectFileName>.\Release/</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>.\Release/Ex71A.exe</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<ProgramDatabaseFile>.\Release/Ex71A.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<Midl>
|
||||
<TypeLibraryName>.\Release/Ex71A.tlb</TypeLibraryName>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0809</Culture>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderOutputFile>.\Debug/Ex71A.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
|
||||
<ObjectFileName>.\Debug/</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<AdditionalIncludeDirectories>C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>.\Debug/Ex71.exe</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>.\Debug/Ex71A.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<Midl>
|
||||
<TypeLibraryName>.\Debug/Ex71A.tlb</TypeLibraryName>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0809</Culture>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CompanyEntry.cpp" />
|
||||
<ClCompile Include="CountVisitor.cpp" />
|
||||
<ClCompile Include="GroupEntry.cpp" />
|
||||
<ClCompile Include="FindVisitor.cpp" />
|
||||
<ClCompile Include="PersonEntry.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="PrintVisitor.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CompanyEntry.h" />
|
||||
<ClInclude Include="CountVisitor.h" />
|
||||
<ClInclude Include="Entry.h" />
|
||||
<ClInclude Include="EntryVisitor.h" />
|
||||
<ClInclude Include="GroupEntry.h" />
|
||||
<ClInclude Include="FindVisitor.h" />
|
||||
<ClInclude Include="PersonEntry.h" />
|
||||
<ClInclude Include="PrintVisitor.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{a373d85d-0daa-4771-a2af-24735700f4b5}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{28280df5-d09d-4335-a70c-dd81eee4485f}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GroupEntry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PersonEntry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CompanyEntry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FindVisitor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CountVisitor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PrintVisitor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Entry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EntryVisitor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GroupEntry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PersonEntry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CompanyEntry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FindVisitor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CountVisitor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PrintVisitor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
</Project>
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma warning(disable : 4786)
|
||||
// PrintVisitor.cpp
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "CompanyEntry.h"
|
||||
#include "FindVisitor.h"
|
||||
#include "GroupEntry.h"
|
||||
#include "PersonEntry.h"
|
||||
|
||||
FindVisitor::FindVisitor(std::string query) : _query(query) {}
|
||||
|
||||
const std::vector<const Entry *> &FindVisitor::getFindings() { return findings; }
|
||||
|
||||
void FindVisitor::visit(const PersonEntry &s) {
|
||||
if (s.getName().find(_query) != std::string::npos) {
|
||||
findings.push_back(&s);
|
||||
}
|
||||
}
|
||||
|
||||
void FindVisitor::visit(const GroupEntry &g) {
|
||||
if (g.getName().find(_query) != std::string::npos) {
|
||||
findings.push_back(&g);
|
||||
}
|
||||
}
|
||||
|
||||
void FindVisitor::visit(const CompanyEntry &c) {
|
||||
|
||||
if (c.getName().find(_query) != std::string::npos || c.getCategory().find(_query) != std::string::npos) {
|
||||
findings.push_back(&c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
#ifndef FINDVISITOR_H
|
||||
#define FINDVISITOR_H
|
||||
|
||||
#include "Entry.h"
|
||||
#include "EntryVisitor.h"
|
||||
#include <vector>
|
||||
|
||||
class FindVisitor : public EntryVisitor {
|
||||
std::string _query; // looking for this
|
||||
std::vector<const Entry *> findings; // finding these entries
|
||||
public:
|
||||
FindVisitor(std::string query);
|
||||
const std::vector<const Entry *> &getFindings();
|
||||
|
||||
void visit(const PersonEntry &);
|
||||
void visit(const CompanyEntry &);
|
||||
void visit(const GroupEntry &);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma warning(disable : 4786)
|
||||
// GroupEntry.cpp
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "EntryVisitor.h"
|
||||
#include "GroupEntry.h"
|
||||
#include "PersonEntry.h"
|
||||
|
||||
GroupEntry::GroupEntry(std::string name) : Entry(name) {}
|
||||
|
||||
void GroupEntry::print(std::string indent) const {
|
||||
// print group name
|
||||
std::cout << indent << "Group: " << getName() << '\n';
|
||||
|
||||
// Part 1: call print() on each group member (with increased indent level)
|
||||
|
||||
for (auto p : _entries) {
|
||||
p->print(indent + " ");
|
||||
}
|
||||
}
|
||||
|
||||
void GroupEntry::addEntry(const Entry &entry) {
|
||||
// Part 1: Add the entry to this group
|
||||
|
||||
_entries.push_back(&entry);
|
||||
}
|
||||
|
||||
void GroupEntry::accept(EntryVisitor &v) const {
|
||||
v.visit(*this);
|
||||
|
||||
// pass visitor to my children
|
||||
for (auto p : _entries) {
|
||||
p->accept(v);
|
||||
}
|
||||
|
||||
v.unVisit(*this);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// GroupEntry.h
|
||||
|
||||
#ifndef GROUPENTRY_H
|
||||
#define GROUPENTRY_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Entry.h"
|
||||
#include "PersonEntry.h"
|
||||
|
||||
class GroupEntry : public Entry {
|
||||
public:
|
||||
GroupEntry(std::string name);
|
||||
|
||||
// print the entire group, including its members
|
||||
// precede the name with the "indent" string
|
||||
void print(std::string indent = "") const;
|
||||
|
||||
// child management
|
||||
void addEntry(const Entry &);
|
||||
|
||||
void accept(EntryVisitor &) const;
|
||||
|
||||
private:
|
||||
std::vector<const Entry *> _entries;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "EntryVisitor.h"
|
||||
#include "PersonEntry.h"
|
||||
|
||||
PersonEntry::PersonEntry(std::string name, std::string phone) : Entry(name), _phone(phone) {}
|
||||
|
||||
void PersonEntry::print(std::string indent) const {
|
||||
|
||||
std::cout << indent << "Person: " << getName() << ' ' << _phone << '\n';
|
||||
}
|
||||
|
||||
std::string PersonEntry::getPhone() const { return _phone; }
|
||||
|
||||
void PersonEntry::accept(EntryVisitor &v) const { v.visit(*this); }
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
#ifndef PERSONENTRY_H
|
||||
#define PERSONENTRY_H
|
||||
|
||||
#include "Entry.h"
|
||||
|
||||
class PersonEntry : public Entry {
|
||||
public:
|
||||
PersonEntry(std::string name, std::string phone);
|
||||
|
||||
void print(std::string indent = "") const;
|
||||
|
||||
std::string getPhone() const;
|
||||
|
||||
void accept(EntryVisitor &) const;
|
||||
|
||||
private:
|
||||
std::string _phone;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "PrintVisitor.h"
|
||||
#include "CompanyEntry.h"
|
||||
#include "GroupEntry.h"
|
||||
#include "PersonEntry.h"
|
||||
#include <iostream>
|
||||
|
||||
void PrintVisitor::visit(const PersonEntry &pe) {
|
||||
std::cout << indent << "Person: " << pe.getName() << ' ' << pe.getPhone() << '\n';
|
||||
}
|
||||
|
||||
void PrintVisitor::visit(const CompanyEntry &ce) {
|
||||
std::cout << indent << "Company: " << ce.getName() << " <" << ce.getCategory() << "> " << ce.getPhone() << '\n';
|
||||
}
|
||||
|
||||
void PrintVisitor::visit(const GroupEntry &ge) {
|
||||
std::cout << indent << "Group: " << ge.getName() << '\n';
|
||||
|
||||
indent += " ";
|
||||
}
|
||||
|
||||
void PrintVisitor::unVisit(const GroupEntry &) {
|
||||
// Get rid of the extra indent we added
|
||||
indent = indent.substr(indent.length() - 2, 2);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef PRINTVISITOR_H
|
||||
#define PRINTVISITOR_H
|
||||
|
||||
#include "EntryVisitor.h"
|
||||
#include <string>
|
||||
|
||||
class PrintVisitor : public EntryVisitor {
|
||||
private:
|
||||
std::string indent;
|
||||
|
||||
public:
|
||||
void visit(const PersonEntry &);
|
||||
void visit(const CompanyEntry &);
|
||||
void visit(const GroupEntry &);
|
||||
|
||||
void unVisit(const GroupEntry &);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#pragma warning(disable : 4786)
|
||||
|
||||
#include "CompanyEntry.h"
|
||||
#include "CountVisitor.h"
|
||||
#include "FindVisitor.h"
|
||||
#include "GroupEntry.h"
|
||||
#include "PersonEntry.h"
|
||||
#include "PrintVisitor.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
|
||||
// declare an address book
|
||||
GroupEntry addressbook("My addressbook");
|
||||
|
||||
// create some entries
|
||||
PersonEntry Fred("Fred", "555 1234");
|
||||
PersonEntry Gert("Gert", "555 1235");
|
||||
PersonEntry Jim("Jim", "999 2445");
|
||||
PersonEntry Sue("Sue", "456 2951");
|
||||
PersonEntry Ingar("Ingar", "999 2345");
|
||||
PersonEntry Lisa("Lisa", "443 4532");
|
||||
CompanyEntry ShoeWorld("ShoeWorld", "Shoes", "234 4314");
|
||||
CompanyEntry BestBurgers("BestBurgers", "Food", "456 4651");
|
||||
CompanyEntry DreamPizza("DreamPizza", "Food", "935 2345");
|
||||
CompanyEntry BestBooks("BestBooks", "Books", "345 3232");
|
||||
|
||||
// add some simple entries
|
||||
addressbook.addEntry(Fred);
|
||||
addressbook.addEntry(Gert);
|
||||
addressbook.addEntry(ShoeWorld);
|
||||
|
||||
// make some groups
|
||||
GroupEntry group1("My Best Food");
|
||||
group1.addEntry(BestBurgers);
|
||||
group1.addEntry(DreamPizza);
|
||||
|
||||
GroupEntry group2("Coworkers");
|
||||
group2.addEntry(Jim);
|
||||
group2.addEntry(Sue);
|
||||
|
||||
// make a nested group
|
||||
GroupEntry group3("Favorites");
|
||||
group3.addEntry(Ingar);
|
||||
group3.addEntry(Lisa);
|
||||
group3.addEntry(BestBooks);
|
||||
group3.addEntry(group1);
|
||||
|
||||
addressbook.addEntry(group2);
|
||||
addressbook.addEntry(group3);
|
||||
|
||||
cout << "\n\n";
|
||||
|
||||
cout << "*** Print using Composite print operation\n";
|
||||
addressbook.print();
|
||||
|
||||
cout << "\n\n";
|
||||
|
||||
cout << "*** Print using PrintVisitor\n";
|
||||
PrintVisitor printVisitor;
|
||||
addressbook.accept(printVisitor);
|
||||
|
||||
cout << "\n\n";
|
||||
|
||||
cout << "*** Find using Visitor\n";
|
||||
FindVisitor pv("Fred");
|
||||
addressbook.accept(pv);
|
||||
for (const Entry *p : pv.getFindings()) {
|
||||
p->print();
|
||||
}
|
||||
|
||||
cout << "*** Print Entry counts using Visitor\n";
|
||||
CountVisitor cv;
|
||||
addressbook.accept(cv);
|
||||
cv.printCounts();
|
||||
|
||||
cout << "*** Test complete\n";
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user