diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 53017a6..0000000 --- a/.clang-format +++ /dev/null @@ -1,274 +0,0 @@ ---- -Language: Cpp -AccessModifierOffset: -2 -AlignAfterOpenBracket: Align -AlignArrayOfStructures: None -AlignConsecutiveAssignments: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: true -AlignConsecutiveBitFields: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveDeclarations: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveMacros: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveShortCaseStatements: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCaseArrows: false - AlignCaseColons: false -AlignConsecutiveTableGenBreakingDAGArgColons: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveTableGenCondOperatorColons: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveTableGenDefinitionColons: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignEscapedNewlines: Right -AlignOperands: Align -AlignTrailingComments: - Kind: Always - OverEmptyLines: 0 -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowBreakBeforeNoexceptSpecifier: Never -AllowShortBlocksOnASingleLine: Never -AllowShortCaseExpressionOnASingleLine: true -AllowShortCaseLabelsOnASingleLine: false -AllowShortCompoundRequirementOnASingleLine: true -AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AttributeMacros: - - __capability -BinPackArguments: true -BinPackParameters: true -BitFieldColonSpacing: Both -BraceWrapping: - AfterCaseLabel: false - AfterClass: false - AfterControlStatement: Never - AfterEnum: false - AfterExternBlock: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakAdjacentStringLiterals: true -BreakAfterAttributes: Leave -BreakAfterJavaFieldAnnotations: false -BreakAfterReturnType: None -BreakArrays: true -BreakBeforeBinaryOperators: None -BreakBeforeConceptDeclarations: Always -BreakBeforeBraces: Attach -BreakBeforeInlineASMColon: OnlyMultiline -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakFunctionDefinitionParameters: false -BreakInheritanceList: BeforeColon -BreakStringLiterals: true -BreakTemplateDeclarations: MultiLine -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IfMacros: - - KJ_IF_MAYBE -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - CaseSensitive: false - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - CaseSensitive: false - - Regex: '.*' - Priority: 1 - SortPriority: 0 - CaseSensitive: false -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: false -IndentCaseBlocks: false -IndentCaseLabels: false -IndentExternBlock: AfterExternBlock -IndentGotoLabels: true -IndentPPDirectives: None -IndentRequiresClause: true -IndentWidth: 4 -IndentWrappedFunctionNames: false -InsertBraces: false -InsertNewlineAtEOF: false -InsertTrailingCommas: None -IntegerLiteralSeparator: - Binary: 0 - BinaryMinDigits: 0 - Decimal: 0 - DecimalMinDigits: 0 - Hex: 0 - HexMinDigits: 0 -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLines: - AtEndOfFile: false - AtStartOfBlock: true - AtStartOfFile: true -LambdaBodyIndentation: Signature -LineEnding: DeriveLF -MacroBlockBegin: '' -MacroBlockEnd: '' -MainIncludeChar: Quote -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCBreakBeforeNestedBlockParam: true -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PackConstructorInitializers: BinPack -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 0 -PenaltyBreakScopeResolution: 500 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyIndentedWhitespace: 0 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -PPIndentWidth: -1 -QualifierAlignment: Leave -ReferenceAlignment: Pointer -ReflowComments: true -RemoveBracesLLVM: false -RemoveParentheses: Leave -RemoveSemicolon: false -RequiresClausePosition: OwnLine -RequiresExpressionIndentation: OuterScope -SeparateDefinitionBlocks: Leave -ShortNamespaceLines: 1 -SkipMacroDefinitionBody: false -SortIncludes: CaseSensitive -SortJavaStaticImport: Before -SortUsingDeclarations: LexicographicNumeric -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeJsonColon: false -SpaceBeforeParens: ControlStatements -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: true - AfterFunctionDefinitionName: false - AfterFunctionDeclarationName: false - AfterIfMacros: true - AfterOverloadedOperator: false - AfterPlacementOperator: true - AfterRequiresInClause: false - AfterRequiresInExpression: false - BeforeNonEmptyParentheses: false -SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInContainerLiterals: true -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 -SpacesInParens: Never -SpacesInParensOptions: - ExceptDoubleParentheses: false - InCStyleCasts: false - InConditionalStatements: false - InEmptyParentheses: false - Other: false -SpacesInSquareBrackets: false -Standard: Latest -StatementAttributeLikeMacros: - - Q_EMIT -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION -TableGenBreakInsideDAGArg: DontBreak -TabWidth: 8 -UseTab: Never -VerilogBreakBetweenInstancePorts: true -WhitespaceSensitiveMacros: - - BOOST_PP_STRINGIZE - - CF_SWIFT_NAME - - NS_SWIFT_NAME - - PP_STRINGIZE - - STRINGIZE -... - diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 655eb89..0000000 --- a/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.o -*.d -*a.out* -build -.cache/ -words.txt -compile_commands.json -lab2/edit -lab2/spell -lab3/tabletest -./vscode \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 51257f5..0000000 --- a/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -format: - find . -regex '.*\.\(c\|cpp\|cc\|cxx\|h\|hpp\|hh\|hxx\)' -exec clang-format {} + diff --git a/cpplabs.pdf b/cpplabs.pdf deleted file mode 100644 index 178567b..0000000 Binary files a/cpplabs.pdf and /dev/null differ diff --git a/lab1/.gitignore b/lab1/.gitignore deleted file mode 100644 index 6f6e224..0000000 --- a/lab1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -hello -test_editor diff --git a/lab4/.vscode/settings.json b/lab1/.vscode/settings.json similarity index 96% rename from lab4/.vscode/settings.json rename to lab1/.vscode/settings.json index b73e5a3..9664ac8 100644 --- a/lab4/.vscode/settings.json +++ b/lab1/.vscode/settings.json @@ -4,7 +4,6 @@ "atomic": "cpp", "bit": "cpp", "*.tcc": "cpp", - "bitset": "cpp", "cctype": "cpp", "charconv": "cpp", "clocale": "cpp", @@ -32,13 +31,13 @@ "numeric": "cpp", "optional": "cpp", "random": "cpp", - "regex": "cpp", "string_view": "cpp", "system_error": "cpp", "tuple": "cpp", "type_traits": "cpp", "utility": "cpp", "format": "cpp", + "fstream": "cpp", "initializer_list": "cpp", "iomanip": "cpp", "iosfwd": "cpp", diff --git a/lab1/Justfile b/lab1/Justfile deleted file mode 100644 index d7b08bc..0000000 --- a/lab1/Justfile +++ /dev/null @@ -1,51 +0,0 @@ -all: a1 a2 a3 a4 cmake buggy - -# Build the A1 lab exercise -a1: - g++ -o hello hello.cc - ./hello - -# Build the A2 lab exercise -a2: - g++ -std=c++11 -o separate_main separate_main.cc separate_fn.cc - -# Build the A3 lab exercise -a3: - g++ -std=c++11 -c separate_main.cc - g++ -std=c++11 -c separate_fn.cc - g++ -std=c++11 -o separate_main separate_main.o separate_fn.o - -# Build the A4 lab exercise -a4: - @echo "Will fail" - -g++ -std=c++11 -o separate_main separate_main.cc - -# Build the A5 lab exercise -a5: - g++ -c -O2 -Wall -Wextra -pedantic-errors -Wold-style-cast -std=c++11 hello.cc - -# Build the cmake exercise -cmake: - rm -rf ./cmake-example/build # Start over - cd ./cmake-example && mkdir -p build - cd ./cmake-example/build && cmake .. - cd ./cmake-example/build && make -j$(nproc) - ./cmake-example/build/SimpleMain - -buggy: - cd ./buggy_programs && make -j4 - cd ./buggy_programs && mkdir -p build - cd ./buggy_programs && cmake -B build - cd ./buggy_programs && make -C build - -valgrind: buggy - cd ./buggy_programs/build/ && valgrind ./dangling - cd ./buggy_programs/build/ && valgrind ./bounds - cd ./buggy_programs/build/ && valgrind ./bounds-heap - cd ./buggy_programs/build/ && valgrind ./leak - cd ./buggy_programs/build/ && valgrind ./sum - cd ./buggy_programs/build/ && valgrind ./sum_alt - cd ./buggy_programs/build/ && valgrind ./ub - -clean: - git clean -fdx diff --git a/lab1/Makefile b/lab1/Makefile index aa95b23..8b08bc0 100644 --- a/lab1/Makefile +++ b/lab1/Makefile @@ -1,17 +1,58 @@ -# The following rule means: "if test_editor does not exist, or -# is older than test_editor.o or editor.o, -# then link test_editor". -test_editor: test_editor.o editor.o - g++ -o test_editor test_editor.o editor.o +# Define the compiler and the linker. The linker must be defined since +# the implicit rule for linking uses CC as the linker. g++ can be +# changed to clang++. +CXX = g++ +CC = $(CXX) -# Rules to create the object files. -test_editor.o: test_editor.cc editor.h - g++ -c test_editor.cc -std=c++11 -editor.o: editor.cc editor.h - g++ -c editor.cc -std=c++11 +# Generate dependencies in *.d files +DEPFLAGS = -MT $@ -MMD -MP -MF $*.d +# Define preprocessor, compiler, and linker flags. Uncomment the # lines +# if you use clang++ and wish to use libc++ instead of GNU's libstdc++. +# -g is for debugging. +CPPFLAGS = -std=c++11 -I. +CXXFLAGS = -O2 -Wall -Wextra -pedantic-errors -Wold-style-cast +CXXFLAGS += -std=c++11 +CXXFLAGS += -g +CXXFLAGS += $(DEPFLAGS) +LDFLAGS = -g +#CPPFLAGS += -stdlib=libc++ +#CXXFLAGS += -stdlib=libc++ +#LDFLAGS += -stdlib=libc++ + +# Targets +PROGS = test_editor test_coding print_argv hello encode decode + +all: $(PROGS) + +test: test_coding test_editor + ./test_coding + ./test_editor + ./hello + +test_encode_decode: encode decode + @echo "Running encode-decode tests" + ./encode testfile.txt + ./decode testfile.txt.enc + +# Targets rely on implicit rules for compiling and linking print_argv: print_argv.o - g++ -o print_argv print_argv.o -print_argv.o: print_argv.cc - g++ -c print_argv.cc -std=c++11 +test_editor: test_editor.o editor.o +test_coding: test_coding.o coding.o +encode: encode.o coding.o +decode: decode.o coding.o +# Phony targets +.PHONY: all test test_encode_decode clean distclean + +# Standard clean +clean: + rm -f *.o $(PROGS) + +distclean: clean + rm *.d + + +# Include the *.d files +SRC = $(wildcard *.cc) +-include $(SRC:.cc=.d) diff --git a/lab1/Makefile1 b/lab1/Makefile1 new file mode 100644 index 0000000..aa95b23 --- /dev/null +++ b/lab1/Makefile1 @@ -0,0 +1,17 @@ +# The following rule means: "if test_editor does not exist, or +# is older than test_editor.o or editor.o, +# then link test_editor". +test_editor: test_editor.o editor.o + g++ -o test_editor test_editor.o editor.o + +# Rules to create the object files. +test_editor.o: test_editor.cc editor.h + g++ -c test_editor.cc -std=c++11 +editor.o: editor.cc editor.h + g++ -c editor.cc -std=c++11 + +print_argv: print_argv.o + g++ -o print_argv print_argv.o +print_argv.o: print_argv.cc + g++ -c print_argv.cc -std=c++11 + diff --git a/lab1/MakefileWithDeps b/lab1/MakefileWithDeps deleted file mode 100644 index 29fd9da..0000000 --- a/lab1/MakefileWithDeps +++ /dev/null @@ -1,50 +0,0 @@ -# Define the compiler and the linker. The linker must be defined since -# the implicit rule for linking uses CC as the linker. g++ can be -# changed to clang++. -CXX = g++ -CC = $(CXX) - -# Generate dependencies in *.d files -DEPFLAGS = -MT $@ -MMD -MP -MF $*.d - -# Define preprocessor, compiler, and linker flags. Uncomment the # lines -# if you use clang++ and wish to use libc++ instead of GNU's libstdc++. -# -g is for debugging. -CPPFLAGS = -std=c++11 -I. -CXXFLAGS = -O2 -Wall -Wextra -pedantic-errors -Wold-style-cast -CXXFLAGS += -std=c++11 -CXXFLAGS += -g -CXXFLAGS += $(DEPFLAGS) -LDFLAGS = -g -#CPPFLAGS += -stdlib=libc++ -#CXXFLAGS += -stdlib=libc++ -#LDFLAGS += -stdlib=libc++ - -# Targets -PROGS = test_editor test_coding print_argv - -all: $(PROGS) - -test: test_coding test_editor - ./test_coding - ./test_editor - -# Targets rely on implicit rules for compiling and linking -print_argv: print_argv.o -test_editor: test_editor.o editor.o -test_coding: test_coding.o coding.o - -# Phony targets -.PHONY: all test clean distclean - -# Standard clean -clean: - rm -f *.o $(PROGS) - -distclean: clean - rm *.d - - -# Include the *.d files -SRC = $(wildcard *.cc) --include $(SRC:.cc=.d) diff --git a/lab1/buggy_programs/.gitignore b/lab1/buggy_programs/.gitignore deleted file mode 100644 index eb7d7dc..0000000 --- a/lab1/buggy_programs/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -bounds -bounds-heap -dangling -leak -sum -ub diff --git a/lab1/buggy_programs/CMakeLists.txt b/lab1/buggy_programs/CMakeLists.txt index a11369d..c3a3b00 100644 --- a/lab1/buggy_programs/CMakeLists.txt +++ b/lab1/buggy_programs/CMakeLists.txt @@ -3,7 +3,7 @@ # It uses generator expressions, to set additional flags when the build type # is Debug. # -# To try this out, first create a build directory for a release build, +# To try this out, first create a build directory for a release build, # and do a release build, e.g., # % mkdir build-rel # % cd build-rel @@ -21,7 +21,7 @@ # # where SRC_DIR is the directory containing the source and CMakeLists.txt, # e.g., .. if your build directories are placed in this directory. -# +# # Run the examples and verify that the sanitizers find the errors. # # If you want to see the actual commands run during the build, for instance diff --git a/lab1/buggy_programs/Makefile b/lab1/buggy_programs/Makefile index 7e015e7..0f14928 100644 --- a/lab1/buggy_programs/Makefile +++ b/lab1/buggy_programs/Makefile @@ -21,20 +21,30 @@ PROGS=ub leak bounds bounds-heap dangling sum ALL: $(PROGS) leak: leak.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< dangling: dangling.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< bounds: bounds.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< ub: ub.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< sum: sum.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< -# Targets -# Phony targets .PHONY: all clean test -# Standard clean clean: - -rm $(PROGS) - -rm -r $(addsuffix .dSYM, $(PROGS)) + -rm -f $(PROGS) + -rm -rf $(addsuffix .dSYM, $(PROGS)) + +test: $(PROGS) + @echo "Running tests with Valgrind..." + @for prog in $(PROGS); do \ + echo "Testing $$prog with Valgrind:"; \ + valgrind ./$$prog; \ + echo ""; \ + done diff --git a/lab1/buggy_programs/Makefile.sanitizers b/lab1/buggy_programs/Makefile3 similarity index 100% rename from lab1/buggy_programs/Makefile.sanitizers rename to lab1/buggy_programs/Makefile3 diff --git a/lab1/buggy_programs/bounds b/lab1/buggy_programs/bounds new file mode 100755 index 0000000..64bbff0 Binary files /dev/null and b/lab1/buggy_programs/bounds differ diff --git a/lab1/buggy_programs/bounds-alt b/lab1/buggy_programs/bounds-alt new file mode 100755 index 0000000..2dc8faf Binary files /dev/null and b/lab1/buggy_programs/bounds-alt differ diff --git a/lab1/buggy_programs/bounds-heap b/lab1/buggy_programs/bounds-heap new file mode 100755 index 0000000..d00e208 Binary files /dev/null and b/lab1/buggy_programs/bounds-heap differ diff --git a/lab1/buggy_programs/bounds-heap-alt b/lab1/buggy_programs/bounds-heap-alt new file mode 100755 index 0000000..cfa4f56 Binary files /dev/null and b/lab1/buggy_programs/bounds-heap-alt differ diff --git a/lab1/buggy_programs/dangling b/lab1/buggy_programs/dangling new file mode 100755 index 0000000..d4a00d0 Binary files /dev/null and b/lab1/buggy_programs/dangling differ diff --git a/lab1/buggy_programs/leak b/lab1/buggy_programs/leak new file mode 100755 index 0000000..14051a8 Binary files /dev/null and b/lab1/buggy_programs/leak differ diff --git a/lab1/buggy_programs/sum b/lab1/buggy_programs/sum new file mode 100755 index 0000000..b708220 Binary files /dev/null and b/lab1/buggy_programs/sum differ diff --git a/lab1/buggy_programs/sum-alt b/lab1/buggy_programs/sum-alt new file mode 100755 index 0000000..7a4728a Binary files /dev/null and b/lab1/buggy_programs/sum-alt differ diff --git a/lab1/buggy_programs/ub b/lab1/buggy_programs/ub new file mode 100755 index 0000000..e0ad5a0 Binary files /dev/null and b/lab1/buggy_programs/ub differ diff --git a/lab1/buggy_programs/vgcore.12684 b/lab1/buggy_programs/vgcore.12684 new file mode 100644 index 0000000..81504c8 Binary files /dev/null and b/lab1/buggy_programs/vgcore.12684 differ diff --git a/lab1/buggy_programs/vgcore.13027 b/lab1/buggy_programs/vgcore.13027 new file mode 100644 index 0000000..f2ecbe6 Binary files /dev/null and b/lab1/buggy_programs/vgcore.13027 differ diff --git a/lab1/buggy_programs/vgcore.13797 b/lab1/buggy_programs/vgcore.13797 new file mode 100644 index 0000000..707a34d Binary files /dev/null and b/lab1/buggy_programs/vgcore.13797 differ diff --git a/lab1/cmake-example/.gitignore b/lab1/cmake-example/.gitignore deleted file mode 100644 index 378eac2..0000000 --- a/lab1/cmake-example/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build diff --git a/lab1/coding.cc b/lab1/coding.cc index 1b51ffd..c80cd87 100644 --- a/lab1/coding.cc +++ b/lab1/coding.cc @@ -1,9 +1,10 @@ -#include +#include -unsigned char encode(unsigned char c) { - return ++c; +unsigned char encode(unsigned char c) +{ + return c + 2; } - -unsigned char decode(unsigned char c) { - return --c; +unsigned char decode(unsigned char c) +{ + return c - 2; } diff --git a/lab1/coding.d b/lab1/coding.d new file mode 100644 index 0000000..d7ad881 --- /dev/null +++ b/lab1/coding.d @@ -0,0 +1,2 @@ +coding.o: coding.cc coding.h +coding.h: diff --git a/lab1/coding.o b/lab1/coding.o new file mode 100644 index 0000000..988de90 Binary files /dev/null and b/lab1/coding.o differ diff --git a/lab1/decode b/lab1/decode new file mode 100755 index 0000000..8859e72 Binary files /dev/null and b/lab1/decode differ diff --git a/lab1/decode.cc b/lab1/decode.cc new file mode 100644 index 0000000..29b36d8 --- /dev/null +++ b/lab1/decode.cc @@ -0,0 +1,34 @@ +#include +#include +#include "coding.h" + +int main(int argc, char* argv[]) { + std::string filename; + + if (argc > 1) { + filename = argv[1]; + } else { + std::cout << "Enter filename to decode: "; + std::cin >> filename; + } + + std::ifstream infile(filename, std::ios::binary); + if (!infile) { + std::cerr << "Could not open file " << filename << "\n"; + return 1; + } + + std::ofstream outfile(filename + ".dec", std::ios::binary); + if (!outfile) { + std::cerr << "Could not create output file" << "\n"; + return 1; + } + + unsigned char c; + while (infile.get(reinterpret_cast(c))) { + outfile.put(decode(c)); + } + + std::cout << "Decoding complete. Output saved to " << filename << ".dec" << "\n"; + return 0; +} \ No newline at end of file diff --git a/lab1/decode.d b/lab1/decode.d new file mode 100644 index 0000000..994ccb5 --- /dev/null +++ b/lab1/decode.d @@ -0,0 +1,2 @@ +decode.o: decode.cc coding.h +coding.h: diff --git a/lab1/decode.o b/lab1/decode.o new file mode 100644 index 0000000..70f6281 Binary files /dev/null and b/lab1/decode.o differ diff --git a/lab1/editor.cc b/lab1/editor.cc index fca27d4..e60100d 100644 --- a/lab1/editor.cc +++ b/lab1/editor.cc @@ -6,29 +6,29 @@ using std::string; using size_type = Editor::size_type; -size_type Editor::get_size() const { return text.size(); } +size_type Editor::get_size() const +{ + return text.size(); +} -Editor::size_type Editor::find_left_par(size_type pos) const { - char right_par = text[pos]; - char left_par; - - // Determine the matching left parenthesis for the given right parenthesis - switch (right_par) { - case ')': left_par = '('; break; - case ']': left_par = '['; break; - case '}': left_par = '{'; break; - default: return string::npos; // Not a valid right parenthesis +size_type Editor::find_left_par(size_type pos) const { + if (pos >= text.size() || (text[pos] != ')' && text[pos] != ']' && text[pos] != '}')) { + return std::string::npos; } - int balance = 1; // Start with the right parenthesis at text[pos] - for (size_type i = pos; i-- > 0;) { - if (text[i] == left_par) { - balance--; - if (balance == 0) return i; // Found the matching left parenthesis - } else if (text[i] == right_par) { + char right_par = text[pos]; + char left_par = (right_par == ')') ? '(' : (right_par == ']') ? '[' : '{'; + + int balance = 0; + + for (int i = pos; i >= 0; --i) { + if (text[i] == right_par) { balance++; + } else if (text[i] == left_par) { + balance--; + if (balance == 0) { + return i; + } } } - - return string::npos; // No matching left parenthesis found } diff --git a/lab1/editor.d b/lab1/editor.d new file mode 100644 index 0000000..b810e0b --- /dev/null +++ b/lab1/editor.d @@ -0,0 +1,2 @@ +editor.o: editor.cc editor.h +editor.h: diff --git a/lab1/editor.h b/lab1/editor.h index 5d6ac7b..f1a576a 100644 --- a/lab1/editor.h +++ b/lab1/editor.h @@ -4,24 +4,24 @@ #include class Editor { - public: +public: using size_type = std::string::size_type; - /* Creates a text editor containing the text t */ - Editor(const std::string &t) : text(t) {} + /* Creates a text editor containing the text t */ + Editor(const std::string& t) : text(t) {} /* Get the size of the current contents */ size_type get_size() const; - /* - * Text[pos] contains a right parentheses. Returns the position of - * the corresponding left parentheses, or string::npos if there - * is no match. - */ - size_type find_left_par(size_type pos) const; + /* + * Text[pos] contains a right parentheses. Returns the position of + * the corresponding left parentheses, or string::npos if there + * is no match. + */ + size_type find_left_par(size_type pos) const; - // ... functions to edit the text (insert and delete characters) - private: - std::string text; + // ... functions to edit the text (insert and delete characters) +private: + std::string text; }; #endif diff --git a/lab1/editor.o b/lab1/editor.o new file mode 100644 index 0000000..2c5a26f Binary files /dev/null and b/lab1/editor.o differ diff --git a/lab1/encode b/lab1/encode new file mode 100755 index 0000000..04f0bc4 Binary files /dev/null and b/lab1/encode differ diff --git a/lab1/encode.cc b/lab1/encode.cc new file mode 100644 index 0000000..200b329 --- /dev/null +++ b/lab1/encode.cc @@ -0,0 +1,35 @@ +#include +#include +#include "coding.h" + +int main (int argc, char* argv[]) { + std::string filename; + + if (argc > 1) { + filename = argv[1]; + } else { + std::cout << "Enter filename: "; + std::cin >> filename; + } + + std::ifstream infile(filename, std::ios::binary); + if (!infile) { + std::cerr << "Could not open file " << filename << "\n"; + return 1; + } + + std::string output_filename = filename + ".enc"; + std::ofstream outfile(output_filename, std::ios::binary); + if (!outfile) { + std::cerr << "Could not create output file" << "\n"; + return 1; + } + + unsigned char c; + while (infile.get(reinterpret_cast(c))) { + outfile.put(encode(c)); + } + + std::cout << "Encoding complete. Output saved to " << filename << "\n"; + return 0; +} \ No newline at end of file diff --git a/lab1/encode.d b/lab1/encode.d new file mode 100644 index 0000000..66f2ed5 --- /dev/null +++ b/lab1/encode.d @@ -0,0 +1,2 @@ +encode.o: encode.cc coding.h +coding.h: diff --git a/lab1/encode.o b/lab1/encode.o new file mode 100644 index 0000000..824425d Binary files /dev/null and b/lab1/encode.o differ diff --git a/lab1/hello b/lab1/hello new file mode 100755 index 0000000..2529b03 Binary files /dev/null and b/lab1/hello differ diff --git a/lab1/hello.cc b/lab1/hello.cc index b873300..96f5da4 100644 --- a/lab1/hello.cc +++ b/lab1/hello.cc @@ -1,5 +1,7 @@ #include -int main(int argc, char *argv[]) { - std::cout << "Hello" << std::endl; -} +int main() { + std::cout << "Hello, World!" << "\n"; + std::cout << "Hello, World!" << "\n"; + return 0; +} \ No newline at end of file diff --git a/lab1/hello.d b/lab1/hello.d new file mode 100644 index 0000000..a3f4bad --- /dev/null +++ b/lab1/hello.d @@ -0,0 +1 @@ +hello: hello.cc diff --git a/lab1/print_argv b/lab1/print_argv new file mode 100755 index 0000000..048b643 Binary files /dev/null and b/lab1/print_argv differ diff --git a/lab1/print_argv.d b/lab1/print_argv.d new file mode 100644 index 0000000..363ab24 --- /dev/null +++ b/lab1/print_argv.d @@ -0,0 +1 @@ +print_argv.o: print_argv.cc diff --git a/lab1/print_argv.o b/lab1/print_argv.o new file mode 100644 index 0000000..da01df8 Binary files /dev/null and b/lab1/print_argv.o differ diff --git a/lab1/reflektion.txt b/lab1/reflektion.txt new file mode 100644 index 0000000..c676a3e --- /dev/null +++ b/lab1/reflektion.txt @@ -0,0 +1,49 @@ +1. What is the difference between a declaration and a definition? + +A declaration tells the compiler about the existence of a variable or function, +while a definition allocates storage or provides the function code. + + +2. How does an include guard prevent multiple definitions? + +An include guard (using #ifndef, #define, #endif) +prevents a header file from being included multiple times, which avoids redefinitions. + + +3. How can you tell if an error comes from the compiler or the linker? Does a linker error +mean that you have an error in your source code? How do you (typically) fix a linker error? + +Compiler errors are syntax or semantic issues in code, while linker errors occur when symbols +are missing or duplicated across files. A linker error often means a missing definition or library; it’s fixed by ensuring all functions and variables are correctly defined and linked. + + +4. Do you have to make any changes to MakefileWithDeps to build your hello world program? + +You may need to adjust MakefileWithDeps +if dependencies or file paths change for your hello world program. + + +5. In encode and decode, the type unsigned char is used. Would your code work the same +way if that type is changed to char or signed char? + +Changing unsigned char to char or signed char +may alter the behavior due to differences in handling negative values. + + +6. In the coding problem, reading the file with char ch; while (infile >> ch) ... doesn’t +work. Why? + +infile >> ch reads formatted input, skipping whitespace; +using infile.get(ch) reads every character, including whitespace. + + +7. If your program crashes, how can you use the debugger to get a stack trace similar to that +of Exception.printStackTrace() in Java? + +lldb ./progrma -> run -> bt + + +8. What is the difference between a debugger breakpoint and a watchpoint? + +A breakpoint pauses execution at a specific line, +while a watchpoint stops execution when a specific variable changes. \ No newline at end of file diff --git a/lab1/stream-examples/Makefile b/lab1/stream-examples/Makefile index 3221e68..7c657b9 100644 --- a/lab1/stream-examples/Makefile +++ b/lab1/stream-examples/Makefile @@ -25,6 +25,8 @@ PROGS = read-words example-out all: $(PROGS) +test: ./example-out ./read-words + # Phony targets .PHONY: all test clean distclean diff --git a/lab1/stream-examples/err.txt b/lab1/stream-examples/err.txt new file mode 100644 index 0000000..9476609 --- /dev/null +++ b/lab1/stream-examples/err.txt @@ -0,0 +1,2 @@ +And this is written to stderr +And some more to stderr diff --git a/lab1/stream-examples/example-out b/lab1/stream-examples/example-out new file mode 100755 index 0000000..b5bb6c8 Binary files /dev/null and b/lab1/stream-examples/example-out differ diff --git a/lab1/stream-examples/example-out.d b/lab1/stream-examples/example-out.d new file mode 100644 index 0000000..c912c8a --- /dev/null +++ b/lab1/stream-examples/example-out.d @@ -0,0 +1 @@ +example-out: example-out.cc diff --git a/lab1/stream-examples/out.txt b/lab1/stream-examples/out.txt new file mode 100644 index 0000000..2b53dce --- /dev/null +++ b/lab1/stream-examples/out.txt @@ -0,0 +1,2 @@ +This text is written to stdout +More text to stdout diff --git a/lab1/stream-examples/read-words b/lab1/stream-examples/read-words new file mode 100755 index 0000000..d281fe4 Binary files /dev/null and b/lab1/stream-examples/read-words differ diff --git a/lab1/stream-examples/read-words.d b/lab1/stream-examples/read-words.d new file mode 100644 index 0000000..176523b --- /dev/null +++ b/lab1/stream-examples/read-words.d @@ -0,0 +1 @@ +read-words: read-words.cc diff --git a/lab1/test_coding b/lab1/test_coding new file mode 100755 index 0000000..7e09ccb Binary files /dev/null and b/lab1/test_coding differ diff --git a/lab1/test_coding.d b/lab1/test_coding.d new file mode 100644 index 0000000..cbbbb42 --- /dev/null +++ b/lab1/test_coding.d @@ -0,0 +1,2 @@ +test_coding.o: test_coding.cc coding.h +coding.h: diff --git a/lab1/test_coding.o b/lab1/test_coding.o new file mode 100644 index 0000000..a588974 Binary files /dev/null and b/lab1/test_coding.o differ diff --git a/lab1/test_editor b/lab1/test_editor new file mode 100755 index 0000000..d141ad4 Binary files /dev/null and b/lab1/test_editor differ diff --git a/lab1/test_editor.d b/lab1/test_editor.d new file mode 100644 index 0000000..edfdcf1 --- /dev/null +++ b/lab1/test_editor.d @@ -0,0 +1,2 @@ +test_editor.o: test_editor.cc editor.h +editor.h: diff --git a/lab1/test_editor.o b/lab1/test_editor.o new file mode 100644 index 0000000..b367fc2 Binary files /dev/null and b/lab1/test_editor.o differ diff --git a/lab1/testfile.txt b/lab1/testfile.txt new file mode 100644 index 0000000..0032b0f --- /dev/null +++ b/lab1/testfile.txt @@ -0,0 +1 @@ +Hello my name is Douglas \ No newline at end of file diff --git a/lab1/testfile.txt.dec b/lab1/testfile.txt.dec new file mode 100644 index 0000000..b975562 --- /dev/null +++ b/lab1/testfile.txt.dec @@ -0,0 +1 @@ +Fcjjmkwl_kcgqBmsej_q \ No newline at end of file diff --git a/lab1/testfile.txt.enc b/lab1/testfile.txt.enc new file mode 100644 index 0000000..e7211eb --- /dev/null +++ b/lab1/testfile.txt.enc @@ -0,0 +1 @@ +Jgnnq"o{"pcog"ku"Fqwincu \ No newline at end of file diff --git a/lab1/testfile.txt.enc.dec b/lab1/testfile.txt.enc.dec new file mode 100644 index 0000000..0032b0f --- /dev/null +++ b/lab1/testfile.txt.enc.dec @@ -0,0 +1 @@ +Hello my name is Douglas \ No newline at end of file diff --git a/lab2/Makefile b/lab2/Makefile deleted file mode 100644 index aaa709f..0000000 --- a/lab2/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -CXX = g++ -CXXFLAGS = -Wall -Wextra -Wpedantic -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual -Wconversion -Wsign-conversion -Wnull-dereference -Wdouble-promotion -Wformat=2 -std=c++17 -#CXXFLAGS += -Werror - -SRC = $(wildcard *.cc) -HDR = $(wildcard *.h) -OBJ = $(SRC:.cc=.o) - -all: spell edit $(OBJ) - -edit: test_edit_distance.o edit_distance.o - @echo "Building & linking $@" - @$(CXX) $(CXXFLAGS) $^ -o $@ - -spell: spell.o word.o dictionary.o edit_distance.o - @echo "Building & linking $@" - @$(CXX) $(CXXFLAGS) $^ -o $@ - -%.o:%.cc - @echo "Building $@" - @$(CXX) -c $(CXXFLAGS) $< -o $@ - -lint: clang-tidy cppcheck clang-format - -clang-tidy: - clang-tidy $(SRC) -- $(CXXFLAGS) - -cppcheck: - cppcheck --enable=all --language=c++ --std=c++17 --suppress=missingIncludeSystem -I/usr/include $(SRC) $(HDR) - -clang-format: - clang-format -i $(SRC) $(HDR) - -clean: - rm -f *.o spell edit - -.PHONY: clean all lint clang-tidy cppcheck clang-format diff --git a/lab2/dictionary.cc b/lab2/dictionary.cc index 2e999c8..79bb69e 100644 --- a/lab2/dictionary.cc +++ b/lab2/dictionary.cc @@ -1,131 +1,22 @@ -#include "dictionary.h" -#include "edit_distance.h" -#include "word.h" -#include -#include -#include -#include #include #include +#include +#include +#include +#include "word.h" +#include "dictionary.h" using std::string; using std::vector; -Dictionary::Dictionary() {} - -bool Dictionary::contains(const string &word) const { - auto l = word.length(); - Word w = Word(word); - if (std::find(this->words[l].begin(), this->words[l].end(), w) != - std::end(this->words[l])) { - return true; - } - return false; +Dictionary::Dictionary() { } -std::vector Dictionary::get_suggestions(const string &word) const { - vector suggestions; - add_trigram_suggestions(suggestions, word); - trim_suggestions(suggestions, word); - rank_suggestions(suggestions, word); - return suggestions; +bool Dictionary::contains(const string& word) const { + return true; } -void Dictionary::add_trigram_suggestions(std::vector &suggestions, - const std::string &word) const { - // Get trigrams of the input word - Word input_word(word); - const std::vector &input_trigrams = input_word.get_trigrams(); - - // Iterate through all words in the dictionary - for (int i = 0; i < MAXLEN; ++i) { - for (const Word &dict_word : words[i]) { - // Get the trigrams of the dictionary word - const std::vector &dict_word_trigrams = - dict_word.get_trigrams(); - - // Count how many trigrams match - unsigned int match_count = dict_word.get_matches(input_trigrams); - - // If there are any matches, add the word to suggestions - if (match_count > 0) { - suggestions.push_back(dict_word.get_word()); - } - } - } -} - -void Dictionary::rank_suggestions(std::vector &suggestions, - const std::string &word) const { - // Sort suggestions based on the levenshtein distance - std::sort(suggestions.begin(), suggestions.end(), - [&](const std::string &a, const std::string &b) { - auto dist_a = edit_distance(a, word); - auto dist_b = edit_distance(b, word); - return dist_a < dist_b; - }); -} - -void Dictionary::trim_suggestions(std::vector &suggestions, - const std::string &word) const { - // Remove duplicates using a set - std::set unique_suggestions(suggestions.begin(), - suggestions.end()); - suggestions.assign(unique_suggestions.begin(), unique_suggestions.end()); - - // Remove the input word from the suggestions list (if present) - suggestions.erase(std::remove(suggestions.begin(), suggestions.end(), word), - suggestions.end()); - - auto l = word.length(); - std::cout << "WTF" << l << std::endl; - - // Example: Remove any suggestions that are not within 1 string length - suggestions.erase(std::remove_if(suggestions.begin(), suggestions.end(), - [l](const std::string &s) { - return s.length() > (l + 1) || - s.length() < (l - 1); - }), - suggestions.end()); -} - -int Dictionary::spit(path p) { - std::ofstream file(p); - - if (!file.is_open()) { - std::cerr << "Error opening file! " << std::endl; - return 1; - } - - for (int a = 0; a < MAXLEN; a++) { - for (auto &word : words[a]) { - file << word; - file << std::endl; - } - } - - file.flush(); - file.close(); - return 0; -} - -int Dictionary::slurp(path p) { - std::ifstream file(p.string()); - - if (!file.is_open()) { - std::cerr << "Error opening file! " << std::endl; - return 1; - } - - std::string line; - while (std::getline(file, line)) { - if (line.empty()) - continue; - // Words larger than max gets placed in the topmost bucket - words[std::min(line.size(), static_cast(MAXLEN) - 1)].push_back( - Word(line)); - } - - file.close(); - return 0; +vector Dictionary::get_suggestions(const string& word) const { + vector suggestions; + return suggestions; } diff --git a/lab2/dictionary.h b/lab2/dictionary.h index 31eada4..b56f143 100644 --- a/lab2/dictionary.h +++ b/lab2/dictionary.h @@ -1,29 +1,15 @@ -#pragma once +#ifndef DICTIONARY_H +#define DICTIONARY_H -#include "word.h" -#include #include #include -#define MAXLEN 30 - -// using std::vector; -using std::filesystem::path; - class Dictionary { - public: - Dictionary(); - void add_trigram_suggestions(std::vector &suggestions, - const std::string &word) const; - void rank_suggestions(std::vector &suggestions, - const std::string &word) const; - void trim_suggestions(std::vector &suggestions, - const std::string &word) const; - bool contains(const std::string &word) const; - std::vector get_suggestions(const std::string &word) const; - int slurp(path p); - int spit(path p); - - private: - std::vector words[MAXLEN]; +public: + Dictionary(); + bool contains(const std::string& word) const; + std::vector get_suggestions(const std::string& word) const; +private: }; + +#endif diff --git a/lab2/edit_distance.cc b/lab2/edit_distance.cc deleted file mode 100644 index 7f635c9..0000000 --- a/lab2/edit_distance.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include - -int edit_distance(const std::string &s1, const std::string &s2) { - size_t m = s1.size(); - size_t n = s2.size(); - - // Create a 2D DP table - std::vector> dp(m + 1, std::vector(n + 1)); - - // Fill the base cases - for (size_t i = 0; i <= m; ++i) - dp[i][0] = i; // Deletion cost - - for (size_t j = 0; j <= n; ++j) - dp[0][j] = j; // Insertion cost - - // Fill the DP table - for (size_t i = 1; i <= m; ++i) { - for (size_t j = 1; j <= n; ++j) { - if (s1[i - 1] == s2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1]; // No operation needed - } else { - dp[i][j] = 1 + std::min({ - dp[i - 1][j], // Deletion - dp[i][j - 1], // Insertion - dp[i - 1][j - 1] // Substitution - }); - } - } - } - - return static_cast(dp[m][n]); -} diff --git a/lab2/edit_distance.h b/lab2/edit_distance.h deleted file mode 100644 index 6ddc48a..0000000 --- a/lab2/edit_distance.h +++ /dev/null @@ -1,17 +0,0 @@ -#include - -/** - * @brief Computes the edit distance (Levenshtein distance) between two strings. - * - * The edit distance is defined as the minimum number of single-character edits - * (insertions, deletions, or substitutions) required to transform one string - * into the other. - * - * This implementation uses dynamic programming to compute the distance - * efficiently. - * - * @param s1 The first string. - * @param s2 The second string. - * @return The edit distance between the two strings. - */ -int edit_distance(const std::string &s1, const std::string &s2); diff --git a/lab2/spell.cc b/lab2/spell.cc index 38f0249..dfb820b 100644 --- a/lab2/spell.cc +++ b/lab2/spell.cc @@ -1,18 +1,18 @@ -#include "dictionary.h" -#include -#include -#include #include #include +#include #include +#include +#include "dictionary.h" +using std::string; +using std::vector; using std::cin; using std::cout; using std::endl; -using std::string; -using std::vector; -void check_word(const string &word, const Dictionary &dict) { +void check_word(const string& word, const Dictionary& dict) +{ if (dict.contains(word)) { cout << "Correct." << endl; } else { @@ -21,22 +21,18 @@ void check_word(const string &word, const Dictionary &dict) { cout << "Wrong, no suggestions." << endl; } else { cout << "Wrong. Suggestions:" << endl; - for (const auto &w : suggestions) { + for (const auto& w : suggestions) { cout << " " << w << endl; } } } } - int main() { - Dictionary dict; - string word; - dict.slurp(std::filesystem::path("/usr/share/dict/words")); - // dict.spit(std::filesystem::path("words.txt")); - - while (cin >> word) { - std::transform(word.begin(), word.end(), word.begin(), ::tolower); + Dictionary dict; + string word; + while (cin >> word) { + transform(word.begin(), word.end(), word.begin(), ::tolower); check_word(word, dict); - } + } return 0; } diff --git a/lab2/test_edit_distance.cc b/lab2/test_edit_distance.cc index 982badf..1f44719 100644 --- a/lab2/test_edit_distance.cc +++ b/lab2/test_edit_distance.cc @@ -8,7 +8,8 @@ #include -bool do_test(const std::string &x, const std::string &y, int expected) { +bool do_test(const std::string& x, const std::string& y, int expected) +{ auto actual = edit_distance(x, y); if (actual != expected) { std::cout << "*** WRONG: distance(" << x << ", " << y << ") was " @@ -18,7 +19,8 @@ bool do_test(const std::string &x, const std::string &y, int expected) { return false; } -int main() { +int main() +{ int res = do_test("foobar", "foobar", 0); res += do_test("x", "x", 0); res += do_test("baz", "bar", 1); diff --git a/lab2/word.cc b/lab2/word.cc index 293f66e..20b9417 100644 --- a/lab2/word.cc +++ b/lab2/word.cc @@ -1,63 +1,16 @@ -#include "word.h" -#include "dictionary.h" -#include #include #include +#include "word.h" -using std::string; using std::vector; +using std::string; -Word::Word(const string &w, const vector &t) : word(w), trigrams(t) { - std::sort(trigrams.begin(), trigrams.end()); +Word::Word(const string& w, const vector& t) {} + +string Word::get_word() const { + return string(); } -std::vector get_trigrams(const std::string &text) { - std::vector trigrams; - if (text.size() < 3) { - return trigrams; // Return an empty vector if the input is too short - } - - for (size_t i = 0; i <= text.size() - 3; ++i) { - trigrams.push_back( - text.substr(i, 3)); // Extract a substring of length 3 - } - - return trigrams; -} - -Word::Word(const std::string &w) : word(w) { - this->trigrams = ::get_trigrams(w); - std::sort(trigrams.begin(), trigrams.end()); -} - -string Word::get_word() const { return word; } - -vector Word::get_trigrams() const { return trigrams; } - -unsigned int Word::get_matches(const vector &t) const { - unsigned int matches = 0; - - for (const auto &trigram : t) { - if (std::binary_search(trigrams.begin(), trigrams.end(), trigram)) { - ++matches; - } - } - return matches; -} - -std::ostream &operator<<(std::ostream &out, const Word &w) { - auto space = string(" "); - out << w.word; - out << space; - out << w.trigrams.size(); - for (const auto &tri : w.trigrams) { - out << space << tri; - } - return out; -} - -bool operator==(const Word &lhs, const Word &rhs) { - return lhs.word == rhs.word && - std::equal(lhs.trigrams.begin(), lhs.trigrams.end(), - rhs.trigrams.begin()); +unsigned int Word::get_matches(const vector& t) const { + return 0; } diff --git a/lab2/word.h b/lab2/word.h index 27b92af..9fb0716 100644 --- a/lab2/word.h +++ b/lab2/word.h @@ -1,34 +1,21 @@ -#pragma once +#ifndef WORD_H +#define WORD_H #include #include -/* - * Contains a word and its trigrams - */ class Word { - public: - /** Creates a word w with the sorted trigrams t */ - Word(const std::string &w, const std::vector &t); - - /** Creates a word w and derives the trigrams internally */ - Word(const std::string &w); - - /** Returns the word */ - std::string get_word() const; - - /** Returns trigrams */ - std::vector get_trigrams() const; - - /** Returns how many of the trigrams in t that are present - in this word's trigram vector */ - unsigned int get_matches(const std::vector &t) const; - - private: - const std::string word; - std::vector trigrams; - friend std::ostream &operator<<(std::ostream &out, const Word &o); - friend bool operator==(const Word &lhs, const Word &rhs); +public: + /* Creates a word w with the sorted trigrams t */ + Word(const std::string& w, const std::vector& t); + + /* Returns the word */ + std::string get_word() const; + + /* Returns how many of the trigrams in t that are present + in this word's trigram vector */ + unsigned int get_matches(const std::vector& t) const; +private: }; -bool operator==(const Word &lhs, const Word &rhs); +#endif diff --git a/lab3/Makefile b/lab3/Makefile deleted file mode 100644 index e6d004c..0000000 --- a/lab3/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CXX = g++ -CXXFLAGS = -Wall -Wextra -Wpedantic -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual -Wconversion -Wsign-conversion -Wnull-dereference -Wdouble-promotion -Wformat=2 -std=c++17 -#CXXFLAGS += -Werror - -SRC = $(wildcard *.cc) -HDR = $(wildcard *.h) -OBJ = $(SRC:.cc=.o) - -all: tabletest $(OBJ) - -tabletest: $(OBJ) - @echo "Building & linking $@" - @$(CXX) $(CXXFLAGS) $^ -o $@ - -%.o:%.cc - @echo "Building $@" - @$(CXX) -c $(CXXFLAGS) $< -o $@ - -lint: clang-tidy cppcheck clang-format - -clang-tidy: - clang-tidy $(SRC) -- $(CXXFLAGS) - -cppcheck: - cppcheck --enable=all --language=c++ --std=c++17 --suppress=missingIncludeSystem -I/usr/include $(SRC) $(HDR) - -clang-format: - clang-format -i $(SRC) $(HDR) - -clean: - rm -f *.o spell edit - -.PHONY: clean all lint clang-tidy cppcheck clang-format diff --git a/lab3/User.cc b/lab3/User.cc index d45437e..0268bd2 100644 --- a/lab3/User.cc +++ b/lab3/User.cc @@ -1,5 +1,6 @@ #include "User.h" -std::ostream &operator<<(std::ostream &os, const User &u) { - return os << "(" << u.getCardNbr() << ") " << u.getName(); +std::ostream& operator<<(std::ostream& os, const User& u) +{ + return os << "(" << u.getCardNbr() << ") "<< u.getName(); } diff --git a/lab3/User.h b/lab3/User.h index b4a8868..cbedfe0 100644 --- a/lab3/User.h +++ b/lab3/User.h @@ -8,26 +8,20 @@ using std::cout; using std::endl; class User { - public: - User() : cardNbr{0}, name{"default"} {} - User(int c, std::string n) : cardNbr{c}, name{n} {} - ~User() { - cardNbr = -2; - name = "--------------------"; - } // overwrite values for security reasons - User(const User &u) = default; - User &operator=(const User &) = default; - int getCardNbr() const { return cardNbr; } - std::string getName() const { return name; } - bool operator==(const User &u) const { - return cardNbr == u.cardNbr && name == u.name; - } - bool operator!=(const User &u) const { return !(u == *this); } - - private: +public: + User() :cardNbr{0},name{"default"}{} + User(int c, std::string n) :cardNbr{c},name{n} {} + ~User() {cardNbr=-2; name="--------------------";} // overwrite values for security reasons + User(const User& u) =default; + User& operator=(const User&) =default; + int getCardNbr() const {return cardNbr;} + std::string getName() const {return name;} + bool operator==(const User& u) const {return cardNbr == u.cardNbr && name == u.name;} + bool operator!=(const User& u) const {return ! (u == *this);} +private: int cardNbr; std::string name; }; -std::ostream &operator<<(std::ostream &os, const User &u); +std::ostream& operator<<(std::ostream& os, const User& u); #endif diff --git a/lab3/UserTable.cc b/lab3/UserTable.cc index 542cd0d..91db558 100644 --- a/lab3/UserTable.cc +++ b/lab3/UserTable.cc @@ -1,22 +1,24 @@ #include "UserTable.h" -#include #include +#include -const User UserTable::user_not_found = User{-1, "Not Found"}; +const User UserTable::user_not_found = User{-1,"Not Found"}; -UserTable::UserTable() : users{new User[capacity]} {} +UserTable::UserTable() :users{new User[capacity]} { } -UserTable::UserTable(const std::string &fname) : UserTable{} { +UserTable::UserTable(const std::string& fname) :UserTable{} +{ std::ifstream ufile(fname); - if (ufile.is_open()) { - while (ufile) { + if(ufile.is_open()) { + while(ufile) { int cn; - if (ufile >> cn) { + if(ufile >> cn ) { ufile.ignore(); // skip space char n[80]; - ufile.getline(n, 80); - addUser(User(cn, n)); + ufile.getline(n,80); + addUser(User(cn,n)); + } } } else { @@ -24,39 +26,38 @@ UserTable::UserTable(const std::string &fname) : UserTable{} { } } -void UserTable::addUser(const User &u) { +void UserTable::addUser(const User& u) +{ // gör tabellen större vid behov - ensureCapacity(n + 1); - + ensureCapacity(n+1); // 1. Hitta rätt plats int pos{0}; - while ((pos < n) && (users[pos].getCardNbr() < u.getCardNbr())) { + while ( (pos < n) && (users[pos].getCardNbr() < u.getCardNbr())){ ++pos; } - // 2. skapa lucka i vektorn - for (int i = n; i > pos; --i) { - users[i] = users[i - 1]; + //2. skapa lucka i vektorn + for(int i=n; i > pos; --i){ + users[i] = users[i-1]; } - // 3. stoppa in den nya användaren i luckan + //3. stoppa in den nya användaren i luckan users[pos] = u; - - ++n; } -User UserTable::find(int c) const { +User UserTable::find(int c) const +{ // binärsökning (baserad på Holm, 2007) int low = 0; int high = n - 1; int mid = -1; bool found = false; - while (low < high && !found) { + while (low < high && ! found) { mid = (low + high) / 2; // - const int midnbr = users[mid].getCardNbr(); - if (c == midnbr) { + int midnbr = users[mid].getCardNbr(); + if (midnbr = c) { found = true; } else if (users[mid].getCardNbr() < c) { low = mid + 1; @@ -67,41 +68,48 @@ User UserTable::find(int c) const { return found ? users[mid] : user_not_found; } -User UserTable::find(std::string name) const { - auto it = std::find_if(users, users + n, [&name](const User &u) { - return u.getName() == name; - }); - - // If it is at the 'end' of users, the result is not found - return (it != users+n) ? *it : user_not_found; +User UserTable::find(std::string name) const +{ + for (int i = 0; i != n; ++i) { + if (users[i].getName() == name) { + return users[i]; + } else { + return user_not_found; + } + } + return user_not_found; } -void UserTable::ensureCapacity(int s) { - if (s > capacity) { - while (s > capacity) { - capacity *= 4; +void UserTable::ensureCapacity(int s) +{ + if(s>capacity) { + while(s > capacity) { + capacity*=4; } auto tmp = new User[capacity]; - std::copy(users, users + n, tmp); + std::copy(users, users+n, tmp); delete[] users; - users = tmp; + users=tmp; } + } -void UserTable::print(std::ostream &os) const { +void UserTable::print(std::ostream& os) const +{ os << "-------------" << std::endl; - for (int i = 0; i != getNbrUsers(); ++i) { - const auto &u = users[i]; - os << "(" << u.getCardNbr() << ") " << u.getName() << std::endl; + for(int i = 0; i != getNbrUsers(); ++i) { + const auto& u = users[i]; + os << "(" < - -int main() { - { /* User Related Tests */ - // Two identical users - User u1 = User(1234, "Name Nameson"); - User u2 = User(1234, "Name Nameson"); - - assert(u1.getName() == u2.getName()); - assert(u1.getCardNbr() == u2.getCardNbr()); - - // Two different users - User u3 = User(1200, "Name Surname"); - User u4 = User(1201, "Name Nameson"); - - assert(u3.getName() != u4.getName()); - assert(u3.getCardNbr() != u4.getCardNbr()); - } - { /* Table Related Tests */ - UserTable tbl1 = UserTable(); - assert(tbl1.find("Jens Holmgren") == UserTable::user_not_found); - tbl1.addUser(User(1200, "Table Yes")); - assert(tbl1.getNbrUsers() == 1); - } - { - // Assumes 'users.txt' is present, containing - // line separated records formatted as: - // "89524 Adam Abrahamsson" - UserTable tbl = UserTable("users.txt"); - assert(tbl.getNbrUsers() > 0); - assert(tbl.find("Jens Holmgren") != UserTable::user_not_found); - - tbl.addUser(User(1200, "Name Surname")); - User ufind1 = tbl.find(1200); - assert(ufind1 != UserTable::user_not_found); - - User ufind2 = tbl.find("Name Surname"); - assert(ufind2 != UserTable::user_not_found); - } -} diff --git a/lab4/Sieve.cc b/lab4/Sieve.cc deleted file mode 100644 index 9360a66..0000000 --- a/lab4/Sieve.cc +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -class Sieve { -private: - std::string sieve; - -public: - // Constructor to initialize sieve with 'P' (prime assumption) - Sieve(size_t limit) : sieve(limit + 1, 'P') { - // 0 and 1 are not primes - sieve[0] = 'C'; - if (limit > 0) sieve[1] = 'C'; - - // Sieve of Eratosthenes - for (size_t i = 2; i * i <= limit; ++i) { - if (sieve[i] == 'P') { - for (size_t j = i * i; j <= limit; j += i) { - sieve[j] = 'C'; - } - } - } - } - - // Get primes as a vector of integers - std::vector getPrimes() const { - std::vector primes; - for (size_t i = 2; i < sieve.size(); ++i) { - if (sieve[i] == 'P') { - primes.push_back(i); - } - } - return primes; - } - - // Print all primes in the range - void printPrimesInRange(int start, int end) const { - for (int i = start; i <= end; ++i) { - if (sieve[i] == 'P') { - std::cout << i << " "; - } - } - std::cout << std::endl; - } - - // Get the largest prime below a limit - int largestPrimeBelow(int limit) const { - for (int i = limit; i >= 2; --i) { - if (sieve[i] == 'P') { - return i; - } - } - return -1; // If no prime is found - } -}; - -// Main function for testing -int main() { - const int limit = 100000; - - // Create a Sieve instance for the range 0 to limit - Sieve sieve(limit); - - // Print primes between 1 and 200 - std::cout << "Primes between 1 and 200:" << std::endl; - sieve.printPrimesInRange(1, 200); - - // Find and print the largest prime below 100,000 - int largestPrime = sieve.largestPrimeBelow(limit); - std::cout << "Largest prime below " << limit << ": " << largestPrime << std::endl; - - return 0; -} diff --git a/lab4/TagRemover.cc b/lab4/TagRemover.cc deleted file mode 100644 index 3f28d28..0000000 --- a/lab4/TagRemover.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include - -class TagRemover { -private: - std::string content; - -public: - TagRemover(std::istream& input) { - std::string line; - while (std::getline(input, line)) { - content += line + '\n'; - } - } - - void print(std::ostream& output) const { - std::string result = std::regex_replace(content, std::regex("<[^>]*>"), ""); - result = std::regex_replace(result, std::regex("<"), "<"); - result = std::regex_replace(result, std::regex(">"), ">"); - result = std::regex_replace(result, std::regex(" "), " "); - result = std::regex_replace(result, std::regex("&"), "&"); - - output << result; - } -}; - -int main() { - TagRemover tr(std::cin); - tr.print(std::cout); - return 0; -} \ No newline at end of file diff --git a/lab4/date.cc b/lab4/date.cc index bf6e37d..ee9b34a 100644 --- a/lab4/date.cc +++ b/lab4/date.cc @@ -1,86 +1,30 @@ -#include // för tid och localtime -#include // för setw och setfill -#include // för inputhantering +#include // time and localtime #include "date.h" int Date::daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -// Konstruktor: dagens datum Date::Date() { - time_t timer = time(0); // tid i sekunder sedan 1970-01-01 - tm* locTime = localtime(&timer); // lokal tid - year = 1900 + locTime->tm_year; - month = 1 + locTime->tm_mon; - day = locTime->tm_mday; + time_t timer = time(0); // time in seconds since 1970-01-01 + tm* locTime = localtime(&timer); // broken-down time + year = 1900 + locTime->tm_year; + month = 1 + locTime->tm_mon; + day = locTime->tm_mday; } -// Konstruktor: specifikt datum -Date::Date(int y, int m, int d) : year(y), month(m), day(d) {} +Date::Date(int y, int m, int d) {} -// Get-funktioner int Date::getYear() const { - return year; + return 0; } int Date::getMonth() const { - return month; + return 0; } int Date::getDay() const { - return day; + return 0; } -// Gå till nästa dag void Date::next() { - day++; - if (day > daysPerMonth[month - 1] + (month == 2 && isLeapYear(year))) { - day = 1; - month++; - if (month > 12) { - month = 1; - year++; - } - } } -// Kontrollera om ett år är ett skottår -bool Date::isLeapYear(int year) { - return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); -} - -// Overloaded operator<< (output) -std::ostream& operator<<(std::ostream& os, const Date& date) { - os << std::setw(4) << std::setfill('0') << date.getYear() << '-' - << std::setw(2) << std::setfill('0') << date.getMonth() << '-' - << std::setw(2) << std::setfill('0') << date.getDay(); - return os; -} - -// Overloaded operator>> (input) -std::istream& operator>>(std::istream& is, Date& date) { - std::string input; - is >> input; - - std::istringstream iss(input); - char dash1, dash2; - int y, m, d; - - if (iss >> y >> dash1 >> m >> dash2 >> d && dash1 == '-' && dash2 == '-') { - // Validera månad och dag - if (m >= 1 && m <= 12) { - int maxDay = Date::daysPerMonth[m - 1]; - if (m == 2 && Date::isLeapYear(y)) { - maxDay = 29; // Februari har 29 dagar under skottår - } - - if (d >= 1 && d <= maxDay) { - date = Date(y, m, d); // Sätt datumet om det är giltigt - return is; - } - } - } - - // Ogiltig inmatning - is.setstate(std::ios_base::failbit); - return is; -} diff --git a/lab4/date.h b/lab4/date.h index 25b57df..9cfecaa 100644 --- a/lab4/date.h +++ b/lab4/date.h @@ -1,27 +1,19 @@ #ifndef DATE_H #define DATE_H -#include - class Date { public: - Date(); // dagens datum - Date(int y, int m, int d); // yyyy-mm-dd - int getYear() const; // returnerar året - int getMonth() const; // returnerar månaden - int getDay() const; // returnerar dagen - void next(); // går till nästa dag - - // Overloaded operators - friend std::ostream& operator<<(std::ostream& os, const Date& date); - friend std::istream& operator>>(std::istream& is, Date& date); - + Date(); // today's date + Date(int y, int m, int d); // yyyy-mm-dd + int getYear() const; // get the year + int getMonth() const; // get the month + int getDay() const; // get the day + void next(); // advance to next day private: - int year; // året (fyra siffror) - int month; // månaden (1-12) - int day; // dagen (1-...) - static int daysPerMonth[12]; // antal dagar i varje månad - static bool isLeapYear(int year); // kontrollera skottår + int year; // the year (four digits) + int month; // the month (1-12) + int day; // the day (1-..) + static int daysPerMonth[12]; // number of days in each month }; #endif diff --git a/lab4/date_test.cc b/lab4/date_test.cc index c66ee07..abd24c9 100644 --- a/lab4/date_test.cc +++ b/lab4/date_test.cc @@ -1,40 +1,64 @@ #include +#include // for setw and setfill #include "date.h" -int main() { - // Test input och output - bool cont = true; - while (cont) { - std::cout << "Type a date: "; - Date aDate; - std::cin >> aDate; +using std::cout; +using std::endl; +using std::setw; +using std::setfill; - if (std::cin.eof()) { - cont = false; - } else if (!std::cin.good()) { - std::cout << "Wrong input format" << std::endl; - std::cin.clear(); - std::cin.ignore(10000, '\n'); - } else { - std::cout << "Output: " << aDate << std::endl; - } - } - - // Testa 'next' med dagens datum - std::cout << "--- Today and more than a month ahead:" << std::endl; - Date d1; - std::cout << d1 << std::endl; - for (int i = 1; i <= 35; ++i) { - d1.next(); - std::cout << d1 << std::endl; - } - - // Testa 'next' från nyårsafton - std::cout << "--- New Year's Eve and the next day:" << std::endl; - Date d2(2013, 12, 31); - std::cout << d2 << std::endl; - d2.next(); - std::cout << d2 << std::endl; - - return 0; +/* + * Prints the date d in the format yyyy-mm-dd. You shall replace this + * function with an overloaded operator<<, and add an overloaded operator>>. + * + */ +void print(const Date& d) { + cout << setw(4) << setfill('0') << d.getYear() << '-'; + cout << setw(2) << setfill('0') << d.getMonth() << '-'; + cout << setw(2) << setfill('0') << d.getDay(); +} + +int main() { + // Check input and output of dates. Uncomment the following when you + // have added operator>> and operator<<. + /* + bool cont = true; + while (cont) { + cout << "Type a date: "; + Date aDate; + cin >> aDate; + if (cin.eof()) { + cont = false; + } else if (!cin.good()) { + cout << "Wrong input format" << endl; + // restore stream state and ignore the rest of the line + cin.clear(); + cin.ignore(10000, '\n'); + } + else { + cout << "Output: " << aDate << endl; + } + } + */ + + // Check 'next' by creating an object describing today's date, then + // printing dates more than a month ahead + cout << "--- Today and more than a month ahead:" << endl; + Date d1; + print(d1); + cout << endl; + for (int i = 1; i <= 35 ; ++i) { + d1.next(); + print(d1); + cout << endl; + } + + // Check so 'next' functions correctly from one year to the next + cout << "--- New Year's Eve and the next day:" << endl; + Date d2(2013, 12, 31); + print(d2); + cout << endl; + d2.next(); + print(d2); + cout << endl; } diff --git a/lab4/makefile b/lab4/makefile deleted file mode 100644 index ca93933..0000000 --- a/lab4/makefile +++ /dev/null @@ -1,56 +0,0 @@ -# Compiler -CXX = g++ -CXXFLAGS = -std=c++17 -Wall -Wextra -pedantic - -# Targets -TARGETS = TagRemover Sieve date_test toString_test string_cast_test - -# Source files -SRCS_TAGREMOVER = TagRemover.cc -SRCS_SIEVE = Sieve.cc -SRCS_DATE = date.cc -SRCS_DATE_TEST = date_test.cc -SRCS_TOSTRING_TEST = toString_test.cc date.cc -SRCS_STRING_CAST_TEST = string_cast_test.cc date.cc - -# Object files -OBJS_TAGREMOVER = $(SRCS_TAGREMOVER:.cc=.o) -OBJS_SIEVE = $(SRCS_SIEVE:.cc=.o) -OBJS_DATE = $(SRCS_DATE:.cc=.o) -OBJS_DATE_TEST = $(SRCS_DATE_TEST:.cc=.o) -OBJS_TOSTRING_TEST = $(SRCS_TOSTRING_TEST:.cc=.o) -OBJS_STRING_CAST_TEST = $(SRCS_STRING_CAST_TEST:.cc=.o) - -# Default target -all: $(TARGETS) - -# Rule to build TagRemover -TagRemover: $(OBJS_TAGREMOVER) - $(CXX) $(CXXFLAGS) -o $@ $^ - -# Rule to build Sieve -Sieve: $(OBJS_SIEVE) - $(CXX) $(CXXFLAGS) -o $@ $^ - -# Rule to build date_test -date_test: $(OBJS_DATE_TEST) $(OBJS_DATE) - $(CXX) $(CXXFLAGS) -o $@ $^ - -# Rule to build toString_test -toString_test: $(OBJS_TOSTRING_TEST) - $(CXX) $(CXXFLAGS) -o $@ $^ - -# Rule to build string_cast_test -string_cast_test: $(OBJS_STRING_CAST_TEST) - $(CXX) $(CXXFLAGS) -o $@ $^ - -# Rule to compile source files into object files -%.o: %.cc - $(CXX) $(CXXFLAGS) -c $< - -# Clean up build artifacts -clean: - rm -f $(OBJS_TAGREMOVER) $(OBJS_SIEVE) $(OBJS_DATE) $(OBJS_DATE_TEST) $(OBJS_TOSTRING_TEST) $(OBJS_STRING_CAST_TEST) $(TARGETS) - -# Phony targets -.PHONY: all clean diff --git a/lab4/reflektion.txt b/lab4/reflektion.txt deleted file mode 100644 index 048257c..0000000 --- a/lab4/reflektion.txt +++ /dev/null @@ -1,61 +0,0 @@ -1. In your tests, how did you test the error handling (e.g., that a wrong string_cast actually -throws?) - -Genom att använda en ogiltig inmatning, som "abc" eller "123abc", och verifiera att std::invalid_argument kastas korrekt. - - -2. In TagRemover, why do you think the constructor takes an istream instead of just the -filename? - -Det gör klassen mer flexibel eftersom den kan arbeta med vilken ström som helst, inte bara filer. Till exempel kan den användas med std::cin eller std::stringstream. - - -3. In TagRemover, did you process the file line by line, or did you first read the entire file? -What are the pros and cons of these two approaches? - -Jag läste hela filen först eftersom det är enklare att använda regex för att bearbeta hela texten på en gång. -Fördelen är att det är mer effektivt för regex-matchning, men nackdelen är att det kräver mer minne för stora filer. - - -4. How do you read the entire contents of an std::istream into a std::string without using -a for or while loop? - -Genom att använda: -std::string content((std::istreambuf_iterator(istream)), std::istreambuf_iterator()); - - -5. In TagRemover, do you have duplicate code for translating the special characters? If so, how -would you refactor your code to avoid duplicate code? - -Ja, det finns duplicerad kod för varje specialtecken. Jag skulle använda en std::map för att lagra mönster och ersättningar och iterera genom den: -std::map replacements = { - {"<", "<"}, {">", ">"}, {" ", " "}, {"&", "&"} -}; -for (const auto& [pattern, replacement] : replacements) { - result = std::regex_replace(result, std::regex(pattern), replacement); -} - - -6. How do you check if an input or output operation on a stream (e.g., operator>> or -operator<<) has failed? - -Genom att använda std::istream::fail() eller std::ostream::fail(). - - -7. How do you know if you have reached the end of an istream? - -Genom att använda std::istream::eof(). - - -8. Does string_cast("123kalle") return the value 123 or does it throw an exception? -How do you implement each of those behaviours? - -Det kastar ett undantag eftersom std::istringstream misslyckas med att konsumera hela strängen. För att tillåta delvis inläsning skulle vi behöva anpassa funktionen. - - -9. When calling the function template toString, the template type argument is not ex- -plicitly given in the call. For string_cast, on the other hand, you have to specify -string_cast or string_cast. What is the difference? When should explicit -template arguments be given to function templates? - -toString använder <<-operatören, som automatiskt identifierar typen av objekt, medan string_cast kräver en explicit typ eftersom det behöver veta vad strängen ska konverteras till. diff --git a/lab4/string_cast.h b/lab4/string_cast.h deleted file mode 100644 index cc258be..0000000 --- a/lab4/string_cast.h +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include // För std::invalid_argument - -// Template function for string_cast -template -T string_cast(const std::string& str) { - std::istringstream iss(str); - T value; - if (!(iss >> value) || !(iss.eof())) { - throw std::invalid_argument("Invalid conversion from string: " + str); - } - return value; -} diff --git a/lab4/string_cast_test.cc b/lab4/string_cast_test.cc deleted file mode 100644 index 23a812a..0000000 --- a/lab4/string_cast_test.cc +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include "date.h" // För Date-klassen -#include "string_cast.h" // Inkludera string_cast - -int main() { - try { - // Testa string_cast med int - int i = string_cast("123"); - std::cout << "Integer: " << i << std::endl; - - // Testa string_cast med double - double d = string_cast("12.34"); - std::cout << "Double: " << d << std::endl; - - // Testa string_cast med Date - Date date = string_cast("2015-01-10"); - std::cout << "Date: " << date << std::endl; - - // Testa ogiltig konvertering - int invalid = string_cast("abc"); - std::cout << "Invalid conversion: " << invalid << std::endl; - - } catch (const std::invalid_argument& e) { - std::cout << "Error: " << e.what() << std::endl; - } - - return 0; -} diff --git a/lab4/toString.h b/lab4/toString.h deleted file mode 100644 index c4f0154..0000000 --- a/lab4/toString.h +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -// Template function to convert an object to a string -template -std::string toString(const T& obj) { - std::ostringstream oss; - oss << obj; - return oss.str(); -} diff --git a/lab4/toString_test.cc b/lab4/toString_test.cc deleted file mode 100644 index 4e9860f..0000000 --- a/lab4/toString_test.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include "date.h" // Inkludera Date-klassen från tidigare lösning -#include "toString.h" // Inkludera toString-mallen - -int main() { - // Testa med ett primitivt datatyper - double d = 1.234; - int i = 42; - std::string strDouble = toString(d); - std::string strInt = toString(i); - - std::cout << "Double as string: " << strDouble << std::endl; - std::cout << "Integer as string: " << strInt << std::endl; - - // Testa med Date-klassen - Date today(2023, 12, 11); // Skapa ett datumobjekt - std::string strDate = toString(today); - - std::cout << "Date as string: " << strDate << std::endl; - - return 0; -}