imported lab skeletons

This commit is contained in:
Sven Gestegard Robertz 2021-10-27 15:15:47 +02:00
parent 4fc8b6c771
commit e4df45f4a9
47 changed files with 15122 additions and 87 deletions

View file

@ -2,90 +2,3 @@
Code skeletons for the labs in EDAF30 Code skeletons for the labs in EDAF30
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/cs-lth-cpp/labs-edaf30.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/integrations/)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Automatically merge when pipeline succeeds](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://docs.gitlab.com/ee/user/clusters/agent/)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://gitlab.com/-/experiment/new_project_readme_content:a265b841aa7eaafd2a78fd9cbf79d8c9?https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

17
lab1/Makefile Normal file
View file

@ -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

50
lab1/MakefileWithDeps Normal file
View file

@ -0,0 +1,50 @@
# 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)

View file

@ -0,0 +1,81 @@
# An example CMakeLists.txt for the sanitizers example, showing how to
# enable sanitizers in a debug build.
# 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,
# and do a release build, e.g.,
# % mkdir build-rel
# % cd build-rel
# % cmake SRC_DIR -DCMAKE_BUILD_TYPE=Release
# % make
#
# Run the examples and see that they crash.
#
# Then create another build directory and do a debug build:
#
# % mkdir build-dbg
# % cd build-dbg
# % cmake SRC_DIR -DCMAKE_BUILD_TYPE=Debug
# % make
#
# 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
# to verify that the correct compiler flags are used, you can do
#
# % make VERBOSE=1
cmake_minimum_required (VERSION 3.5)
project (Sanitizers)
set (CMAKE_CXX_STANDARD 11)
# The three standard build types are Release, Debug, and RelWithDebInfo.
# If set here, it forces that build type.
#
# set(CMAKE_BUILD_TYPE Release)
# set build type to DEBUG
# set(CMAKE_BUILD_TYPE Debug)
# or to get an optimized build w/ debug symbols
# set(CMAKE_BUILD_TYPE RelWithDebInfo)
# add the executables
add_executable(leak leak.cc)
add_executable(bounds bounds.cc)
add_executable(bounds-heap bounds-heap.cc)
add_executable(ub ub.cc)
add_executable(dangling dangling.cc)
add_executable(sum sum.cc)
add_executable(sum_alt sum.cc)
# set compiler flag to turn off optimization (for all builds)
# add_compile_options("-O0")
# or use generator expressions to set flags in debug builds
add_compile_options($<$<CONFIG:Debug>:-O0>)
# set compiler and linker flags to enable the relevant sanitizer
target_compile_options(leak PUBLIC $<$<CONFIG:Debug>:-fsanitize=leak>)
target_link_libraries(leak $<$<CONFIG:Debug>:-fsanitize=leak>)
target_compile_options(bounds PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
target_link_libraries(bounds $<$<CONFIG:Debug>:-fsanitize=address>)
target_compile_options(bounds-heap PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
target_link_libraries(bounds-heap $<$<CONFIG:Debug>:-fsanitize=address>)
target_compile_options(ub PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
target_link_libraries(ub $<$<CONFIG:Debug>:-fsanitize=undefined>)
target_compile_options(dangling PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
target_link_libraries(dangling $<$<CONFIG:Debug>:-fsanitize=address>)
target_compile_options(sum PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
target_link_libraries(sum $<$<CONFIG:Debug>:-fsanitize=undefined>)
target_compile_options(sum_alt PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
target_link_libraries(sum_alt $<$<CONFIG:Debug>:-fsanitize=address>)

View file

@ -0,0 +1,40 @@
# 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)
# 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 = -O0 -Wall -Wextra -pedantic-errors -Wold-style-cast
CXXFLAGS += -std=c++11
CXXFLAGS += -g
LDFLAGS = -g
# CPPFLAGS += -stdlib=libc++
# CXXFLAGS += -stdlib=libc++
# LDFLAGS += -stdlib=libc++
PROGS=ub leak bounds bounds-heap dangling sum
ALL: $(PROGS)
leak: leak.cc
dangling: dangling.cc
bounds: bounds.cc
ub: ub.cc
sum: sum.cc
# Targets
# Phony targets
.PHONY: all clean test
# Standard clean
clean:
-rm $(PROGS)
-rm -r $(addsuffix .dSYM, $(PROGS))

View file

@ -0,0 +1,58 @@
# 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)
# 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 = -O0 -Wall -Wextra -pedantic-errors -Wold-style-cast
CXXFLAGS += -std=c++11
CXXFLAGS += -g
LDFLAGS = -g
# CPPFLAGS += -stdlib=libc++
# CXXFLAGS += -stdlib=libc++
# LDFLAGS += -stdlib=libc++
PROGS=ub leak bounds bounds-heap dangling sum sum-alt bounds-alt bounds-heap-alt
ALL: $(PROGS)
leak: leak.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=leak -o $@ $<
dangling: dangling.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
bounds: bounds.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
bounds-heap: bounds-heap.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
bounds-alt: bounds.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
bounds-heap-alt: bounds-heap.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
ub: ub.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
sum: sum.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
sum-alt: sum.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
# Targets
# Phony targets
.PHONY: all clean
# Standard clean
clean:
-rm $(PROGS)
-rm -r $(addsuffix .dSYM, $(PROGS))

View file

@ -0,0 +1,64 @@
This directory contains a few small examples of how the google sanitizers
can be used to find problems related to memory management and undefined behaviour.
The sanitizers are libraries that are used to instrument your programs, which is
done by compiling and linking with the option -fsanitize=<SANITIZER>.
For building this example includes two makefiles, one for building without
sanitizers (Makefile) and one for building with them (Makefile.sanitizers).
Also included is a CMakeListst.txt which uses sanitizers when doing a debug build.
Examples:
The file leak.cc contains an example of a memory leak.
The files bounds.cc, bounds-heap.cc and sum.cc contain examples of accessing
outside the bounds of an array (on the stack and on the heap).
The file dangling.cc contains an example of using a dangling pointer.
The file ub.cc contains an example of undefined behaviour.
Demonstration:
First build the programs using Makefile, and run them.
Then, first do make clean and then build them using Makefile.sanitizers
(make -f Makefile.sanitizers)
Run the programs again, and see if the errors are detected. Try to understand
the diagnostics pringed when the sanitizer detects an error.
Note that the different sanitizers may produce different error messages
for the same problem. Compare the output from sum and sum_alt (which are
built from the same source file, but with different sanitizers.)
This example also includes a CMakeLists.txt that illustrates how to enable
the sanitizers for debug builds.
Building with cmake:
With cmake, make debug and release builds and compare, typically in
separate build directories:
For the release build:
% mkdir build-rel
% cd build-rel
% cmake -DCMAKE_BUILD_TYPE=Release SRC_DIR
% make
For the debug build:
% mkdir build-rel
% cd build-rel
% cmake -DCMAKE_BUILD_TYPE=Debug SRC_DIR
% make
Both gcc and clang use the google sanitizers, but different compiler versions
may use different versions of the sanitizers. If you have installed a more recent
compiler version, you may need to tell cmake to use that.
By default, cmake will use the system's default compiler. To specify which
compiler to use, you can add (for gcc)
-DCMAKE_CXX_COMPILER=g++
-DCMAKE_C_COMPILER=gcc
or, for clang:
-DCMAKE_CXX_COMPILER=clang++
-DCMAKE_C_COMPILER=clang

View file

@ -0,0 +1,25 @@
#include <iostream>
#include <numeric>
#include <memory>
using std::cout;
void print(int* a, int size)
{
for(int i=0; i < size; ++i){
cout << a[i] << " ";
}
cout << "\n";
}
void example()
{
std::unique_ptr<int[]> xs(new int[10]);
std::iota(xs.get(), xs.get()+10, 0);
print(xs.get(), 15);
}
int main()
{
example();
}

View file

@ -0,0 +1,24 @@
#include <iostream>
#include <numeric>
using std::cout;
void print(int* a, int size)
{
for(int i=0; i < size; ++i){
cout << a[i] << " ";
}
cout << "\n";
}
void example()
{
int xs[10];
std::iota(xs, xs+10, 0);
print(xs, 15);
}
int main()
{
example();
}

View file

@ -0,0 +1,37 @@
#include <iostream>
#include <numeric>
using std::cout;
struct Foo{
Foo(int s) :p(new int[s]), sz(s) {}
~Foo() {delete[] p;}
int* begin() {return p;}
int* end() {return begin()+sz;}
const int* begin() const {return p;}
const int* end() const {return begin()+sz;}
int* p;
int sz;
};
void print(Foo f)
{
for(const auto& x : f) cout << x << " ";
endl(cout);
}
void example1()
{
Foo f(10);
std::iota(std::begin(f), std::end(f), 0);
print(f);
cout << "after first print\n";
*f.begin()=123;
cout << "printing again\n";
print(f);
cout << "done\n";
}
int main()
{
example1();
}

View file

@ -0,0 +1,29 @@
#include <iostream>
using std::cout;
struct Foo{
Foo(int s) :p{new int[s]} {}
int* p;
};
struct Bar{
Bar(int x) :f(x) {}
Foo f;
};
void example1()
{
Foo f(10);
{
cout << "entering inner block\n";
Bar b(20);
cout << "leaving inner block\n";
}
cout << "leaving example1\n";
}
int main()
{
example1();
cout << "leaving main\n";
}

View file

@ -0,0 +1,20 @@
#include <iostream>
#define N (4)
int x = 1000;
int a[]{ 1, 2, 3, 4 };
int y = 2000;
int main()
{
int sum{0};
std::cout << "welcome to the buggy sum program. the sum should be 10\n";
for (int i = 0; i <= N; i++)
sum += a[i];
std::cout << "sum = " << sum << "\n";
return 0;
}

31
lab1/buggy_programs/ub.cc Normal file
View file

@ -0,0 +1,31 @@
#include <iostream>
#include <vector>
#include <cassert>
#include <numeric>
using std::cout;
using std::endl;
std::vector<int> create_vector(int s)
{
assert(s >= 0);
std::vector<int> res(s);
}
template <typename C>
void print_seq(const C& c)
{
for(const auto& x : c) cout << x << " ";
cout << "\n";
}
void example()
{
auto v = create_vector(10);
std::iota(begin(v), end(v), 0);
print_seq(v);
}
int main()
{
example();
}

View file

@ -0,0 +1,44 @@
cmake_minimum_required (VERSION 3.5)
project (Simple)
set (CMAKE_CXX_STANDARD 11)
# set build type to DEBUG
set(CMAKE_BUILD_TYPE Debug)
# or to get an optimized build w/ debug symbols
# set(CMAKE_BUILD_TYPE RelWithDebInfo)
# add the library to the include file search path
include_directories ("${PROJECT_SOURCE_DIR}/testlib")
add_subdirectory (testlib)
# set compiler and linker flags
add_compile_options("-Og")
#add_compile_options("-fsanitize=address")
#link_libraries("-fsanitize=address")
# add the executable SimpleMain and its dependency on TestLib
add_executable(SimpleMain main.cc)
target_link_libraries (SimpleMain TestLib)
##################### Optional features below this line ############
# The version number. This is not needed but included
# to show how information can be passed from CMakeLists.txt
# to the program.
set (Simple_VERSION_MAJOR 1)
set (Simple_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code. Only needed if we want to pass some
# information or configuration from Cmake to the program
# being built.
configure_file (
"${PROJECT_SOURCE_DIR}/SimpleConfig.h.in"
"${PROJECT_BINARY_DIR}/SimpleConfig.h"
)
# add the binary tree to the search path for include files
# so that we will find SimpleConfig.h
include_directories("${PROJECT_BINARY_DIR}")

35
lab1/cmake-example/README Normal file
View file

@ -0,0 +1,35 @@
This is an example project that is built with cmake.
The project consists of
- an example library, TestLib, which is built from testlib/foo.h and .cc
- a configuration file, SimpleConfig.h which is built from SimpleConfig.h.in
- a main program, in main.cc
With cmake, you usually build the project in a directory separate from the source,
typically named build. This has the advantages that you can easily make several
separate builds simply by doing them in separate build directories. It also
means that the generated files are kept separate from the source code, so that
removing them is done by simply removing the entire build directory.
The steps to create the build files (Makefile, unless otherwise specified, but
cmake can generate project files for other build systems as well) and then
build the project are
> mkdir build
> cd build
> cmake ..
> make
To see the actual commands executed when building with the generated Makefile,
use the command
> make VERBOSE=1
Configuration of the compilation can be done by setting environment variables
which are read by cmake.
To set which compiler to use:
CC=clang CXX=clang++ cmake ..
To set compiler flags, one can use
cmake -DCMAKE_CXX_FLAGS="-Wall -Werror" ..

View file

@ -0,0 +1,3 @@
// the configured options and settings for simple
#define Simple_VERSION_MAJOR @Simple_VERSION_MAJOR@
#define Simple_VERSION_MINOR @Simple_VERSION_MINOR@

View file

@ -0,0 +1,25 @@
#include <iostream>
#include "SimpleConfig.h"
#include "foo.h"
#include "bar.h"
using std::cout;
using std::endl;
/* A small example of a project built using CMake.
* The Simple_VERSION_* variables are included
* to show how a header file with configuration macros
* can be generated from the CMakeLists.txt.
*/
int main()
{
cout << "This is version " << Simple_VERSION_MAJOR << "." <<
Simple_VERSION_MINOR << "\n";
cout << "Hello, world!\n";
foo_fun();
bar_fun(42);
}

View file

@ -0,0 +1 @@
add_library(TestLib foo.cc bar.cc)

View file

@ -0,0 +1,6 @@
#include <iostream>
void bar_fun(int x)
{
std::cout << "[bar: " << x << "]" << "\n";
}

View file

@ -0,0 +1 @@
void bar_fun(int);

View file

@ -0,0 +1,7 @@
#include <iostream>
void foo_fun()
{
auto x = 17; // use a C++11 feature to see if flags are set correctly
std::cout << "[foo: " << x << "]" << "\n";
}

View file

@ -0,0 +1 @@
void foo_fun();

10
lab1/coding.cc Normal file
View file

@ -0,0 +1,10 @@
#include<coding.h>
unsigned char encode(unsigned char c)
{
return c;
}
unsigned char decode(unsigned char c)
{
return c;
}

6
lab1/coding.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef __CODING_H
#define __CODING_H
unsigned char encode(unsigned char c);
unsigned char decode(unsigned char c);
#endif

16
lab1/editor.cc Normal file
View file

@ -0,0 +1,16 @@
#include "editor.h"
#include <string>
using std::string;
using size_type = Editor::size_type;
size_type Editor::get_size() const
{
return text.size();
}
size_type Editor::find_left_par(size_type pos) const {
return string::npos;
}

27
lab1/editor.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef EDITOR_H
#define EDITOR_H
#include <string>
class Editor {
public:
using size_type = std::string::size_type;
/* 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;
// ... functions to edit the text (insert and delete characters)
private:
std::string text;
};
#endif

25
lab1/file_io_example.cc Normal file
View file

@ -0,0 +1,25 @@
#include"coding.h"
#include<iostream>
#include <iomanip>
#include<fstream>
void print_bytes(std::string infile)
{
std::ifstream in{infile};
int c;
while((c = in.get()) != EOF ) {
std::cout << "read: " << std::setw(3) << c << " [" << char(c) << "]" << std::endl;
}
}
int main(int argc, char* argv[])
{
if(argc != 2) {
std::cout << "Usage: " << argv[0] << " filename" << std::endl;
return 1;
}
print_bytes(argv[1]);
return 0;
}

29
lab1/print_argv.cc Normal file
View file

@ -0,0 +1,29 @@
#include <string>
#include <iostream>
using std::cout;
using std::endl;
/* Example program, printing command line arguments
* It is good practice to convert the C string
* i.e., "pointer to first element of a null-terminated
* array of char" to a std::string and then use the
* safer std::string instead of directly using the C-string.
*/
void print_string(std::string str)
{
cout << "[" << str << "] ";
}
int main(int argc, char** argv)
{
cout << "argc=" << argc << endl;
for(int i=0; i != argc; ++i){
std::string arg{argv[i]}; // create a std::string for the argument
print_string(arg); // pass the std::string to a functio
}
cout << endl;
return 0;
}

6
lab1/separate_fn.cc Normal file
View file

@ -0,0 +1,6 @@
#include <iostream>
void the_function(const std::string& s)
{
std::cout << "the_function: " << s << "\n";
}

3
lab1/separate_fn.h Normal file
View file

@ -0,0 +1,3 @@
#include <string>
void the_function(const std::string& s);

7
lab1/separate_main.cc Normal file
View file

@ -0,0 +1,7 @@
#include "separate_fn.h"
int main()
{
the_function("Called from main()");
exit(0);
}

56
lab1/test_coding.cc Normal file
View file

@ -0,0 +1,56 @@
#include <iostream>
#include "coding.h"
#include <string>
#include <cassert>
std::string do_encode(std::string s)
{
for(auto& c : s) {
c = encode(c);
}
return s;
}
std::string do_decode(std::string s)
{
for(auto& c: s) {
c = decode(c);
}
return s;
}
bool test_coding()
{
std::string str = "Testing, testing... I should be the same after encoding and decoding";
std::string enc = do_encode(str);
assert(enc.size() == str.size()); // sanity check for test program
bool result = true;
for(std::string::size_type i=0; i != enc.size(); ++i){
if(enc[i] == str[i]) {
std::cout << "enc == str in position " << i << std::endl;
result = false;
}
};
std::string dec = do_decode(enc);
assert(enc.size() == dec.size()); // sanity check for test program
if(str != dec) {
std::cout << "Expected: " << str << "(" << str.size() <<
")\nActual: " << dec << "(" << dec.size() << ")" << std::endl;
result = false;
}
return result;
}
int main()
{
if(test_coding()) {
std::cout << "Test passed." << std::endl;
} else {
std::cout << "Test failed." << std::endl;
}
return 0;
}

22
lab1/test_editor.cc Normal file
View file

@ -0,0 +1,22 @@
#include "editor.h"
#include <iostream>
void test_equals(Editor::size_type x, Editor::size_type y)
{
if(x != y) {
std::cout << "Wrong result: " << x << " != " << y << std::endl;
};
}
int main() {
Editor ed("...(...(...[...]...)...)...{...}...");
std::cout << "editor.size(): " << ed.get_size() << std::endl;
test_equals( ed.find_left_par(15), 11);
test_equals( ed.find_left_par(19), 7);
test_equals( ed.find_left_par(23), 3);
test_equals( ed.find_left_par(31), 27);
test_equals( ed.find_left_par(32), std::string::npos);
std::cout << "test done." << std::endl;
}

22
lab2/dictionary.cc Normal file
View file

@ -0,0 +1,22 @@
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>
#include "word.h"
#include "dictionary.h"
using std::string;
using std::vector;
Dictionary::Dictionary() {
}
bool Dictionary::contains(const string& word) const {
return true;
}
vector<string> Dictionary::get_suggestions(const string& word) const {
vector<string> suggestions;
return suggestions;
}

15
lab2/dictionary.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include <string>
#include <vector>
class Dictionary {
public:
Dictionary();
bool contains(const std::string& word) const;
std::vector<std::string> get_suggestions(const std::string& word) const;
private:
};
#endif

38
lab2/spell.cc Normal file
View file

@ -0,0 +1,38 @@
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cctype>
#include "dictionary.h"
using std::string;
using std::vector;
using std::cin;
using std::cout;
using std::endl;
void check_word(const string& word, const Dictionary& dict)
{
if (dict.contains(word)) {
cout << "Correct." << endl;
} else {
vector<string> suggestions = dict.get_suggestions(word);
if (suggestions.empty()) {
cout << "Wrong, no suggestions." << endl;
} else {
cout << "Wrong. Suggestions:" << endl;
for (const auto& w : suggestions) {
cout << " " << w << endl;
}
}
}
}
int main() {
Dictionary dict;
string word;
while (cin >> word) {
transform(word.begin(), word.end(), word.begin(), ::tolower);
check_word(word, dict);
}
return 0;
}

16
lab2/word.cc Normal file
View file

@ -0,0 +1,16 @@
#include <string>
#include <vector>
#include "word.h"
using std::vector;
using std::string;
Word::Word(const string& w, const vector<string>& t) {}
string Word::get_word() const {
return string();
}
unsigned int Word::get_matches(const vector<string>& t) const {
return 0;
}

21
lab2/word.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef WORD_H
#define WORD_H
#include <string>
#include <vector>
class Word {
public:
/* Creates a word w with the sorted trigrams t */
Word(const std::string& w, const std::vector<std::string>& 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<std::string>& t) const;
private:
};
#endif

6
lab3/User.cc Normal file
View file

@ -0,0 +1,6 @@
#include "User.h"
std::ostream& operator<<(std::ostream& os, const User& u)
{
return os << "(" << u.getCardNbr() << ") "<< u.getName();
}

27
lab3/User.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef __USER_H
#define __USER_H
#include <iostream>
#include <string>
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:
int cardNbr;
std::string name;
};
std::ostream& operator<<(std::ostream& os, const User& u);
#endif

122
lab3/UserTable.cc Normal file
View file

@ -0,0 +1,122 @@
#include "UserTable.h"
#include <fstream>
#include <algorithm>
const User UserTable::user_not_found = User{-1,"Not Found"};
UserTable::UserTable() :users{new User[capacity]} { }
UserTable::UserTable(const std::string& fname) :UserTable{}
{
std::ifstream ufile(fname);
if(ufile.is_open()) {
while(ufile) {
int cn;
if(ufile >> cn ) {
ufile.ignore(); // skip space
char n[80];
ufile.getline(n,80);
addUser(User(cn,n));
}
}
} else {
std::cout << "Could not open " << fname << std::endl;
}
}
void UserTable::addUser(const User& u)
{
// gör tabellen större vid behov
ensureCapacity(n+1);
// 1. Hitta rätt plats
int pos{0};
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];
}
//3. stoppa in den nya användaren i luckan
users[pos] = u;
}
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) {
mid = (low + high) / 2;
//
int midnbr = users[mid].getCardNbr();
if (midnbr = c) {
found = true;
} else if (users[mid].getCardNbr() < c) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return found ? users[mid] : 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;
}
auto tmp = new User[capacity];
std::copy(users, users+n, tmp);
delete[] users;
users=tmp;
}
}
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;
}
os << "=============" << std::endl;
}
/**
* Testmetod för binärsökningen:
* går igenom alla användare och kollar att deras kortnummer kan sökas upp.
* Om något kortnummer inte kunde sökas upp returneras detta. Annars, om
* alla sökningar lyckades, returneras 0.
*/
int testFindNbr(const UserTable ut)
{
for (int i = 0; i < ut.n; i++) {
int nbr = ut.users[i].getCardNbr();
User found = ut.find(nbr);
if (found != ut.users[i]) {
return nbr;
}
}
return 0;
}

33
lab3/UserTable.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef __USERTABLE_H
#define __USERTABLE_H
#include <iostream>
#include "User.h"
class UserTable{
public:
UserTable();
UserTable(const std::string&);
~UserTable() {delete[] users;}
void addUser(const User&);
User find(int) const;
User find(std::string) const;
int getNbrUsers() const {
return n;
}
void print(std::ostream&) const;
static const User user_not_found;
private:
int capacity{1000};
void ensureCapacity(int);
int n{0};
User* users;
friend int testFindNbr(const UserTable ut);
};
#endif

13896
lab3/users.txt Normal file

File diff suppressed because it is too large Load diff

30
lab4/date.cc Normal file
View file

@ -0,0 +1,30 @@
#include <ctime> // time and localtime
#include "date.h"
int Date::daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
Date::Date() {
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;
}
Date::Date(int y, int m, int d) {}
int Date::getYear() const {
return 0;
}
int Date::getMonth() const {
return 0;
}
int Date::getDay() const {
return 0;
}
void Date::next() {
}

19
lab4/date.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef DATE_H
#define DATE_H
class Date {
public:
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; // 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

64
lab4/date_test.cc Normal file
View file

@ -0,0 +1,64 @@
#include <iostream>
#include <iomanip> // for setw and setfill
#include "date.h"
using std::cout;
using std::endl;
using std::setw;
using std::setfill;
/*
* 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;
}

7
lab4/test.html Normal file
View file

@ -0,0 +1,7 @@
This is a line without a tag
This is <tag tag> a line with one tag
And this <tag> line has two tags <...>
A line with a starting tag < ..... continues
... we're still in a tag ...
... finishes> which finished on this line <last tag>
Special chars: &lt;&gt;&nbsp;&amp;