Compare commits
2 commits
daa2dfc077
...
5c0f319d0c
Author | SHA1 | Date | |
---|---|---|---|
|
5c0f319d0c | ||
|
e707a6649f |
16 changed files with 87 additions and 479 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,4 +8,3 @@ compile_commands.json
|
||||||
lab2/edit
|
lab2/edit
|
||||||
lab2/spell
|
lab2/spell
|
||||||
lab3/tabletest
|
lab3/tabletest
|
||||||
./vscode
|
|
|
@ -1,6 +1,6 @@
|
||||||
CXX = g++
|
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 = -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
|
CXXFLAGS += -g
|
||||||
|
|
||||||
SRC = $(wildcard *.cc)
|
SRC = $(wildcard *.cc)
|
||||||
HDR = $(wildcard *.h)
|
HDR = $(wildcard *.h)
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
|
|
||||||
class UserTable {
|
class UserTable {
|
||||||
public:
|
public:
|
||||||
UserTable();
|
UserTable();
|
||||||
|
@ -29,4 +28,7 @@ class UserTable {
|
||||||
|
|
||||||
friend int testFindNbr(const UserTable ut);
|
friend int testFindNbr(const UserTable ut);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// int testFindNbr(const UserTable ut);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,4 +39,8 @@ int main() {
|
||||||
User ufind2 = tbl.find("Name Surname");
|
User ufind2 = tbl.find("Name Surname");
|
||||||
assert(ufind2 != UserTable::user_not_found);
|
assert(ufind2 != UserTable::user_not_found);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
auto t = UserTable("users.txt");
|
||||||
|
int r = testFindNbr(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
59
lab4/.vscode/settings.json
vendored
59
lab4/.vscode/settings.json
vendored
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"files.associations": {
|
|
||||||
"array": "cpp",
|
|
||||||
"atomic": "cpp",
|
|
||||||
"bit": "cpp",
|
|
||||||
"*.tcc": "cpp",
|
|
||||||
"bitset": "cpp",
|
|
||||||
"cctype": "cpp",
|
|
||||||
"charconv": "cpp",
|
|
||||||
"clocale": "cpp",
|
|
||||||
"cmath": "cpp",
|
|
||||||
"compare": "cpp",
|
|
||||||
"concepts": "cpp",
|
|
||||||
"cstdarg": "cpp",
|
|
||||||
"cstddef": "cpp",
|
|
||||||
"cstdint": "cpp",
|
|
||||||
"cstdio": "cpp",
|
|
||||||
"cstdlib": "cpp",
|
|
||||||
"ctime": "cpp",
|
|
||||||
"cwchar": "cpp",
|
|
||||||
"cwctype": "cpp",
|
|
||||||
"deque": "cpp",
|
|
||||||
"string": "cpp",
|
|
||||||
"unordered_map": "cpp",
|
|
||||||
"vector": "cpp",
|
|
||||||
"exception": "cpp",
|
|
||||||
"algorithm": "cpp",
|
|
||||||
"functional": "cpp",
|
|
||||||
"iterator": "cpp",
|
|
||||||
"memory": "cpp",
|
|
||||||
"memory_resource": "cpp",
|
|
||||||
"numeric": "cpp",
|
|
||||||
"optional": "cpp",
|
|
||||||
"random": "cpp",
|
|
||||||
"regex": "cpp",
|
|
||||||
"string_view": "cpp",
|
|
||||||
"system_error": "cpp",
|
|
||||||
"tuple": "cpp",
|
|
||||||
"type_traits": "cpp",
|
|
||||||
"utility": "cpp",
|
|
||||||
"format": "cpp",
|
|
||||||
"initializer_list": "cpp",
|
|
||||||
"iomanip": "cpp",
|
|
||||||
"iosfwd": "cpp",
|
|
||||||
"iostream": "cpp",
|
|
||||||
"istream": "cpp",
|
|
||||||
"limits": "cpp",
|
|
||||||
"new": "cpp",
|
|
||||||
"numbers": "cpp",
|
|
||||||
"ostream": "cpp",
|
|
||||||
"span": "cpp",
|
|
||||||
"sstream": "cpp",
|
|
||||||
"stdexcept": "cpp",
|
|
||||||
"streambuf": "cpp",
|
|
||||||
"text_encoding": "cpp",
|
|
||||||
"typeinfo": "cpp",
|
|
||||||
"variant": "cpp"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
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<int> getPrimes() const {
|
|
||||||
std::vector<int> 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;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <regex>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
76
lab4/date.cc
76
lab4/date.cc
|
@ -1,86 +1,30 @@
|
||||||
#include <ctime> // för tid och localtime
|
#include <ctime> // time and localtime
|
||||||
#include <iomanip> // för setw och setfill
|
|
||||||
#include <sstream> // för inputhantering
|
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
|
|
||||||
int Date::daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
int Date::daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
|
||||||
// Konstruktor: dagens datum
|
|
||||||
Date::Date() {
|
Date::Date() {
|
||||||
time_t timer = time(0); // tid i sekunder sedan 1970-01-01
|
time_t timer = time(0); // time in seconds since 1970-01-01
|
||||||
tm* locTime = localtime(&timer); // lokal tid
|
tm* locTime = localtime(&timer); // broken-down time
|
||||||
year = 1900 + locTime->tm_year;
|
year = 1900 + locTime->tm_year;
|
||||||
month = 1 + locTime->tm_mon;
|
month = 1 + locTime->tm_mon;
|
||||||
day = locTime->tm_mday;
|
day = locTime->tm_mday;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Konstruktor: specifikt datum
|
Date::Date(int y, int m, int d) {}
|
||||||
Date::Date(int y, int m, int d) : year(y), month(m), day(d) {}
|
|
||||||
|
|
||||||
// Get-funktioner
|
|
||||||
int Date::getYear() const {
|
int Date::getYear() const {
|
||||||
return year;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Date::getMonth() const {
|
int Date::getMonth() const {
|
||||||
return month;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Date::getDay() const {
|
int Date::getDay() const {
|
||||||
return day;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gå till nästa dag
|
|
||||||
void Date::next() {
|
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;
|
|
||||||
}
|
|
||||||
|
|
28
lab4/date.h
28
lab4/date.h
|
@ -1,27 +1,19 @@
|
||||||
#ifndef DATE_H
|
#ifndef DATE_H
|
||||||
#define DATE_H
|
#define DATE_H
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class Date {
|
class Date {
|
||||||
public:
|
public:
|
||||||
Date(); // dagens datum
|
Date(); // today's date
|
||||||
Date(int y, int m, int d); // yyyy-mm-dd
|
Date(int y, int m, int d); // yyyy-mm-dd
|
||||||
int getYear() const; // returnerar året
|
int getYear() const; // get the year
|
||||||
int getMonth() const; // returnerar månaden
|
int getMonth() const; // get the month
|
||||||
int getDay() const; // returnerar dagen
|
int getDay() const; // get the day
|
||||||
void next(); // går till nästa dag
|
void next(); // advance to next day
|
||||||
|
|
||||||
// Overloaded operators
|
|
||||||
friend std::ostream& operator<<(std::ostream& os, const Date& date);
|
|
||||||
friend std::istream& operator>>(std::istream& is, Date& date);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int year; // året (fyra siffror)
|
int year; // the year (four digits)
|
||||||
int month; // månaden (1-12)
|
int month; // the month (1-12)
|
||||||
int day; // dagen (1-...)
|
int day; // the day (1-..)
|
||||||
static int daysPerMonth[12]; // antal dagar i varje månad
|
static int daysPerMonth[12]; // number of days in each month
|
||||||
static bool isLeapYear(int year); // kontrollera skottår
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,40 +1,64 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iomanip> // for setw and setfill
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
|
|
||||||
int main() {
|
using std::cout;
|
||||||
// Test input och output
|
using std::endl;
|
||||||
bool cont = true;
|
using std::setw;
|
||||||
while (cont) {
|
using std::setfill;
|
||||||
std::cout << "Type a date: ";
|
|
||||||
Date aDate;
|
|
||||||
std::cin >> aDate;
|
|
||||||
|
|
||||||
if (std::cin.eof()) {
|
/*
|
||||||
cont = false;
|
* Prints the date d in the format yyyy-mm-dd. You shall replace this
|
||||||
} else if (!std::cin.good()) {
|
* function with an overloaded operator<<, and add an overloaded operator>>.
|
||||||
std::cout << "Wrong input format" << std::endl;
|
*
|
||||||
std::cin.clear();
|
*/
|
||||||
std::cin.ignore(10000, '\n');
|
void print(const Date& d) {
|
||||||
} else {
|
cout << setw(4) << setfill('0') << d.getYear() << '-';
|
||||||
std::cout << "Output: " << aDate << std::endl;
|
cout << setw(2) << setfill('0') << d.getMonth() << '-';
|
||||||
}
|
cout << setw(2) << setfill('0') << d.getDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testa 'next' med dagens datum
|
int main() {
|
||||||
std::cout << "--- Today and more than a month ahead:" << std::endl;
|
// Check input and output of dates. Uncomment the following when you
|
||||||
Date d1;
|
// have added operator>> and operator<<.
|
||||||
std::cout << d1 << std::endl;
|
/*
|
||||||
for (int i = 1; i <= 35; ++i) {
|
bool cont = true;
|
||||||
d1.next();
|
while (cont) {
|
||||||
std::cout << d1 << std::endl;
|
cout << "Type a date: ";
|
||||||
}
|
Date aDate;
|
||||||
|
cin >> aDate;
|
||||||
// Testa 'next' från nyårsafton
|
if (cin.eof()) {
|
||||||
std::cout << "--- New Year's Eve and the next day:" << std::endl;
|
cont = false;
|
||||||
Date d2(2013, 12, 31);
|
} else if (!cin.good()) {
|
||||||
std::cout << d2 << std::endl;
|
cout << "Wrong input format" << endl;
|
||||||
d2.next();
|
// restore stream state and ignore the rest of the line
|
||||||
std::cout << d2 << std::endl;
|
cin.clear();
|
||||||
|
cin.ignore(10000, '\n');
|
||||||
return 0;
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -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<char>(istream)), std::istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
|
|
||||||
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<std::string, std::string> 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<int>("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<int> or string_cast<Date>. 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.
|
|
|
@ -1,14 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept> // För std::invalid_argument
|
|
||||||
|
|
||||||
// Template function for string_cast
|
|
||||||
template <typename T>
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#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<int>("123");
|
|
||||||
std::cout << "Integer: " << i << std::endl;
|
|
||||||
|
|
||||||
// Testa string_cast med double
|
|
||||||
double d = string_cast<double>("12.34");
|
|
||||||
std::cout << "Double: " << d << std::endl;
|
|
||||||
|
|
||||||
// Testa string_cast med Date
|
|
||||||
Date date = string_cast<Date>("2015-01-10");
|
|
||||||
std::cout << "Date: " << date << std::endl;
|
|
||||||
|
|
||||||
// Testa ogiltig konvertering
|
|
||||||
int invalid = string_cast<int>("abc");
|
|
||||||
std::cout << "Invalid conversion: " << invalid << std::endl;
|
|
||||||
|
|
||||||
} catch (const std::invalid_argument& e) {
|
|
||||||
std::cout << "Error: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// Template function to convert an object to a string
|
|
||||||
template <typename T>
|
|
||||||
std::string toString(const T& obj) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << obj;
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#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;
|
|
||||||
}
|
|
Loading…
Reference in a new issue