imported lab skeletons
This commit is contained in:
parent
4fc8b6c771
commit
e4df45f4a9
47 changed files with 15122 additions and 87 deletions
87
README.md
87
README.md
|
@ -2,90 +2,3 @@
|
|||
|
||||
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
17
lab1/Makefile
Normal 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
50
lab1/MakefileWithDeps
Normal 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)
|
81
lab1/buggy_programs/CMakeLists.txt
Normal file
81
lab1/buggy_programs/CMakeLists.txt
Normal 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>)
|
||||
|
40
lab1/buggy_programs/Makefile
Normal file
40
lab1/buggy_programs/Makefile
Normal 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))
|
58
lab1/buggy_programs/Makefile.sanitizers
Normal file
58
lab1/buggy_programs/Makefile.sanitizers
Normal 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))
|
||||
|
64
lab1/buggy_programs/README.txt
Normal file
64
lab1/buggy_programs/README.txt
Normal 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
|
25
lab1/buggy_programs/bounds-heap.cc
Normal file
25
lab1/buggy_programs/bounds-heap.cc
Normal 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();
|
||||
}
|
24
lab1/buggy_programs/bounds.cc
Normal file
24
lab1/buggy_programs/bounds.cc
Normal 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();
|
||||
}
|
37
lab1/buggy_programs/dangling.cc
Normal file
37
lab1/buggy_programs/dangling.cc
Normal 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();
|
||||
}
|
29
lab1/buggy_programs/leak.cc
Normal file
29
lab1/buggy_programs/leak.cc
Normal 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";
|
||||
}
|
20
lab1/buggy_programs/sum.cc
Normal file
20
lab1/buggy_programs/sum.cc
Normal 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
31
lab1/buggy_programs/ub.cc
Normal 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();
|
||||
}
|
44
lab1/cmake-example/CMakeLists.txt
Normal file
44
lab1/cmake-example/CMakeLists.txt
Normal 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
35
lab1/cmake-example/README
Normal 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" ..
|
3
lab1/cmake-example/SimpleConfig.h.in
Normal file
3
lab1/cmake-example/SimpleConfig.h.in
Normal 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@
|
25
lab1/cmake-example/main.cc
Normal file
25
lab1/cmake-example/main.cc
Normal 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);
|
||||
}
|
||||
|
||||
|
1
lab1/cmake-example/testlib/CMakeLists.txt
Normal file
1
lab1/cmake-example/testlib/CMakeLists.txt
Normal file
|
@ -0,0 +1 @@
|
|||
add_library(TestLib foo.cc bar.cc)
|
6
lab1/cmake-example/testlib/bar.cc
Normal file
6
lab1/cmake-example/testlib/bar.cc
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <iostream>
|
||||
|
||||
void bar_fun(int x)
|
||||
{
|
||||
std::cout << "[bar: " << x << "]" << "\n";
|
||||
}
|
1
lab1/cmake-example/testlib/bar.h
Normal file
1
lab1/cmake-example/testlib/bar.h
Normal file
|
@ -0,0 +1 @@
|
|||
void bar_fun(int);
|
7
lab1/cmake-example/testlib/foo.cc
Normal file
7
lab1/cmake-example/testlib/foo.cc
Normal 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";
|
||||
}
|
1
lab1/cmake-example/testlib/foo.h
Normal file
1
lab1/cmake-example/testlib/foo.h
Normal file
|
@ -0,0 +1 @@
|
|||
void foo_fun();
|
10
lab1/coding.cc
Normal file
10
lab1/coding.cc
Normal 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
6
lab1/coding.h
Normal 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
16
lab1/editor.cc
Normal 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
27
lab1/editor.h
Normal 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
25
lab1/file_io_example.cc
Normal 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
29
lab1/print_argv.cc
Normal 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
6
lab1/separate_fn.cc
Normal 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
3
lab1/separate_fn.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include <string>
|
||||
void the_function(const std::string& s);
|
||||
|
7
lab1/separate_main.cc
Normal file
7
lab1/separate_main.cc
Normal 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
56
lab1/test_coding.cc
Normal 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
22
lab1/test_editor.cc
Normal 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
22
lab2/dictionary.cc
Normal 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
15
lab2/dictionary.h
Normal 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
38
lab2/spell.cc
Normal 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
16
lab2/word.cc
Normal 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
21
lab2/word.h
Normal 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
6
lab3/User.cc
Normal 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
27
lab3/User.h
Normal 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
122
lab3/UserTable.cc
Normal 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
33
lab3/UserTable.h
Normal 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
13896
lab3/users.txt
Normal file
File diff suppressed because it is too large
Load diff
30
lab4/date.cc
Normal file
30
lab4/date.cc
Normal 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
19
lab4/date.h
Normal 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
64
lab4/date_test.cc
Normal 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
7
lab4/test.html
Normal 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: <> &
|
Loading…
Reference in a new issue