1
0

migration

This commit is contained in:
2025-04-29 22:08:00 +03:00
commit ad28507008
232 changed files with 12299 additions and 0 deletions

View File

@ -0,0 +1,5 @@
Викладач: Мельникова Р. В.
Оцінка: 87
Додатково:
Завдання на максимальний бал із віддзеркаленням рядків виконано для UTF-8 замість UTF-16.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@ -0,0 +1,692 @@
// Academic aliases {{{1
/// subject abbreviations to full names
#let subjects = (
"БД": "Бази даних",
"ОПНJ": "Основи програмування на Java",
"ОС": "Операційні системи",
"ПП": "Проектний практикум",
"СПМ": "Скриптові мови програмування",
"Ф": "Філософія",
)
/// education program abbreviations to name & number
#let edu_programs = (
"ПЗПІ": (
name: "Інженерія програмного забезпечення",
number: 121, // TODO: ПЗПІ is "F2" now
),
)
// Template formatting functions {{{1
/// numberless heading
#let nheading(title) = heading(depth: 1, numbering: none, title)
/// fill horizontal space with a box and not an empty space
#let hfill(width) = box(width: width, repeat("")) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
/// make underlined cell with filled value
#let uline(align: center, content) = underline[
#if align != left { hfill(1fr) }
#content
#if align != right { hfill(1fr) }
]
/// bold text
#let bold(content) = text(weight: "bold")[#content]
/// month name from its number
#let month_gen(month) = (
"січня",
"лютого",
"березня",
"квітня",
"травня",
"червня",
"липня",
"серпня",
"вересня",
"жовтня",
"листопада",
"грудня",
).at(month - 1)
// Helper functions {{{1
/// captioned image with label derived from path:
/// - "image.png" = @image
/// - "img/image.png" = @image
/// - "img/foo/image.png" = @foo_image
/// - "img/foo/foo_image.png" = @foo_image
/// the caption will be modified based on a conditional positional value:
/// - `none`: no change
/// - some value: "`caption` (за даними `value`)"
/// - no value: "`caption` (рисунок виконано самостійно)"
/// additional named arguments will be passed to original `image` function
#let img(path, caption, ..sink) = {
let parts = path.split(".").first().split("/")
let label_string = if parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2)) {
// ("image",), (_, "image") and (.., "img", "img_image")
parts.last()
} else {
// (.., "img", "image") = "img_image"
parts.at(-2) + "_" + parts.at(-1)
}.replace(" ", "_")
let caption = if sink.pos().len() == 0 {
caption + " (рисунок виконано самостійно)"
} else if sink.pos().first() == none {
caption
} else {
[#caption (за даними #sink.pos().first())]
}
[#figure(image(path, ..sink.named()), caption: caption) #label(label_string)]
}
// Styling {{{1
/// NOTE: may be wrong
#let ua_alpha_numbering = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а"
// general outlook {{{2
// spacing between lines
#let spacing = 0.95em
#let style(it) = {
set page(
paper: "a4",
margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm),
number-align: top + right,
numbering: (..numbers) => {
if numbers.pos().at(0) != 1 {
numbering("1", numbers.pos().at(0))
}
},
)
set text(font: ("Times New Roman", "Liberation Serif"), size: 14pt, hyphenate: false, lang: "uk")
set par(justify: true, first-line-indent: (amount: 1.25cm, all: true))
set underline(evade: false)
// set 1.5 line spacing
set block(spacing: spacing)
set par(spacing: spacing)
set par(leading: spacing)
// enums and lists {{{2
set enum(numbering: i => { ua_alpha_numbering.at(i) + ")" }, indent: 1.25cm, body-indent: 0.5cm)
show enum: it => {
set enum(indent: 0em, numbering: "1)")
it
}
set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--])
// figures {{{2
show figure: it => {
v(spacing * 2, weak: true)
it
v(spacing * 2, weak: true)
}
set figure.caption(separator: [ -- ])
show figure.where(kind: table): set figure.caption(position: top)
show figure.caption.where(kind: table): set align(left)
// figure numbering
show heading.where(level: 1): it => {
counter(math.equation).update(0)
counter(figure.where(kind: image)).update(0)
counter(figure.where(kind: table)).update(0)
counter(figure.where(kind: raw)).update(0)
it
}
set math.equation(numbering: (..num) => numbering("(1.1)", counter(heading).get().at(0), num.pos().first()))
set figure(numbering: (..num) => numbering("1.1", counter(heading).get().at(0), num.pos().first()))
// appearance of references to images and tables {{{2
set ref(
supplement: it => {
if it == none or not it.has("kind") {
it
} else if it.kind == image {
"див. рис."
} else if it.kind == table {
"див. таблицю"
} else {
it
}
},
)
show ref: it => {
let el = it.element
if el == none or not el.has("kind") {
return it
}
if el.kind != image and el.kind != table {
return it
}
[(#it)]
}
// headings {{{2
set heading(numbering: "1.1")
show heading.where(level: 1): it => {
set align(center)
set text(size: 14pt, weight: "semibold")
pagebreak(weak: true)
upper(it)
v(spacing * 2, weak: true)
}
show heading.where(level: 2): it => {
set text(size: 14pt, weight: "regular")
v(spacing * 2, weak: true)
block(width: 100%, spacing: 0em)[
#h(1.25cm)
#counter(heading).display(it.numbering)
#it.body
]
v(spacing * 2, weak: true)
}
show heading.where(level: 3): it => {
set text(size: 14pt, weight: "regular")
v(spacing * 2, weak: true)
block(width: 100%, spacing: 0em)[
#h(1.25cm)
#counter(heading).display(it.numbering)
#it.body
]
v(spacing * 2, weak: true)
}
it
}
// Coursework template {{{1
/// DSTU 3008:2015 Template for NURE
/// -> content
/// - doc (content): Content to apply the template to.
/// - title (str): Title of the document.
/// - subject_shorthand (str): Subject short name.
/// - department_gen (str): Department name in genitive form.
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
/// - mentors ((name: str, gender: str, degree: str),): List of mentors dicts.
/// - edu_program_shorthand (str): Education program shorthand.
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
/// - bib_path path: Path to the bibliography yaml file.
/// - appendices (content): Content with appendices.
#let cw-template(
doc,
title: "NONE",
subject_shorthand: "NONE",
department_gen: "Програмної інженерії",
author: (),
mentors: (),
edu_program_shorthand: "ПЗПІ",
task_list: (),
calendar_plan: (),
abstract: (),
bib_path: "bibl.yml",
appendices: (),
) = {
set document(title: title, author: author.name)
show: style
let bib-count = state("citation-counter", ())
show cite: it => {
it
bib-count.update(((..c)) => (..c, it.key))
}
show bibliography: it => {
set text(size: 0pt)
it
}
let head_mentor = mentors.at(0)
let edu_program = edu_programs.at(edu_program_shorthand)
// page 1 {{{2
[
#set align(center)
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
\
Кафедра Програмної інженерії
\
ПОЯСНЮВАЛЬНА ЗАПИСКА
ДО КУРСОВОЇ РОБОТИ
з дисципліни: "#subjects.at(subject_shorthand, default: "NONE")"
Тема роботи: "#title"
\ \ \
#columns(2, gutter: 4cm)[
#set align(left)
#if author.gender == "m" { [Виконав\ ] } else { [Виконала\ ] } ст. гр. #author.group
\
Керівник:\
#head_mentor.degree
\
Робота захищена на оцінку
\
Комісія:\
#for mentor in mentors {
[#mentor.degree\
]
}
#colbreak()
#set align(left)
\
#author.name
\ \
#head_mentor.name
\
#underline(" " * 35)
\ \
#for mentor in mentors {
[#mentor.name\
]
}
]
#v(1fr)
Харків -- #task_list.done_date.display("[year]")
#pagebreak()
]
// page 2 {{{2
{
uline[Харківський національний університет радіоелектроніки]
linebreak()
linebreak()
grid(
columns: (100pt, 1fr),
bold[
Кафедра
Дисципліна
Спеціальність
],
{
uline(align: left, department_gen)
linebreak()
uline(align: left, subjects.at(subject_shorthand))
linebreak()
uline(align: left, [#edu_program.number #edu_program.name])
},
)
grid(
columns: (1fr, 1fr, 1fr),
gutter: 0.3fr,
[#bold[Курс] #uline(2)], [#bold[Група] #uline(author.group)], [#bold[Семестр] #uline(3)],
)
linebreak()
linebreak()
linebreak()
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
linebreak()
uline(align: left)[_#author.full_name_gen _]
linebreak()
linebreak()
bold[\1. Тема роботи:]
uline[#title.]
linebreak()
{
bold[\2. Строк здачі закінченої роботи:]
uline(task_list.done_date.display("[day].[month].[year]"))
hfill(10fr)
}
linebreak()
bold[\3. Вихідні дані для роботи:]
uline(task_list.source)
linebreak()
bold[\4. Зміст розрахунково-пояснювальної записки:]
uline(task_list.content)
linebreak()
bold[\5. Перелік графічного матеріалу:]
uline(task_list.graphics)
linebreak()
{
bold[\6. Дата видачі завдання:]
uline(task_list.initial_date.display("[day].[month].[year]"))
hfill(10fr)
}
pagebreak()
}
// page 3 {{{2
{
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
set par(first-line-indent: 0pt)
linebreak()
calendar_plan.plan_table
linebreak()
grid(
columns: (5fr, 5fr),
grid(
columns: (1fr, 2fr, 1fr),
gutter: 0.2fr,
[
Студент \
Керівник \
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
],
[
#uline(align: center, []) \
#uline(align: center, []) \
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
],
[
\ \
#underline[#calendar_plan.approval_date.year()] р.
],
),
[
#author.name, \
#head_mentor.degree
#head_mentor.name.
],
)
pagebreak()
}
// page 4 {{{2
[
#align(center, bold[РЕФЕРАТ]) \
#context [
#let pages = counter(page).final().at(0)
#let images = query(figure.where(kind: image)).len()
#let tables = query(figure.where(kind: table)).len()
#let bibs = bib-count.final().dedup().len()
/* TODO: why this stopped working?
#let tables = counter(figure.where(kind: table)).final().at(0)
#let images = counter(figure.where(kind: image)).final().at(0)*/
#let counters = ()
#if pages != 0 { counters.push[#pages с.] }
#if tables != 0 { counters.push[#tables табл.] }
#if images != 0 { counters.push[#images рис.] }
#if bibs != 0 { counters.push[#bibs джерел] }
Пояснювальна записка до курсової роботи: #counters.join(", ").
]
\
#{
let keywords = abstract.keywords.map(upper)
let is_cyrillic = word => word.split("").any(char => ("А" <= char and char <= "я"))
let n = keywords.len()
for i in range(n) {
for j in range(0, n - i - 1) {
if (
(not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1)))
or (
is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1)
)
) {
(keywords.at(j), keywords.at(j + 1)) = (keywords.at(j + 1), keywords.at(j))
}
}
}
keywords.join(", ")
}
\
#abstract.text
]
// page 5 {{{2
outline(
title: [
ЗМІСТ
#v(spacing * 2, weak: true)
],
depth: 2,
indent: auto,
)
doc
// bibliography {{{2
{
heading(depth: 1, numbering: none)[Перелік джерел посилання]
bibliography(
bib_path,
style: "ieee",
full: true,
title: none,
)
let bib_data = yaml(bib_path)
let format-entry(citation) = {
if (citation.type == "Web") {
let date_array = citation.url.date.split("-")
let date = datetime(
year: int(date_array.at(0)),
month: int(date_array.at(1)),
day: int(date_array.at(2)),
)
[
#citation.title.
#citation.author.
URL: #citation.url.value (дата звернення: #date.display("[day].[month].[year]")).
]
} else if citation.type == "Book" [
#citation.author
#citation.title.
#citation.publisher,
#citation.date.
#citation.page-total c.
] else [
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
]
}
show enum.item: it => {
set par(first-line-indent: 0pt)
box(width: 1.25cm)
box(width: 1em + 0.5cm)[#it.number.]
it.body
linebreak()
}
context {
for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() {
enum.item(
i + 1,
format-entry(bib_data.at(citation)),
)
}
}
}
// appendices {{{2
{
counter(heading).update(0)
set heading(
numbering: (i, ..nums) => {
let char = upper(ua_alpha_numbering.at(i))
if nums.pos().len() == 0 { char } else {
char + "." + nums.pos().map(str).join(".")
}
},
)
show heading.where(level: 1): it => {
set align(center)
set text(size: 14pt, weight: "regular")
pagebreak(weak: true)
bold[ДОДАТОК #counter(heading).display(it.numbering)]
linebreak()
it.body
v(spacing * 2, weak: true)
}
show heading.where(level: 2): it => {
set text(size: 14pt, weight: "regular")
v(spacing * 2, weak: true)
block(width: 100%, spacing: 0em)[
#h(1.25cm)
#counter(heading).display(it.numbering)
#it.body
]
v(spacing * 2, weak: true)
}
appendices
}
}
// Laboratory work template {{{1
/// DSTU 3008:2015 Template for NURE
/// -> content
/// - doc (content): Content to apply the template to.
/// - doctype ("ЛБ" | "ПЗ"): Document type.
/// - title (str): Title of the document.
/// - subject_shorthand (str): Subject short name.
/// - department_gen (str): Department name in genitive form.
/// - worknumber (int): Number of the work, can be omitted.
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
/// - mentor (name: str, gender: str, degree: str): Mentors objects.
#let lab-pz-template(
doc,
doctype: "NONE",
title: "NONE",
subject_shorthand: "NONE",
department_gen: "Програмної інженерії",
worknumber: 1,
authors: (),
mentor: (),
) = {
set document(title: title, author: authors.at(0).name)
show: style
context counter(heading).update(worknumber - 1)
// page 1 {{{2
align(center)[
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
\ \
Кафедра #department_gen
\ \ \
Звіт \
з
#if doctype == "ЛБ" [лабораторної роботи] else [практичної роботи]
#if worknumber != none [ #worknumber]
з дисципліни: "#subjects.at(subject_shorthand, default: "UNLNOWN SUBJECT, PLEASE OPEN AN ISSUE")"
з теми: "#title"
\ \ \ \
#columns(2)[
#set align(left)
#set par(first-line-indent: 0pt)
#if authors.len() == 1 {
let author = authors.at(0)
if author.gender == "m" [Виконав:\ ] else [Виконала:\ ]
[
ст. гр. #author.group\
#author.name\
]
if author.variant != none [Варіант: #author.variant]
} else [
Виконали:\
ст. гр. #authors.at(0).group\
#authors.map(a => [ #a.name\ ])
]
#colbreak()
#set align(right)
#if mentor.gender == "m" { [Перевірив:\ ] } else { [Перевірила:\ ] }
#mentor.degree #if mentor.degree.len() >= 15 [\ ]
#mentor.name\
]
#v(1fr)
Харків -- #datetime.today().display("[year]")
]
pagebreak(weak: true)
heading(title)
doc
}
// vim:sts=2:sw=2:fdl=0:fdm=marker:cms=/*%s*/

View File

@ -0,0 +1,7 @@
CompileFlags:
Add:
- --target=x86_64-w64-mingw32
- -I/usr/x86_64-w64-mingw32/include
- -I/usr/x86_64-w64-mingw32/include/w32api
- -DUNICODE
- -D_UNICODE

View File

@ -0,0 +1,5 @@
unicode: main.cpp
x86_64-w64-mingw32-g++ -Wall -Wextra -DUNICODE -D_UNICODE -o main.exe main.cpp
ascii: main.cpp
x86_64-w64-mingw32-g++ -Wall -Wextra -DMBCS -o main.exe main.cpp

View File

@ -0,0 +1,4 @@
test
1234
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1,4 @@
test
1234
привіт

View File

@ -0,0 +1,173 @@
#include <algorithm>
#include <iostream>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
// #include <stringapiset.h>
#include <tchar.h>
// #include <wchar.h>
#include <windows.h>
void reverse_file(const char *input_filename, const char *output_filename);
void reverse_string(char *str, size_t len, int codepage);
int get_codepage(const char *filename);
int main() {
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> UNICODE
// setlocale(LC_ALL, "Ukrainian");
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 1251 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> ASCII
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
int tchar_size = sizeof(TCHAR);
printf("TCHAR size: %d\n", tchar_size);
char ua_strings[3][60] = {"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"};
printf("\nua_strings:\n");
for (int i = 0; i < 3; i++) {
printf("%d: %s\n", i + 1, ua_strings[i]);
}
printf("\nua_wstrings:\n");
wchar_t ua_wstrings[3][60] = {};
for (int i = 0; i < 3; i++) {
MultiByteToWideChar(CP_ACP, 0, ua_strings[i], -1, ua_wstrings[i], 60);
printf("- - - - - - - - - - - - - - - - - - - - - -\n");
printf("%d:\n", i + 1);
_tprintf(_T("_tprintf:\t%ls\n"), ua_wstrings[i]);
std::wcout << L"std::wcout:\t" << ua_wstrings[i] << std::endl;
MessageBoxW(NULL, ua_wstrings[i], L"MessageBox", MB_OK);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
wchar_t ua_wstrings_to_qsort[3][60] = {};
wchar_t *ua_wstrings_to_sort[3] = {};
for (int i = 0; i < 3; i++) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> qsort
wcscpy(ua_wstrings_to_qsort[i], ua_wstrings[i]);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> std::sort
ua_wstrings_to_sort[i] = (wchar_t *)malloc(sizeof(wchar_t) * 60);
wcscpy(ua_wstrings_to_sort[i], ua_wstrings[i]);
}
printf("\nqsort:\n");
qsort(ua_wstrings_to_qsort, 3, sizeof(wchar_t) * 60,
(int (*)(const void *, const void *))wcscoll);
for (int i = 0; i < 3; i++) {
_tprintf(_T("%ls\n"), ua_wstrings_to_qsort[i]);
}
printf("\nstd::sort:\n");
std::sort(ua_wstrings_to_sort, ua_wstrings_to_sort + 3,
[](const wchar_t *a, const wchar_t *b) -> bool {
return wcscoll(a, b) < 0;
});
for (int i = 0; i < 3; i++) {
_tprintf(_T("%ls\n"), ua_wstrings_to_sort[i]);
}
printf("\nua_strings_from_wstrings:\n");
char ua_strings_from_wstrings[3][60] = {};
for (int i = 0; i < 3; i++) {
WideCharToMultiByte(CP_ACP, 0, ua_wstrings[i], -1,
ua_strings_from_wstrings[i], 60, NULL, NULL);
printf("%d: %s\n", i + 1, ua_strings_from_wstrings[i]);
}
printf("\nfile convertions:\n");
reverse_file("inputA.txt", "outputA.txt");
reverse_file("inputU.txt", "outputU.txt");
return 0;
}
void reverse_string(char *str, size_t len, int codepage) {
if (str == NULL || len == 0)
return;
wchar_t *wstr = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
if (wstr == NULL) {
fprintf(stderr, "Error encountered while allocating memory\n");
return;
}
MultiByteToWideChar(codepage, 0, str, len + 1, wstr, len + 1);
size_t wlen = wcslen(wstr);
for (size_t i = 0, j = wlen - 1; i < j; i++, j--) {
wchar_t temp = wstr[i];
wstr[i] = wstr[j];
wstr[j] = temp;
}
WideCharToMultiByte(codepage, 0, wstr, len, str, len, NULL, NULL);
free(wstr);
}
void reverse_file(const char *input_filename, const char *output_filename) {
FILE *input_file = fopen(input_filename, "r");
if (input_file == NULL) {
fprintf(stderr, "Cant open input file '%s'\n", input_filename);
return;
}
FILE *output_file = fopen(output_filename, "w");
if (output_file == NULL) {
fprintf(stderr, "Cant create output file '%s'\n", output_filename);
fclose(input_file);
return;
}
int codepage = get_codepage(input_filename);
char buffer[4096];
while (fgets(buffer, sizeof(buffer), input_file) != NULL) {
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
len--;
}
reverse_string(buffer, len, codepage);
fprintf(output_file, "%s\n", buffer);
}
fclose(input_file);
fclose(output_file);
printf("Successfully reversed file '%s' to '%s'\n", input_filename,
output_filename);
};
int get_codepage(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Cant open file '%s'\n", filename);
return -1;
}
int codepage;
if (fgetc(file) == 0xEF && fgetc(file) == 0xBB && fgetc(file) == 0xBF) {
codepage = CP_UTF8;
} else {
codepage = CP_ACP;
}
fclose(file);
return codepage;
}

View File

@ -0,0 +1,4 @@
tset
4321
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1,4 @@
tset
4321
тівирп

View File

@ -0,0 +1,357 @@
#import "@local/nure:0.0.0": *
#show: lab-pz-template.with(
doctype: "ЛБ",
title: "Розробка універсальних додатків для різних типів кодувань символьної інформації",
subject_shorthand: "ОС",
department_gen: "Програмної інженерії",
authors: (
(
name: "Ситник Є. С.",
full_name_gen: "Ситника Єгора Сергійовича",
group: "ПЗПІ-23-2",
gender: "m",
variant: none,
),
),
mentor: (
name: "Мельнікова Р. В.",
gender: "f",
degree: "доц. каф. ПІ",
),
worknumber: 1,
)
#v(-spacing)
== Мета роботи
Мета даної лабораторної роботи - навчитися опрацьовувати тексти для типів кодування ASCII та UNICODE,
таким чином, щоб програма не залежала від обраного типу.
== Передмова
Я користуюсь операційною системою Arch Linux, це накладає певні обмеження, а саме:
- я не можу використовувати інтегроване середовище розробки Visual Studio, замість цього я використовую редактор NeoVim;
- я не можу використовувати компілятор MSVC, замість цього я використовую GCC та MinGW (що забезпечує кросс-компіляцію);
- код я буду запускати за допомогою шару трансляції Wine, який забезпечує сумісність з Windows.
== Хід роботи
#v(-spacing)
=== Створіть консольний застосунок для C++ програм
Створення консольного застосунку на C++ відбувається в декілька етапів:
- створення файлу "Makefile" для спрощення збірки програми;
- створення файлу "main.cpp" в якому буде знаходитись код програми.
#figure(image("img/task1/make.png"), caption: [Вміст файлу "Makefile"])
#figure(image("img/task1/main.png", width: 75%), caption: [Вміст файлу "main.cpp"])
=== Складіть оператори для програмної перевірки типу кодування, заданого за замовчуванням
Щоб дізнатись тип кодування, що задано за замовчуванням можна переглянути розмір типу "TCHAR" із заголовного файлу "tchar.h". Розмір цього типу буде дорівнювати 1 байту для ASCII та 2 байтам для UNICODE.
#figure(image("img/task2/main.png", width: 75%), caption: [Вміст файлу "main.cpp"])
#figure(image("img/task2/result.png"), caption: [Результат виконання програми])
Можемо побачити, що розмір TCHAR дорівнює 1 байту, це означає, що за замовчуванням використовується кодування ASCII.
=== Визначте тип кодування по заданих макросах в командному рядку
Оскільки під час написання команди компіляції в "Makefile" я не додав визначення макросів, які б вплинули на кодування, компілятор використовує ASCII як кодування за замовчуванням.
=== Перемикніть режим завдання символу на протилежний
Щоб задати тип кодування необхідно визначити відповідні макроси. Для UNICODE це макроси "UNICODE" (для WinAPI) та "\_UNICODE" (для стандартної бібліотеки), а для ASCII - "MBCS".
Змінимо існуючу ціль в "Makefile" щоб вона відповідала кодуванню ASCII, та додамо нову, що буде відповідати кодуванню UNICODE визначивши відповідні макроси.
#figure(image("img/task4/make.png"), caption: [Вміст файлу "Makefile"])
=== Після перемикання режиму знову перевірте тип символу за замовчуванням та командний рядок.
Перевіримо яке кодування використовує програма після проведених дій.
#figure(image("img/task5/result.png"), caption: [Результат виконання програми])
Можемо побачити, що після компіляції цілі "unicode" розмір типу "TCHAR" змінився на 2 байти, що підтверджує використання кодування UNICODE.
=== Задайте ПІБ членів своєї сім'ї в ASCII та виведіть задані значення
Щоб кириличні символи коректно друкувались в консолі необхідно виконати деякі дії, які будуть відрізнятись в залежності від кодування.
Для кодування UNICODE необхідно встановити системну локаль "Ukrainian" (або іншу, що має кириличні символи),
а для ASCII встановити кодову сторінку "CP1251".
Для встановлення системної локалі використаємо функцію "setlocale" з заголовного файлу "locale.h" який надає стандартна бібліотека,
а для встановлення кодової сторінки використаємо функції "SetConsoleOutputCP" та "SetConsoleCP" з заголовного файлу "windows.h"
який надає бібліотека WinAPI.
Також варто зазначити, що кириличні символи для ASCII відрізняються від аналогічних для UNICODE,
тому для сумісності необхідно змінити кодування файлу із UTF-8
(яке є стандартним для Unix-подібних операційних систем таких як MacOS та Linux) на CP1251.
#figure(image("img/task6/main.png"), caption: [Вміст файлу "main.cpp"])
#figure(image("img/task6/result.png"), caption: [Результат виконання програми])
=== Переведіть задані рядки в UNICODE за допомогою функції "MultiByteToWideChar"
Перевести рядок з ASCII в UNICODE можна за допомогою функції "MultiByteToWideChar" з бібліотеки WinAPI.
#figure(image("img/task7/main.png"), caption: [Код доданий до файлу "main.cpp"])
=== Виведіть отриманий масив кожним з трьох способів (функція \_tprintf, потік wcout, функція MessageBox)
#figure(image("img/task8/main.png"), caption: [Код доданий до файлу "main.cpp"])
#figure(
grid(
columns: 3,
gutter: 10pt,
align: horizon + center,
grid.cell(
colspan: 3,
image("img/task8/result.png"),
), box(image("img/task8/msg1.png")), box(image("img/task8/msg2.png")),
box(image("img/task8/msg3.png")),
),
caption: [Результат виконання програми],
)
=== Виконайте упорядкування масиву рядків, заданих в UNICODE. Для сортування використовувати універсальну стандартну функцію "qsort" та шаблонну функцію "sort"
1. Функція qsort приймає такі аргументи:
1. Вказівник на масив: Це адреса початку масиву, який потрібно відсортувати.
2. Розмір масиву: Кількість елементів у масиві, що дозволяє функції знати, скільки елементів потрібно обробити.
3. Розмір елемента масиву: Це розмір одного елемента масиву, який можна визначити, помноживши розмір типу "wchar_t" на кількість символів у рядку.
4. Вказівник на функцію порівняння: Функція, яка визначає порядок сортування. Вона повинна мати сигнатуру "int (\*)(const void\*, const void\*)". Стандартна бібліотека С має багато функцій для порівняння рядків, найпоширенішою з яких є функція "strcmp" (та її аналог "wcscmp" для "wchat_t"), однак ця функція порівнює рядки без врахування локалізації, що зіпсує результат в певних випадках. Для порівняння рядків з урахуванням локалізації можна використовувати стандартну функцію "wcscoll". Сигнатура цієї функції відрізняється від сигнатури, яку очікує "qsort", в даному випадку буде достатньо привести тип функції "wcscoll" до такого, який очікує "qsort".
2. Функція sort приймає такі аргументи:
1. Вказівник на початок масиву: Адреса першого елемента масиву, який потрібно відсортувати. Функція sort не підтримує сортування багатовимірних масивів, тому масив, який вона обробляє, повинен бути одновимірним масивом вказівників на рядки, тому перед копіюванням рядків необхідно виділити пам'ять для кожного рядка, використовуючи функцію "malloc". Зазвичай, після виділення пам'яті програміст має звільнити її, коли вона більше не потрібна. Однак, оскільки система автоматично звільняє пам'ять після завершення виконання програми, а програма для лабораторної роботи завершується дуже швидко, виклик функції "free" для звільнення виділеної пам'яті не є обов'язковим.
2. Вказівник на кінець масиву: Адреса елемента, що йде після останнього елемента масиву, що дозволяє функції визначити межі масиву.
3. Вказівник на функцію порівняння: Функція, яка визначає порядок сортування. Вона повинна мати сигнатуру "bool (\*)(wchar_t\*, wchar_t\*)". Для використання функції "wcscoll" з стандартної бібліотеки, її вихід потрібно перетворити, наприклад обгорнувши її в лямбда-функцію.
#figure(image("img/task9/strcp.png", width: 90%), caption: [Код для копіювання рядків])
#figure(image("img/task9/qsort.png", width: 90%), caption: [Код для перевірки функції "qsort"])
#figure(image("img/task9/sort.png", width: 90%), caption: [Код для перевірки функції "sort"])
#figure(image("img/task9/result.png", width: 50%), caption: [Результат виконання програми])
#let test = 2
=== Виконайте зворотне перетворення масиву з Unicode в ASCII
Перевести рядок з UNICODE в ASCII можна за допомогою функції "WideCharToMultiByte" з бібліотеки WinAPI.
#figure(image("img/task10/main.png"), caption: [Код доданий до файлу "main.cpp"])
=== Виведіть отриманий результат
#figure(image("img/task11/main.png"), caption: [Код доданий до файлу "main.cpp"])
#figure(image("img/task11/result.png", width: 80%), caption: [Результат виконання програми])
=== Задано текстовий файл. Не залежно від способу кодування символів в цьому файлі, переставити символи в кожному рядку в зворотному порядку.
#figure(image("img/task12/rfile.png"), caption: [Функція, яка створює копію файлу з розвернутими рядками])
#figure(image("img/task12/rstr.png", width: 80%), caption: [Функція, яка розвертає рядок])
#figure(image("img/task12/codepage.png", width: 80%), caption: [Функція, яка визначає кодову сторінку файлу])
#figure(image("img/task12/resultA.png"), caption: [Результат перетворення ASCII файлу])
#figure(image("img/task12/resultU.png"), caption: [Результат перетворення UNICODE файлу])
== Висновки
Під час виконання даної лабораторної роботи я навчився опрацьовувати тексти для типів кодування ASCII та UNICODE,
таким чином, щоб програма не залежала від обраного типу.
#counter(heading).update(0)
#set heading(
numbering: (i, ..nums) => {
let char = upper(ua_alpha_numbering.at(i))
if nums.pos().len() == 0 { char } else {
char + "." + nums.pos().map(str).join(".")
}
},
)
#show heading.where(level: 1): it => {
set align(center)
set text(size: 14pt, weight: "regular")
pagebreak(weak: true)
bold[ДОДАТОК #counter(heading).display(it.numbering)]
linebreak()
it.body
v(spacing * 2, weak: true)
}
= Вміст файлу "main.cpp"
```
#include <algorithm>
#include <iostream>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stringapiset.h>
#include <tchar.h>
#include <wchar.h>
#include <windows.h>
void reverse_file(const char *input_filename, const char *output_filename);
void reverse_string(char *str, size_t len, int codepage);
int get_codepage(const char *filename);
int main() {
// Зміна локалізації на українську для сумісності з UNICODE
setlocale(LC_ALL, "Ukrainian");
// Зміна кодової сторінки консолі на 1251 для сумісності з ASCII
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
int tchar_size = sizeof(TCHAR);
printf("TCHAR size: %d\n", tchar_size);
char ua_strings[3][60] = {"Ситник Сергій Олексійович",
"Ситник Єгор Сергійович",
"Ситник Ольга Володимирівна"};
printf("\nua_strings:\n");
for (int i = 0; i < 3; i++) {
printf("%d: %s\n", i + 1, ua_strings[i]);
}
printf("\nua_wstrings:\n");
wchar_t ua_wstrings[3][60] = {};
for (int i = 0; i < 3; i++) {
MultiByteToWideChar(CP_ACP, 0, ua_strings[i], -1, ua_wstrings[i], 60);
printf("- - - - - - - - - - - - - - - - - - - - - -\n");
printf("%d:\n", i + 1);
_tprintf(_T("_tprintf:\t%ls\n"), ua_wstrings[i]);
std::wcout << L"std::wcout:\t" << ua_wstrings[i] << std::endl;
// MessageBoxW(NULL, ua_wstrings[i], L"MessageBox", MB_OK);
}
// Копіювання масиву рядків для перевірки сортування
wchar_t ua_wstrings_to_qsort[3][60] = {};
wchar_t *ua_wstrings_to_sort[3] = {};
for (int i = 0; i < 3; i++) {
// Копіювання масиву для qsort
wcscpy(ua_wstrings_to_qsort[i], ua_wstrings[i]);
// Копіювання масиву для std::sort
ua_wstrings_to_sort[i] = (wchar_t *)malloc(sizeof(wchar_t) * 60);
wcscpy(ua_wstrings_to_sort[i], ua_wstrings[i]);
}
printf("\nqsort:\n");
qsort(ua_wstrings_to_qsort, 3, sizeof(wchar_t) * 60,
(int (*)(const void *, const void *))wcscoll);
for (int i = 0; i < 3; i++) {
_tprintf(_T("%ls\n"), ua_wstrings_to_qsort[i]);
}
printf("\nstd::sort:\n");
std::sort(ua_wstrings_to_sort, ua_wstrings_to_sort + 3,
[](const wchar_t *a, const wchar_t *b) -> bool {
return wcscoll(a, b) < 0;
});
for (int i = 0; i < 3; i++) {
_tprintf(_T("%ls\n"), ua_wstrings_to_sort[i]);
}
printf("\nua_strings_from_wstrings:\n");
char ua_strings_from_wstrings[3][60] = {};
for (int i = 0; i < 3; i++) {
WideCharToMultiByte(CP_ACP, 0, ua_wstrings[i], -1,
ua_strings_from_wstrings[i], 60, NULL, NULL);
printf("%d: %s\n", i + 1, ua_strings_from_wstrings[i]);
}
printf("\nfile convertions:\n");
reverse_file("inputA.txt", "outputA.txt");
reverse_file("inputU.txt", "outputU.txt");
return 0;
}
void reverse_string(char *str, size_t len, int codepage) {
if (str == NULL || len == 0)
return;
wchar_t *wstr = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
if (wstr == NULL) {
fprintf(stderr, "Error encountered while allocating memory\n");
return;
}
MultiByteToWideChar(codepage, 0, str, len + 1, wstr, len + 1);
size_t wlen = wcslen(wstr);
for (size_t i = 0, j = wlen - 1; i < j; i++, j--) {
wchar_t temp = wstr[i];
wstr[i] = wstr[j];
wstr[j] = temp;
}
WideCharToMultiByte(codepage, 0, wstr, len, str, len, NULL, NULL);
free(wstr);
}
void reverse_file(const char *input_filename, const char *output_filename) {
FILE *input_file = fopen(input_filename, "r");
if (input_file == NULL) {
fprintf(stderr, "Cant open input file '%s'\n", input_filename);
return;
}
FILE *output_file = fopen(output_filename, "w");
if (output_file == NULL) {
fprintf(stderr, "Cant create output file '%s'\n", output_filename);
fclose(input_file);
return;
}
int codepage = get_codepage(input_filename);
char buffer[4096];
while (fgets(buffer, sizeof(buffer), input_file) != NULL) {
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
len--;
}
reverse_string(buffer, len, codepage);
fprintf(output_file, "%s\n", buffer);
}
fclose(input_file);
fclose(output_file);
printf("Successfully reversed file '%s' to '%s'\n", input_filename,
output_filename);
};
int get_codepage(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Cant open file '%s'\n", filename);
return -1;
}
int codepage;
if (fgetc(file) == 0xEF && fgetc(file) == 0xBB && fgetc(file) == 0xBF) {
codepage = CP_UTF8;
} else {
codepage = CP_ACP;
}
fclose(file);
return codepage;
}
```
= Вміст файлу "Makefile"
```
unicode: main.cpp
x86_64-w64-mingw32-g++ -Wall -Wextra -DUNICODE -D_UNICODE -o main.exe main.cpp
ascii: main.cpp
x86_64-w64-mingw32-g++ -Wall -Wextra -DMBCS -o main.exe main.cpp
```