commit 23255e9121ee5cfb8ea8ad5e4e7c8eb484fe5848 Author: krosh Date: Sun Apr 13 21:48:15 2025 +0300 init commit diff --git a/.clang-format b/.clang-format new file mode 100755 index 0000000..ae6c7ef --- /dev/null +++ b/.clang-format @@ -0,0 +1,34 @@ +LineEnding: LF +BasedOnStyle: LLVM +IndentWidth: 4 +ColumnLimit: 120 +# ColumnLimit: 80 +UseTab: Never +SortIncludes: Never +SpaceAfterCStyleCast: true +IndentCaseLabels: false +InsertBraces: true +InsertNewlineAtEOF: true +IndentGotoLabels: false +AlwaysBreakAfterReturnType: AllDefinitions +AllowShortEnumsOnASingleLine: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: true + AfterExternBlock: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfe5e57 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +run +test \ No newline at end of file diff --git a/3sem/cnts/contest1/02.c b/3sem/cnts/contest1/02.c new file mode 100755 index 0000000..a66df3b --- /dev/null +++ b/3sem/cnts/contest1/02.c @@ -0,0 +1,53 @@ +#include +#include + +enum +{ + NUM_OF_DIGITS = '9' - '0' + 1, + NUM_OF_LETTERS = 'z' - 'a' + 1, + BIT_MASK_1 = 0b111011, + BIT_MASK_2 = 0b001000, + MAX_NUM = 64, +}; + +int +main(void) +{ + int c; + + while ((c = getchar()) != EOF) { + int code = 0; + + if (c <= '9' && c >= '0') { + code = c - '0' + 1; + } else if (c <= 'z' && c >= 'a') { + code = c - 'a' + NUM_OF_DIGITS + 1; + } else if (c <= 'Z' && c >= 'A') { + code = c - 'A' + NUM_OF_DIGITS + NUM_OF_LETTERS + 1; + } + + if (code == 0) { + continue; + } + + code = code & BIT_MASK_1; + code ^= BIT_MASK_2; + + int res = 0; + if (code <= NUM_OF_DIGITS && code >= 1) { + res = code - 1 + '0'; + } else if (code <= NUM_OF_DIGITS + NUM_OF_LETTERS && code >= NUM_OF_DIGITS + 1) { + res = code + 'a' - NUM_OF_DIGITS - 1; + } else if (code <= NUM_OF_DIGITS + NUM_OF_LETTERS * 2 && code >= NUM_OF_DIGITS + NUM_OF_LETTERS + 1) { + res = code + 'A' - NUM_OF_DIGITS - NUM_OF_LETTERS - 1; + } else if (code == 0) { + res = '@'; + } else if (code == MAX_NUM - 1) { + res = '#'; + } + + putchar(res); + } + + return 0; +} diff --git a/3sem/cnts/contest1/03.c b/3sem/cnts/contest1/03.c new file mode 100755 index 0000000..6cf0265 --- /dev/null +++ b/3sem/cnts/contest1/03.c @@ -0,0 +1,80 @@ +#include +#include + +enum +{ + MAX_N = 2000 +}; + +int +is_prime(int num) +{ + if (num <= 1) { + return 0; + } + if (num <= 3) { + return 1; + } + if (num % 2 == 0 || num % 3 == 0) { + return 0; + } + for (int i = 5; i * i <= num; i += 6) { + if (num % i == 0 || num % (i + 2) == 0) { + return 0; + } + } + return 1; +} + +int +main(void) +{ + int n; + if (scanf("%d", &n) != 1) { + fprintf(stderr, "Error reading input\n"); + return 1; + } + + if (n >= MAX_N || !is_prime(n)) { + return 1; + } + + // двумерный под хранение результата. Не может быть одномерным, т.к. заполняются столбцы по порядку + int **mas = (int **) malloc(n * sizeof(mas)); + if (mas == NULL) { + return 1; + } + + for (int i = 0; i < n; i++) { + mas[i] = (int *) malloc(n * sizeof(*mas)); + + if (mas[i] == NULL) { + for (int j = 0; j < i; j++) { + free(mas[j]); + } + + free(mas); + return 1; + } + } + + for (int i = 1; i < n; i++) { + for (int a = 0; a < n; a++) { + mas[i][(a * i) % n] = a; + } + } + + for (int j = 0; j < n; j++) { + for (int i = 1; i < n; i++) { + printf("%d ", mas[i][j]); + } + printf("\n"); + } + + for (int i = 0; i < n; i++) { + free(mas[i]); + } + free(mas); + + return 0; +} diff --git a/3sem/cnts/contest1/05.c b/3sem/cnts/contest1/05.c new file mode 100755 index 0000000..bd7641b --- /dev/null +++ b/3sem/cnts/contest1/05.c @@ -0,0 +1,78 @@ +#include +#include + +void +swap(int *a, int *b) +{ + int temp = *a; + *a = *b; + *b = temp; + + return; +} + +int +next_permutation(int *arr, int n) +{ + int i = n - 2; + + while (i >= 0 && arr[i] >= arr[i + 1]) { + i--; + } + + if (i < 0) { + return 0; + } + + int j = n - 1; + + while (arr[j] <= arr[i]) { + j--; + } + + swap(&arr[i], &arr[j]); + + int pt1 = i + 1, pt2 = n - 1; + + while (pt1 < pt2) { + swap(&arr[pt1++], &arr[pt2--]); + } + + return 1; +} + +int +main() +{ + int n; + + if (scanf("%d", &n) != 1) { + fprintf(stderr, "Error reading input\n"); + return 1; + } + + if (n <= 0 || n >= 10) { + return 1; + } + + int *arr = (int *) malloc(n * sizeof(*arr)); + if (arr == NULL) { + return 1; + } + + for (int i = 0; i < n; i++) { + arr[i] = i + 1; + } + + do { + for (int i = 0; i < n; i++) { + printf("%d", arr[i]); + } + + printf("\n"); + } while (next_permutation(arr, n)); + + free(arr); + + return 0; +} diff --git a/3sem/cnts/contest1/test.c b/3sem/cnts/contest1/test.c new file mode 100755 index 0000000..b8a62a5 --- /dev/null +++ b/3sem/cnts/contest1/test.c @@ -0,0 +1,51 @@ +#include +#include +#include + +int +cmp(const void *a, const void *b) +{ + if (*(int *) a % 2 == 0) { + if (*(int *) b % 2 == 1) { + return -1; + } + if (*(int *) a > *(int *) b) { + return 1; + } + if (*(int *) a < *(int *) b) { + return -1; + } + return 0; + } + if (*(int *) b % 2 == 0) { + return 1; + } + if (*(int *) a > *(int *) b) { + return -1; + } + if (*(int *) a < *(int *) b) { + return 1; + } + return 0; +} + +void +sort_even_odd(size_t count, int *data) +{ + qsort(data, count, sizeof(int), cmp); +} + +int +main() +{ + int a[] = {4, 2, 5, 3, 1, 0, -4, -2, -68, 23, 3}; + sort_even_odd(sizeof(a) / sizeof(a[0]), a); + + for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { + printf("%d ", a[i]); + } + + printf("\n"); + + return 0; +} diff --git a/3sem/cnts/contest10/t1/ans1 b/3sem/cnts/contest10/t1/ans1 new file mode 100755 index 0000000..1977e66 --- /dev/null +++ b/3sem/cnts/contest10/t1/ans1 @@ -0,0 +1,3 @@ +1) 'a' +2) 1 +3) 7 \ No newline at end of file diff --git a/3sem/cnts/contest10/t1/cJSON.c b/3sem/cnts/contest10/t1/cJSON.c new file mode 100755 index 0000000..d503e22 --- /dev/null +++ b/3sem/cnts/contest10/t1/cJSON.c @@ -0,0 +1,1129 @@ +/* +Copyright (c) 2009 Dave Gamble + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char * +cJSON_GetErrorPtr() +{ + return ep; +} + +static int +cJSON_strcasecmp(const char *s1, const char *s2) +{ + if (!s1) { + return (s1 == s2) ? 0 : 1; + } + if (!s2) { + return 1; + } + for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) { + if (*s1 == 0) { + return 0; + } + } + return tolower(*(const unsigned char *) s1) - tolower(*(const unsigned char *) s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char * +cJSON_strdup(const char *str) +{ + size_t len; + char *copy; + + len = strlen(str) + 1; + if (!(copy = (char *) cJSON_malloc(len))) { + return 0; + } + memcpy(copy, str, len); + return copy; +} + +void +cJSON_InitHooks(cJSON_Hooks *hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc; + cJSON_free = (hooks->free_fn) ? hooks->free_fn : free; +} + +/* Internal constructor. */ +static cJSON * +cJSON_New_Item() +{ + cJSON *node = (cJSON *) cJSON_malloc(sizeof(cJSON)); + if (node) { + memset(node, 0, sizeof(cJSON)); + } + return node; +} + +/* Delete a cJSON structure. */ +void +cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) { + next = c->next; + if (!(c->type & cJSON_IsReference) && c->child) { + cJSON_Delete(c->child); + } + if (!(c->type & cJSON_IsReference) && c->valuestring) { + cJSON_free(c->valuestring); + } + cJSON_free(c); + c = next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char * +parse_number(cJSON *item, const char *num) +{ + double n = 0, sign = 1, scale = 0; + int subscale = 0, signsubscale = 1; + + /* Could use sscanf for this? */ + if (*num == '-') { + sign = -1, num++; /* Has sign? */ + } + if (*num == '0') { + num++; /* is zero */ + } + if (*num >= '1' && *num <= '9') { + do { + n = (n * 10.0) + (*num++ - '0'); + } while (*num >= '0' && *num <= '9'); /* Number? */ + } + if (*num == '.' && num[1] >= '0' && num[1] <= '9') { + num++; + do { + n = (n * 10.0) + (*num++ - '0'), scale--; + } while (*num >= '0' && *num <= '9'); + } /* Fractional part? */ + if (*num == 'e' || *num == 'E') /* Exponent? */ + { + num++; + if (*num == '+') { + num++; + } else if (*num == '-') { + signsubscale = -1, num++; /* With sign? */ + } + while (*num >= '0' && *num <= '9') { + subscale = (subscale * 10) + (*num++ - '0'); /* Number? */ + } + } + + n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble = n; + item->valueint = (int) n; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char * +print_number(cJSON *item) +{ + char *str; + double d = item->valuedouble; + if (fabs(((double) item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) { + str = (char *) cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) { + sprintf(str, "%d", item->valueint); + } + } else { + str = (char *) cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) { + if (fabs(floor(d) - d) <= DBL_EPSILON) { + sprintf(str, "%.0f", d); + } else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9) { + sprintf(str, "%e", d); + } else { + sprintf(str, "%f", d); + } + } + } + return str; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; +static const char * +parse_string(cJSON *item, const char *str) +{ + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + ep = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = (char *) cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; // check for invalid. + } + + if (uc >= 0xD800 && uc <= 0xDBFF) // UTF16 surrogate pairs. + { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; // missing second-half of surrogate. + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; // invalid second-half of surrogate. + } + uc = 0x10000 | ((uc & 0x3FF) << 10) | (uc2 & 0x3FF); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + *ptr2 = 0; + if (*ptr == '\"') { + ptr++; + } + item->valuestring = out; + item->type = cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char * +print_string_ptr(const char *str) +{ + const char *ptr; + char *ptr2, *out; + int len = 0; + unsigned char token; + + if (!str) { + return cJSON_strdup(""); + } + ptr = str; + while ((token = *ptr) && ++len) { + if (strchr("\"\\\b\f\n\r\t", token)) { + len++; + } else if (token < 32) { + len += 5; + } + ptr++; + } + + out = (char *) cJSON_malloc(len + 3); + if (!out) { + return 0; + } + + ptr2 = out; + ptr = str; + *ptr2++ = '\"'; + while (*ptr) { + if ((unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\') { + *ptr2++ = *ptr++; + } else { + *ptr2++ = '\\'; + switch (token = *ptr++) { + case '\\': + *ptr2++ = '\\'; + break; + case '\"': + *ptr2++ = '\"'; + break; + case '\b': + *ptr2++ = 'b'; + break; + case '\f': + *ptr2++ = 'f'; + break; + case '\n': + *ptr2++ = 'n'; + break; + case '\r': + *ptr2++ = 'r'; + break; + case '\t': + *ptr2++ = 't'; + break; + default: + sprintf(ptr2, "u%04x", token); + ptr2 += 5; + break; /* escape and print */ + } + } + } + *ptr2++ = '\"'; + *ptr2++ = 0; + return out; +} + +/* Invote print_string_ptr (which is useful) on an item. */ +static char * +print_string(cJSON *item) +{ + return print_string_ptr(item->valuestring); +} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item, const char *value); +static char *print_value(cJSON *item, int depth, int fmt); +static const char *parse_array(cJSON *item, const char *value); +static char *print_array(cJSON *item, int depth, int fmt); +static const char *parse_object(cJSON *item, const char *value); +static char *print_object(cJSON *item, int depth, int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char * +skip(const char *in) +{ + while (in && *in && (unsigned char) *in <= 32) { + in++; + } + return in; +} + +/* Parse an object - create a new root, and populate. */ +cJSON * +cJSON_Parse(const char *value) +{ + cJSON *c = cJSON_New_Item(); + ep = 0; + if (!c) { + return 0; /* memory fail */ + } + + if (!parse_value(c, skip(value))) { + cJSON_Delete(c); + return 0; + } + return c; +} + +/* Render a cJSON item/entity/structure to text. */ +char * +cJSON_Print(cJSON *item) +{ + return print_value(item, 0, 1); +} + +char * +cJSON_PrintUnformatted(cJSON *item) +{ + return print_value(item, 0, 0); +} + +/* Parser core - when encountering text, process appropriately. */ +static const char * +parse_value(cJSON *item, const char *value) +{ + if (!value) { + return 0; /* Fail on null. */ + } + if (!strncmp(value, "null", 4)) { + item->type = cJSON_NULL; + return value + 4; + } + if (!strncmp(value, "false", 5)) { + item->type = cJSON_False; + return value + 5; + } + if (!strncmp(value, "true", 4)) { + item->type = cJSON_True; + item->valueint = 1; + return value + 4; + } + if (*value == '\"') { + return parse_string(item, value); + } + if (*value == '-' || (*value >= '0' && *value <= '9')) { + return parse_number(item, value); + } + if (*value == '[') { + return parse_array(item, value); + } + if (*value == '{') { + return parse_object(item, value); + } + + ep = value; + return 0; /* failure. */ +} + +/* Render a value to text. */ +static char * +print_value(cJSON *item, int depth, int fmt) +{ + char *out = 0; + if (!item) { + return 0; + } + switch ((item->type) & 255) { + case cJSON_NULL: + out = cJSON_strdup("null"); + break; + case cJSON_False: + out = cJSON_strdup("false"); + break; + case cJSON_True: + out = cJSON_strdup("true"); + break; + case cJSON_Number: + out = print_number(item); + break; + case cJSON_String: + out = print_string(item); + break; + case cJSON_Array: + out = print_array(item, depth, fmt); + break; + case cJSON_Object: + out = print_object(item, depth, fmt); + break; + } + return out; +} + +/* Build an array from input text. */ +static const char * +parse_array(cJSON *item, const char *value) +{ + cJSON *child; + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ + + item->type = cJSON_Array; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->child = child = cJSON_New_Item(); + if (!item->child) { + return 0; /* memory fail */ + } + value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */ + if (!value) { + return 0; + } + + while (*value == ',') { + cJSON *new_item; + if (!(new_item = cJSON_New_Item())) { + return 0; /* memory fail */ + } + child->next = new_item; + child = new_item; + value = skip(parse_value(child, skip(value + 1))); + if (!value) { + return 0; /* memory fail */ + } + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + ep = value; + return 0; /* malformed. */ +} + +/* Render an array to text */ +static char * +print_array(cJSON *item, int depth, int fmt) +{ + char **entries; + char *out = 0, *ptr, *ret; + int len = 5; + cJSON *child = item->child; + int numentries = 0, i = 0, fail = 0; + + /* How many entries in the array? */ + while (child) { + numentries++, child = child->next; + } + /* Allocate an array to hold the values for each */ + entries = (char **) cJSON_malloc(numentries * sizeof(char *)); + if (!entries) { + return 0; + } + memset(entries, 0, numentries * sizeof(char *)); + /* Retrieve all the results: */ + child = item->child; + while (child && !fail) { + ret = print_value(child, depth + 1, fmt); + entries[i++] = ret; + if (ret) { + len += strlen(ret) + 2 + (fmt ? 1 : 0); + } else { + fail = 1; + } + child = child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) { + out = (char *) cJSON_malloc(len); + } + /* If that fails, we fail. */ + if (!out) { + fail = 1; + } + + /* Handle failure. */ + if (fail) { + for (i = 0; i < numentries; i++) { + if (entries[i]) { + cJSON_free(entries[i]); + } + } + cJSON_free(entries); + return 0; + } + + /* Compose the output array. */ + *out = '['; + ptr = out + 1; + *ptr = 0; + for (i = 0; i < numentries; i++) { + strcpy(ptr, entries[i]); + ptr += strlen(entries[i]); + if (i != numentries - 1) { + *ptr++ = ','; + if (fmt) { + *ptr++ = ' '; + } + *ptr = 0; + } + cJSON_free(entries[i]); + } + cJSON_free(entries); + *ptr++ = ']'; + *ptr++ = 0; + return out; +} + +/* Build an object from the text. */ +static const char * +parse_object(cJSON *item, const char *value) +{ + cJSON *child; + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ + + item->type = cJSON_Object; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->child = child = cJSON_New_Item(); + if (!item->child) { + return 0; + } + value = skip(parse_string(child, skip(value))); + if (!value) { + return 0; + } + child->string = child->valuestring; + child->valuestring = 0; + if (*value != ':') { + ep = value; + return 0; + } /* fail! */ + value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return 0; + } + + while (*value == ',') { + cJSON *new_item; + if (!(new_item = cJSON_New_Item())) { + return 0; /* memory fail */ + } + child->next = new_item; + new_item->prev = child; + child = new_item; + value = skip(parse_string(child, skip(value + 1))); + if (!value) { + return 0; + } + child->string = child->valuestring; + child->valuestring = 0; + if (*value != ':') { + ep = value; + return 0; + } /* fail! */ + value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return 0; + } + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + ep = value; + return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char * +print_object(cJSON *item, int depth, int fmt) +{ + char **entries = 0, **names = 0; + char *out = 0, *ptr, *ret, *str; + int len = 7, i = 0, j; + cJSON *child = item->child; + int numentries = 0, fail = 0; + /* Count the number of entries. */ + while (child) { + numentries++, child = child->next; + } + /* Allocate space for the names and the objects */ + entries = (char **) cJSON_malloc(numentries * sizeof(char *)); + if (!entries) { + return 0; + } + names = (char **) cJSON_malloc(numentries * sizeof(char *)); + if (!names) { + cJSON_free(entries); + return 0; + } + memset(entries, 0, sizeof(char *) * numentries); + memset(names, 0, sizeof(char *) * numentries); + + /* Collect all the results into our arrays: */ + child = item->child; + depth++; + if (fmt) { + len += depth; + } + while (child) { + names[i] = str = print_string_ptr(child->string); + entries[i++] = ret = print_value(child, depth, fmt); + if (str && ret) { + len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0); + } else { + fail = 1; + } + child = child->next; + } + + /* Try to allocate the output string */ + if (!fail) { + out = (char *) cJSON_malloc(len); + } + if (!out) { + fail = 1; + } + + /* Handle failure */ + if (fail) { + for (i = 0; i < numentries; i++) { + if (names[i]) { + cJSON_free(names[i]); + } + if (entries[i]) { + cJSON_free(entries[i]); + } + } + cJSON_free(names); + cJSON_free(entries); + return 0; + } + + /* Compose the output: */ + *out = '{'; + ptr = out + 1; + if (fmt) { + *ptr++ = '\n'; + } + *ptr = 0; + for (i = 0; i < numentries; i++) { + if (fmt) { + for (j = 0; j < depth; j++) { + *ptr++ = '\t'; + } + } + strcpy(ptr, names[i]); + ptr += strlen(names[i]); + *ptr++ = ':'; + if (fmt) { + *ptr++ = '\t'; + } + strcpy(ptr, entries[i]); + ptr += strlen(entries[i]); + if (i != numentries - 1) { + *ptr++ = ','; + } + if (fmt) { + *ptr++ = '\n'; + } + *ptr = 0; + cJSON_free(names[i]); + cJSON_free(entries[i]); + } + + cJSON_free(names); + cJSON_free(entries); + if (fmt) { + for (i = 0; i < depth - 1; i++) { + *ptr++ = '\t'; + } + } + *ptr++ = '}'; + *ptr++ = 0; + return out; +} + +/* Get Array size/item / object item. */ +int +cJSON_GetArraySize(cJSON *array) +{ + cJSON *c = array->child; + int i = 0; + while (c) { + i++, c = c->next; + } + return i; +} + +cJSON * +cJSON_GetArrayItem(cJSON *array, int item) +{ + cJSON *c = array->child; + while (c && item > 0) { + item--, c = c->next; + } + return c; +} + +cJSON * +cJSON_GetObjectItem(cJSON *object, const char *string) +{ + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string, string)) { + c = c->next; + } + return c; +} + +/* Utility for array list handling. */ +static void +suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON * +create_reference(cJSON *item) +{ + cJSON *ref = cJSON_New_Item(); + if (!ref) { + return 0; + } + memcpy(ref, item, sizeof(cJSON)); + ref->string = 0; + ref->type |= cJSON_IsReference; + ref->next = ref->prev = 0; + return ref; +} + +/* Add item to array/object. */ +void +cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + cJSON *c = array->child; + if (!item) { + return; + } + if (!c) { + array->child = item; + } else { + while (c && c->next) { + c = c->next; + } + suffix_object(c, item); + } +} + +void +cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + if (!item) { + return; + } + if (item->string) { + cJSON_free(item->string); + } + item->string = cJSON_strdup(string); + cJSON_AddItemToArray(object, item); +} + +void +cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + cJSON_AddItemToArray(array, create_reference(item)); +} + +void +cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + cJSON_AddItemToObject(object, string, create_reference(item)); +} + +cJSON * +cJSON_DetachItemFromArray(cJSON *array, int which) +{ + cJSON *c = array->child; + while (c && which > 0) { + c = c->next, which--; + } + if (!c) { + return 0; + } + if (c->prev) { + c->prev->next = c->next; + } + if (c->next) { + c->next->prev = c->prev; + } + if (c == array->child) { + array->child = c->next; + } + c->prev = c->next = 0; + return c; +} + +void +cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +cJSON * +cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + int i = 0; + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string, string)) { + i++, c = c->next; + } + if (c) { + return cJSON_DetachItemFromArray(object, i); + } + return 0; +} + +void +cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +/* Replace array/object items with new ones. */ +void +cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *c = array->child; + while (c && which > 0) { + c = c->next, which--; + } + if (!c) { + return; + } + newitem->next = c->next; + newitem->prev = c->prev; + if (newitem->next) { + newitem->next->prev = newitem; + } + if (c == array->child) { + array->child = newitem; + } else { + newitem->prev->next = newitem; + } + c->next = c->prev = 0; + cJSON_Delete(c); +} + +void +cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + int i = 0; + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string, string)) { + i++, c = c->next; + } + if (c) { + newitem->string = cJSON_strdup(string); + cJSON_ReplaceItemInArray(object, i, newitem); + } +} + +/* Create basic types: */ +cJSON * +cJSON_CreateNull() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_NULL; + } + return item; +} + +cJSON * +cJSON_CreateTrue() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_True; + } + return item; +} + +cJSON * +cJSON_CreateFalse() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_False; + } + return item; +} + +cJSON * +cJSON_CreateBool(int b) +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = b ? cJSON_True : cJSON_False; + } + return item; +} + +cJSON * +cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_Number; + item->valuedouble = num; + item->valueint = (int) num; + } + return item; +} + +cJSON * +cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_String; + item->valuestring = cJSON_strdup(string); + } + return item; +} + +cJSON * +cJSON_CreateArray() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_Array; + } + return item; +} + +cJSON * +cJSON_CreateObject() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_Object; + } + return item; +} + +/* Create Arrays: */ +cJSON * +cJSON_CreateIntArray(int *numbers, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} + +cJSON * +cJSON_CreateFloatArray(float *numbers, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} + +cJSON * +cJSON_CreateDoubleArray(double *numbers, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} + +cJSON * +cJSON_CreateStringArray(const char **strings, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateString(strings[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} diff --git a/3sem/cnts/contest10/t1/cJSON.h b/3sem/cnts/contest10/t1/cJSON.h new file mode 100755 index 0000000..cc1beb9 --- /dev/null +++ b/3sem/cnts/contest10/t1/cJSON.h @@ -0,0 +1,133 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +// #ifdef __cplusplus +// extern "C" +//{ +// #endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON +{ + struct cJSON *next, *prev; /* next/prev allow you to walk array/object chains. Alternatively, use + GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the + array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char + *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks *hooks); + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array, int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back + * to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(); +extern cJSON *cJSON_CreateTrue(); +extern cJSON *cJSON_CreateFalse(); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(); +extern cJSON *cJSON_CreateObject(); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(int *numbers, int count); +extern cJSON *cJSON_CreateFloatArray(float *numbers, int count); +extern cJSON *cJSON_CreateDoubleArray(double *numbers, int count); +extern cJSON *cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new + * cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which); +extern void cJSON_DeleteItemFromArray(cJSON *array, int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); + +#define cJSON_AddNullToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddNumberToObject(object, name, n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object, name, s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +// #ifdef __cplusplus +// } +// #endif + +#endif diff --git a/3sem/cnts/contest10/t1/gdb command b/3sem/cnts/contest10/t1/gdb command new file mode 100755 index 0000000..f55846a --- /dev/null +++ b/3sem/cnts/contest10/t1/gdb command @@ -0,0 +1,12 @@ +break parse_value +commands + silent + set $count = $count + 1 + if $count == 2 + print item->type + continue + end + continue +end +set $count = 0 +run \ No newline at end of file diff --git a/3sem/cnts/contest10/t1/gdb command copy b/3sem/cnts/contest10/t1/gdb command copy new file mode 100755 index 0000000..8b56f43 --- /dev/null +++ b/3sem/cnts/contest10/t1/gdb command copy @@ -0,0 +1,12 @@ +break parse_string if $pc == *parse_string + +commands + silent + set $count = $count + 1 + if $count == 4 + print len + continue + end + continue +end +set $count = 0 +run \ No newline at end of file diff --git a/3sem/cnts/contest10/t1/gdb-1-task.tar b/3sem/cnts/contest10/t1/gdb-1-task.tar new file mode 100755 index 0000000..e3cb44b Binary files /dev/null and b/3sem/cnts/contest10/t1/gdb-1-task.tar differ diff --git a/3sem/cnts/contest10/t1/gdb-1-task.tarZone.Identifier b/3sem/cnts/contest10/t1/gdb-1-task.tarZone.Identifier new file mode 100755 index 0000000..cca3dca --- /dev/null +++ b/3sem/cnts/contest10/t1/gdb-1-task.tarZone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://unicorn.ejudge.ru/ej/client/view-problem-submit/Sa889e21564f40a8b?prob_id=80 +HostUrl=https://unicorn.ejudge.ru/ej/client?SID=a889e21564f40a8b&prob_id=80&action=194&file=gdb-1-task.tar diff --git a/3sem/cnts/contest10/t1/task1 b/3sem/cnts/contest10/t1/task1 new file mode 100755 index 0000000..e7a47b3 Binary files /dev/null and b/3sem/cnts/contest10/t1/task1 differ diff --git a/3sem/cnts/contest10/t1/task1.c b/3sem/cnts/contest10/t1/task1.c new file mode 100755 index 0000000..120a9af --- /dev/null +++ b/3sem/cnts/contest10/t1/task1.c @@ -0,0 +1,27 @@ +#include +#include +#include "cJSON.h" + +void +task1() +{ + cJSON *item; + char *json = "{" + "\"a\" : true, " + "\"b\" : { " + "\"c\":\"stro\\\"ka\"" + "}" + "}"; + + item = cJSON_Parse(json); + + cJSON_Delete(item); +} + +int +main(int argc, char **argv) +{ + task1(); + + return 0; +} diff --git a/3sem/cnts/contest10/t2/cJSON.c b/3sem/cnts/contest10/t2/cJSON.c new file mode 100755 index 0000000..58d37fb --- /dev/null +++ b/3sem/cnts/contest10/t2/cJSON.c @@ -0,0 +1,1126 @@ +/* +Copyright (c) 2009 Dave Gamble + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char * +cJSON_GetErrorPtr() +{ + return ep; +} + +static int +cJSON_strcasecmp(const char *s1, const char *s2) +{ + if (!s1) { + return (s1 == s2) ? 0 : 1; + } + if (!s2) { + return 1; + } + for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) { + if (*s1 == 0) { + return 0; + } + } + return tolower(*(const unsigned char *) s1) - tolower(*(const unsigned char *) s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char * +cJSON_strdup(const char *str) +{ + size_t len; + char *copy; + + len = strlen(str) + 1; + if (!(copy = (char *) cJSON_malloc(len))) { + return 0; + } + memcpy(copy, str, len); + return copy; +} + +void +cJSON_InitHooks(cJSON_Hooks *hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc; + cJSON_free = (hooks->free_fn) ? hooks->free_fn : free; +} + +/* Internal constructor. */ +static cJSON * +cJSON_New_Item() +{ + cJSON *node = (cJSON *) cJSON_malloc(sizeof(cJSON)); + if (node) { + memset(node, 0, sizeof(cJSON)); + } + return node; +} + +/* Delete a cJSON structure. */ +void +cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) { + next = c->next; + if (!(c->type & cJSON_IsReference) && c->child) { + cJSON_Delete(c->child); + } + if (!(c->type & cJSON_IsReference) && c->valuestring) { + cJSON_free(c->valuestring); + } + cJSON_free(c); + c = next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char * +parse_number(cJSON *item, const char *num) +{ + double n = 0, sign = 1, scale = 0; + int subscale = 0, signsubscale = 1; + + /* Could use sscanf for this? */ + if (*num == '-') { + sign = -1, num++; /* Has sign? */ + } + if (*num == '0') { + num++; /* is zero */ + } + if (*num >= '1' && *num <= '9') { + do { + n = (n * 10.0) + (*num++ - '0'); + } while (*num >= '0' && *num <= '9'); /* Number? */ + } + if (*num == '.' && num[1] >= '0' && num[1] <= '9') { + num++; + do { + n = (n * 10.0) + (*num++ - '0'), scale--; + } while (*num >= '0' && *num <= '9'); + } /* Fractional part? */ + if (*num == 'e' || *num == 'E') /* Exponent? */ + { + num++; + if (*num == '+') { + num++; + } else if (*num == '-') { + signsubscale = -1, num++; /* With sign? */ + } + while (*num >= '0' && *num <= '9') { + subscale = (subscale * 10) + (*num++ - '0'); /* Number? */ + } + } + + n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble = n; + item->valueint = (int) round(n); + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char * +print_number(cJSON *item) +{ + char *str; + double d = item->valuedouble; + if (fabs(((double) item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) { + str = (char *) cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + sprintf(str, "%d", item->valueint); + } else { + str = (char *) cJSON_malloc(64); /* This is a nice tradeoff. */ + if (fabs(floor(d) - d) <= DBL_EPSILON) { + sprintf(str, "%.0f", d); + } else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9) { + sprintf(str, "%e", d); + } else { + sprintf(str, "%f", d); + } + } + + return str; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; +static const char * +parse_string(cJSON *item, const char *str) +{ + const char *ptr = str + 1; + char *ptr2; + char *out; + int len = 0; + unsigned uc, uc2; + if (*str != '\"') { + ep = str; + return 0; + } /* not a string! */ + + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { + ptr++; /* Skip escaped quotes. */ + } + } + + out = (char *) cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */ + if (!out) { + return 0; + } + + ptr = str + 1; + ptr2 = out; + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { + *ptr2++ = *ptr++; + } else { + ptr++; + switch (*ptr) { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case 'u': /* transcode utf16 to utf8. */ + sscanf(ptr + 1, "%4x", &uc); + ptr += 4; /* get the unicode char. */ + + if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) { + break; // check for invalid. + } + + if (uc >= 0xD800 && uc <= 0xDBFF) // UTF16 surrogate pairs. + { + if (ptr[1] != '\\' || ptr[2] != 'u') { + break; // missing second-half of surrogate. + } + sscanf(ptr + 3, "%4x", &uc2); + ptr += 6; + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { + break; // invalid second-half of surrogate. + } + uc = 0x10000 | ((uc & 0x3FF) << 10) | (uc2 & 0x3FF); + } + + len = 4; + if (uc < 0x80) { + len = 1; + } else if (uc < 0x800) { + len = 2; + } else if (uc < 0x10000) { + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 3: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 2: + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 1: + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + default: + *ptr2++ = *ptr; + break; + } + ptr++; + } + } + *ptr2 = 0; + if (*ptr == '\"') { + ptr++; + } + item->valuestring = out; + item->type = cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char * +print_string_ptr(const char *str) +{ + const char *ptr; + char *ptr2, *out; + int len = 0; + unsigned char token; + + if (!str) { + return cJSON_strdup(""); + } + ptr = str; + while ((token = *ptr) && ++len) { + if (strchr("\"\\\b\f\n\r\t", token)) { + len++; + } else if (token < 32) { + len += 5; + } + ptr++; + } + + out = (char *) cJSON_malloc(len + 3); + if (!out) { + return 0; + } + + ptr2 = out; + ptr = str; + *ptr2++ = '\"'; + while (*ptr) { + if ((unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\') { + *ptr2++ = *ptr++; + } else { + *ptr2++ = '\\'; + switch (token = *ptr++) { + case '\\': + *ptr2++ = '\\'; + break; + case '\"': + *ptr2++ = '\"'; + break; + case '\b': + *ptr2++ = 'b'; + break; + case '\f': + *ptr2++ = 'f'; + break; + case '\n': + *ptr2++ = 'n'; + break; + case '\r': + *ptr2++ = 'r'; + break; + case '\t': + *ptr2++ = 't'; + break; + default: + sprintf(ptr2, "u%04x", token); + ptr2 += 5; + break; /* escape and print */ + } + } + } + *ptr2++ = '\"'; + *ptr2++ = 0; + return out; +} + +/* Invote print_string_ptr (which is useful) on an item. */ +static char * +print_string(cJSON *item) +{ + return print_string_ptr(item->valuestring); +} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item, const char *value); +static char *print_value(cJSON *item, int depth, int fmt); +static const char *parse_array(cJSON *item, const char *value); +static char *print_array(cJSON *item, int depth, int fmt); +static const char *parse_object(cJSON *item, const char *value); +static char *print_object(cJSON *item, int depth, int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char * +skip(const char *in) +{ + while (in && *in && (unsigned char) *in <= 32) { + in++; + } + return in; +} + +/* Parse an object - create a new root, and populate. */ +cJSON * +cJSON_Parse(const char *value) +{ + cJSON *c = cJSON_New_Item(); + ep = 0; + if (!c) { + return 0; /* memory fail */ + } + + if (!parse_value(c, skip(value))) { + cJSON_Delete(c); + return 0; + } + return c; +} + +/* Render a cJSON item/entity/structure to text. */ +char * +cJSON_Print(cJSON *item) +{ + return print_value(item, 0, 1); +} + +char * +cJSON_PrintUnformatted(cJSON *item) +{ + return print_value(item, 0, 0); +} + +/* Parser core - when encountering text, process appropriately. */ +static const char * +parse_value(cJSON *item, const char *value) +{ + if (!value) { + return 0; /* Fail on null. */ + } + if (!strncmp(value, "null", 4)) { + item->type = cJSON_NULL; + return value + 4; + } + if (!strncmp(value, "false", 5)) { + item->type = cJSON_False; + return value + 5; + } + if (!strncmp(value, "true", 4)) { + item->type = cJSON_True; + item->valueint = 1; + return value + 4; + } + if (*value == '\"') { + return parse_string(item, value); + } + if (*value == '-' || (*value >= '0' && *value <= '9')) { + return parse_number(item, value); + } + if (*value == '[') { + return parse_array(item, value); + } + if (*value == '{') { + return parse_object(item, value); + } + + ep = value; + return 0; /* failure. */ +} + +/* Render a value to text. */ +static char * +print_value(cJSON *item, int depth, int fmt) +{ + char *out = 0; + if (!item) { + return 0; + } + switch ((item->type) & 255) { + case cJSON_NULL: + out = cJSON_strdup("null"); + break; + case cJSON_False: + out = cJSON_strdup("false"); + break; + case cJSON_True: + out = cJSON_strdup("true"); + break; + case cJSON_Number: + out = print_number(item); + break; + case cJSON_String: + out = print_string(item); + break; + case cJSON_Array: + out = print_array(item, depth, fmt); + break; + case cJSON_Object: + out = print_object(item, depth, fmt); + break; + } + return out; +} + +/* Build an array from input text. */ +static const char * +parse_array(cJSON *item, const char *value) +{ + cJSON *child; + if (*value != '[') { + ep = value; + return 0; + } /* not an array! */ + + item->type = cJSON_Array; + value = skip(value + 1); + if (*value == ']') { + return value + 1; /* empty array. */ + } + + item->child = child = cJSON_New_Item(); + if (!item->child) { + return 0; /* memory fail */ + } + value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */ + if (!value) { + return 0; + } + + while (*value == ',') { + cJSON *new_item; + if (!(new_item = cJSON_New_Item())) { + return 0; /* memory fail */ + } + child->next = new_item; + child = new_item; + value = skip(parse_value(child, skip(value + 1))); + if (!value) { + return 0; /* memory fail */ + } + } + + if (*value == ']') { + return value + 1; /* end of array */ + } + ep = value; + return 0; /* malformed. */ +} + +/* Render an array to text */ +static char * +print_array(cJSON *item, int depth, int fmt) +{ + char **entries; + char *out = 0, *ptr, *ret; + int len = 5; + cJSON *child = item->child; + int numentries = 0, i = 0, fail = 0; + + /* How many entries in the array? */ + while (child) { + numentries++, child = child->next; + } + /* Allocate an array to hold the values for each */ + entries = (char **) cJSON_malloc(numentries * sizeof(char *)); + if (!entries) { + return 0; + } + memset(entries, 0, numentries * sizeof(char *)); + /* Retrieve all the results: */ + child = item->child; + while (child && !fail) { + ret = print_value(child, depth + 1, fmt); + entries[i++] = ret; + if (ret) { + len += strlen(ret) + 2 + (fmt ? 1 : 0); + } else { + fail = 1; + } + child = child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) { + out = (char *) cJSON_malloc(len); + } + /* If that fails, we fail. */ + if (!out) { + fail = 1; + } + + /* Handle failure. */ + if (fail) { + for (i = 0; i < numentries; i++) { + if (entries[i]) { + cJSON_free(entries[i]); + } + } + cJSON_free(entries); + return 0; + } + + /* Compose the output array. */ + *out = '['; + ptr = out + 1; + *ptr = 0; + for (i = 0; i < numentries; i++) { + strcpy(ptr, entries[i]); + ptr += strlen(entries[i]); + if (i != numentries - 1) { + *ptr++ = ','; + if (fmt) { + *ptr++ = ' '; + } + *ptr = 0; + } + cJSON_free(entries[i]); + } + cJSON_free(entries); + *ptr++ = ']'; + *ptr++ = 0; + return out; +} + +/* Build an object from the text. */ +static const char * +parse_object(cJSON *item, const char *value) +{ + cJSON *child; + if (*value != '{') { + ep = value; + return 0; + } /* not an object! */ + + item->type = cJSON_Object; + value = skip(value + 1); + if (*value == '}') { + return value + 1; /* empty array. */ + } + + item->child = child = cJSON_New_Item(); + if (!item->child) { + return 0; + } + value = skip(parse_string(child, skip(value))); + if (!value) { + return 0; + } + child->string = child->valuestring; + child->valuestring = 0; + if (*value != ':') { + ep = value; + return 0; + } /* fail! */ + value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return 0; + } + + while (*value == ',') { + cJSON *new_item; + if (!(new_item = cJSON_New_Item())) { + return 0; /* memory fail */ + } + child->next = new_item; + new_item->prev = child; + child = new_item; + value = skip(parse_string(child, skip(value + 1))); + if (!value) { + return 0; + } + child->string = child->valuestring; + child->valuestring = 0; + if (*value != ':') { + ep = value; + return 0; + } /* fail! */ + value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) { + return 0; + } + } + + if (*value == '}') { + return value + 1; /* end of array */ + } + ep = value; + return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char * +print_object(cJSON *item, int depth, int fmt) +{ + char **entries = 0, **names = 0; + char *out = 0, *ptr, *ret, *str; + int len = 7, i = 0, j; + cJSON *child = item->child; + int numentries = 0, fail = 0; + /* Count the number of entries. */ + while (child) { + numentries++, child = child->next; + } + /* Allocate space for the names and the objects */ + entries = (char **) cJSON_malloc(numentries * sizeof(char *)); + if (!entries) { + return 0; + } + names = (char **) cJSON_malloc(numentries * sizeof(char *)); + if (!names) { + cJSON_free(entries); + return 0; + } + memset(entries, 0, sizeof(char *) * numentries); + memset(names, 0, sizeof(char *) * numentries); + + /* Collect all the results into our arrays: */ + child = item->child; + depth++; + if (fmt) { + len += depth; + } + while (child) { + names[i] = str = print_string_ptr(child->string); + entries[i++] = ret = print_value(child, depth, fmt); + if (str && ret) { + len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0); + } else { + fail = 1; + } + child = child->next; + } + + /* Try to allocate the output string */ + if (!fail) { + out = (char *) cJSON_malloc(len); + } + if (!out) { + fail = 1; + } + + /* Handle failure */ + if (fail) { + for (i = 0; i < numentries; i++) { + if (names[i]) { + cJSON_free(names[i]); + } + if (entries[i]) { + cJSON_free(entries[i]); + } + } + cJSON_free(names); + cJSON_free(entries); + return 0; + } + + /* Compose the output: */ + *out = '{'; + ptr = out + 1; + if (fmt) { + *ptr++ = '\n'; + } + *ptr = 0; + for (i = 0; i < numentries; i++) { + if (fmt) { + for (j = 0; j < depth; j++) { + *ptr++ = '\t'; + } + } + strcpy(ptr, names[i]); + ptr += strlen(names[i]); + *ptr++ = ':'; + if (fmt) { + *ptr++ = '\t'; + } + strcpy(ptr, entries[i]); + ptr += strlen(entries[i]); + if (i != numentries - 1) { + *ptr++ = ','; + } + if (fmt) { + *ptr++ = '\n'; + } + *ptr = 0; + cJSON_free(names[i]); + cJSON_free(entries[i]); + } + + cJSON_free(names); + cJSON_free(entries); + if (fmt) { + for (i = 0; i < depth - 1; i++) { + *ptr++ = '\t'; + } + } + *ptr++ = '}'; + *ptr++ = 0; + return out; +} + +/* Get Array size/item / object item. */ +int +cJSON_GetArraySize(cJSON *array) +{ + cJSON *c = array->child; + int i = 0; + while (c) { + i++, c = c->next; + } + return i; +} + +cJSON * +cJSON_GetArrayItem(cJSON *array, int item) +{ + cJSON *c = array->child; + while (c && item > 0) { + item--, c = c->next; + } + return c; +} + +cJSON * +cJSON_GetObjectItem(cJSON *object, const char *string) +{ + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string, string)) { + c = c->next; + } + return c; +} + +/* Utility for array list handling. */ +static void +suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON * +create_reference(cJSON *item) +{ + cJSON *ref = cJSON_New_Item(); + if (!ref) { + return 0; + } + memcpy(ref, item, sizeof(cJSON)); + ref->string = 0; + ref->type |= cJSON_IsReference; + ref->next = ref->prev = 0; + return ref; +} + +/* Add item to array/object. */ +void +cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + cJSON *c = array->child; + if (!item) { + return; + } + if (!c) { + array->child = item; + } else { + while (c && c->next) { + c = c->next; + } + suffix_object(c, item); + } +} + +void +cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + if (!item) { + return; + } + if (item->string) { + cJSON_free(item->string); + } + item->string = cJSON_strdup(string); + cJSON_AddItemToArray(object, item); +} + +void +cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + cJSON_AddItemToArray(array, create_reference(item)); +} + +void +cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + cJSON_AddItemToObject(object, string, create_reference(item)); +} + +cJSON * +cJSON_DetachItemFromArray(cJSON *array, int which) +{ + cJSON *c = array->child; + while (c && which > 0) { + c = c->next, which--; + } + if (!c) { + return 0; + } + if (c->prev) { + c->prev->next = c->next; + } + if (c->next) { + c->next->prev = c->prev; + } + if (c == array->child) { + array->child = c->next; + } + c->prev = c->next = 0; + return c; +} + +void +cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +cJSON * +cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + int i = 0; + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string, string)) { + i++, c = c->next; + } + if (c) { + return cJSON_DetachItemFromArray(object, i); + } + return 0; +} + +void +cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +/* Replace array/object items with new ones. */ +void +cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *c = array->child; + while (c && which > 0) { + c = c->next, which--; + } + if (!c) { + return; + } + newitem->next = c->next; + newitem->prev = c->prev; + if (newitem->next) { + newitem->next->prev = newitem; + } + if (c == array->child) { + array->child = newitem; + } else { + newitem->prev->next = newitem; + } + c->next = c->prev = 0; + cJSON_Delete(c); +} + +void +cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + int i = 0; + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string, string)) { + i++, c = c->next; + } + if (c) { + newitem->string = cJSON_strdup(string); + cJSON_ReplaceItemInArray(object, i, newitem); + } +} + +/* Create basic types: */ +cJSON * +cJSON_CreateNull() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_NULL; + } + return item; +} + +cJSON * +cJSON_CreateTrue() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_True; + } + return item; +} + +cJSON * +cJSON_CreateFalse() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_False; + } + return item; +} + +cJSON * +cJSON_CreateBool(int b) +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = b ? cJSON_True : cJSON_False; + } + return item; +} + +cJSON * +cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_Number; + item->valuedouble = num; + item->valueint = (int) num; + } + return item; +} + +cJSON * +cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_String; + item->valuestring = cJSON_strdup(string); + } + return item; +} + +cJSON * +cJSON_CreateArray() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_Array; + } + return item; +} + +cJSON * +cJSON_CreateObject() +{ + cJSON *item = cJSON_New_Item(); + if (item) { + item->type = cJSON_Object; + } + return item; +} + +/* Create Arrays: */ +cJSON * +cJSON_CreateIntArray(int *numbers, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} + +cJSON * +cJSON_CreateFloatArray(float *numbers, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} + +cJSON * +cJSON_CreateDoubleArray(double *numbers, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} + +cJSON * +cJSON_CreateStringArray(const char **strings, int count) +{ + int i; + cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); + for (i = 0; a && i < count; i++) { + n = cJSON_CreateString(strings[i]); + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + return a; +} diff --git a/3sem/cnts/contest10/t2/cJSON.h b/3sem/cnts/contest10/t2/cJSON.h new file mode 100755 index 0000000..cc1beb9 --- /dev/null +++ b/3sem/cnts/contest10/t2/cJSON.h @@ -0,0 +1,133 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +// #ifdef __cplusplus +// extern "C" +//{ +// #endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON +{ + struct cJSON *next, *prev; /* next/prev allow you to walk array/object chains. Alternatively, use + GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the + array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char + *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks *hooks); + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array, int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back + * to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(); +extern cJSON *cJSON_CreateTrue(); +extern cJSON *cJSON_CreateFalse(); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(); +extern cJSON *cJSON_CreateObject(); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(int *numbers, int count); +extern cJSON *cJSON_CreateFloatArray(float *numbers, int count); +extern cJSON *cJSON_CreateDoubleArray(double *numbers, int count); +extern cJSON *cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new + * cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which); +extern void cJSON_DeleteItemFromArray(cJSON *array, int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); + +#define cJSON_AddNullToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddNumberToObject(object, name, n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object, name, s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +// #ifdef __cplusplus +// } +// #endif + +#endif diff --git a/3sem/cnts/contest10/t2/gdb-2-task.tar b/3sem/cnts/contest10/t2/gdb-2-task.tar new file mode 100755 index 0000000..b40f33a Binary files /dev/null and b/3sem/cnts/contest10/t2/gdb-2-task.tar differ diff --git a/3sem/cnts/contest10/t2/gdb-2-task.tarZone.Identifier b/3sem/cnts/contest10/t2/gdb-2-task.tarZone.Identifier new file mode 100755 index 0000000..ffebe14 --- /dev/null +++ b/3sem/cnts/contest10/t2/gdb-2-task.tarZone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://unicorn.ejudge.ru/ej/client/view-problem-submit/Sa889e21564f40a8b?prob_id=81 +HostUrl=https://unicorn.ejudge.ru/ej/client?SID=a889e21564f40a8b&prob_id=81&action=194&file=gdb-2-task.tar diff --git a/3sem/cnts/contest10/t2/task2 b/3sem/cnts/contest10/t2/task2 new file mode 100755 index 0000000..e1c7dfa Binary files /dev/null and b/3sem/cnts/contest10/t2/task2 differ diff --git a/3sem/cnts/contest10/t2/task2.c b/3sem/cnts/contest10/t2/task2.c new file mode 100755 index 0000000..1d25864 --- /dev/null +++ b/3sem/cnts/contest10/t2/task2.c @@ -0,0 +1,30 @@ +#include +#include +#include "cJSON.h" + +void +task2() +{ + cJSON *item; + char *text; + + item = cJSON_Parse("{" + "\"name\" : \"Ivanov\"," + "\"age\" : 25" + "}"); + + text = cJSON_PrintUnformatted(item); + + puts(text); + + free(text); + cJSON_Delete(item); +} + +int +main(int argc, char **argv) +{ + task2(); + + return 0; +} diff --git a/3sem/cnts/contest10/t2/task2.out b/3sem/cnts/contest10/t2/task2.out new file mode 100755 index 0000000..3d22ae7 --- /dev/null +++ b/3sem/cnts/contest10/t2/task2.out @@ -0,0 +1 @@ +{"name":"Ivanov","age":25} \ No newline at end of file diff --git a/3sem/cnts/contest11/01.c b/3sem/cnts/contest11/01.c new file mode 100755 index 0000000..23dfc53 --- /dev/null +++ b/3sem/cnts/contest11/01.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +int +proc(void) +{ + int pid = fork(); + if (!pid) { + write(1, "1\n", 2); + } + return pid; +} + +int +main(int argc, char **argv) +{ + proc(), proc(), proc(); + + return 0; +} diff --git a/3sem/cnts/contest11/01_ans.c b/3sem/cnts/contest11/01_ans.c new file mode 100755 index 0000000..8a95483 --- /dev/null +++ b/3sem/cnts/contest11/01_ans.c @@ -0,0 +1 @@ +proc(), proc(), proc() diff --git a/3sem/cnts/contest11/02.c b/3sem/cnts/contest11/02.c new file mode 100755 index 0000000..1b04694 --- /dev/null +++ b/3sem/cnts/contest11/02.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +int +main() +{ + pid_t pid; + pid = fork(); + if (!pid) { + pid = fork(); + if (!pid) { + printf("3 "); + + return 0; + } else if (pid == -1) { + return 1; + } else { + wait(NULL); + printf("2 "); + } + return 0; + } else if (pid == -1) { + return 1; + } else { + wait(NULL); + printf("1"); + } + + printf("\n"); + + return 0; +} diff --git a/3sem/cnts/contest11/03.c b/3sem/cnts/contest11/03.c new file mode 100755 index 0000000..f785b7e --- /dev/null +++ b/3sem/cnts/contest11/03.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +enum +{ + MAX_LEN = 8 +}; + +void +process_line(int line_number) +{ + char buffer[MAX_LEN + 1] = {0}; + read(0, buffer, sizeof(buffer) - 1); + long long number = strtoll(buffer, NULL, 10); + long long square = number * number; + printf("%d %lld\n", line_number, square); + + return; +} + +int +main() +{ + pid_t pid; + + for (int i = 0; i < 3; i++) { + if ((pid = fork()) == 0) { + process_line(i + 1); + exit(0); + } + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/cnts/contest11/04 b/3sem/cnts/contest11/04 new file mode 100755 index 0000000..e440e5c --- /dev/null +++ b/3sem/cnts/contest11/04 @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/3sem/cnts/contest11/04.c b/3sem/cnts/contest11/04.c new file mode 100755 index 0000000..4e4577a --- /dev/null +++ b/3sem/cnts/contest11/04.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +int +main() +{ + pid_t pid; + + int n; + if (scanf("%d", &n) != 1) { + return 1; + } + + for (int i = 1; i <= n; i++) { + printf("%d", i); + fflush(stdout); + + if (i == n) { + printf("\n"); + return 0; + } else { + printf(" "); + fflush(stdout); + } + pid = fork(); + + if (!pid) { + continue; + } else { + wait(NULL); + return 0; + } + } + + return 0; +} diff --git a/3sem/cnts/contest11/05 b/3sem/cnts/contest11/05 new file mode 100755 index 0000000..703ca85 --- /dev/null +++ b/3sem/cnts/contest11/05 @@ -0,0 +1 @@ +1 2 3 \ No newline at end of file diff --git a/3sem/cnts/contest11/05.c b/3sem/cnts/contest11/05.c new file mode 100755 index 0000000..1f4aad0 --- /dev/null +++ b/3sem/cnts/contest11/05.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +int +main() +{ + + pid_t pid; + int n; + + pid = fork(); + if (!pid) { + for (;;) { + if (scanf("%d", &n) != 1) { + return 0; + } + + pid = fork(); + if (!pid) { + continue; + } + int status; + wait(&status); + if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status)) { + return -1; + } + + printf("%d\n", n); + return 0; + } + } else { + int status; + wait(&status); + if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status)) { + printf("-1\n"); + } + } + + return 0; +} diff --git a/3sem/cnts/contest12/01.c b/3sem/cnts/contest12/01.c new file mode 100755 index 0000000..77b7168 --- /dev/null +++ b/3sem/cnts/contest12/01.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include + +// CMD < FILE1 >> FILE2 2> FILE3 + +enum +{ + EXIT_ERROR = 42, + ACCESS_FILE = 0660 +}; + +int +main(int argc, char **argv) +{ + char *cmd = argv[1]; + char *file1 = argv[2]; + char *file2 = argv[3]; + char *file3 = argv[4]; + pid_t pid = fork(); + if (pid == 0) { + + int fd1 = open(file1, O_RDONLY); + int fd2 = open(file2, O_WRONLY | O_APPEND | O_CREAT, ACCESS_FILE); + int fd3 = open(file3, O_WRONLY | O_TRUNC | O_CREAT, ACCESS_FILE); + + if (fd1 == -1 || fd2 == -1 || fd3 == -1) { + _exit(EXIT_ERROR); + } + + if (dup2(fd1, 0) == -1 || dup2(fd2, 1) == -1 || dup2(fd3, 2) == -1) { + _exit(EXIT_ERROR); + } + + execlp(cmd, cmd, NULL); + _exit(EXIT_ERROR); + } else { + int status; + wait(&status); + printf("%d\n", status); + } + + return 0; +} diff --git a/3sem/cnts/contest12/02-ai.c b/3sem/cnts/contest12/02-ai.c new file mode 100755 index 0000000..b5e6ded --- /dev/null +++ b/3sem/cnts/contest12/02-ai.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +int +run_command(char *cmd) +{ + pid_t pid = fork(); + if (pid == -1) { + perror("fork"); + exit(1); + } else if (pid == 0) { + execlp(cmd, cmd, (char *) NULL); + perror("execlp"); + exit(1); + } else { + int status; + waitpid(pid, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return 1; + } else { + return 0; + } + } +} + +int +main(int argc, char *argv[]) +{ + int cmd1_success = run_command(argv[1]); + int cmd2_success = 0; + + if (!cmd1_success) { + cmd2_success = run_command(argv[2]); + } + + if (cmd1_success || cmd2_success) { + if (run_command(argv[3])) { + exit(0); + } else { + exit(1); + } + } + + exit(1); +} diff --git a/3sem/cnts/contest12/02.c b/3sem/cnts/contest12/02.c new file mode 100755 index 0000000..4d5c56c --- /dev/null +++ b/3sem/cnts/contest12/02.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include + +int +run(const char *cmd) +{ + pid_t pid = fork(); + if (pid == -1) { + exit(1); + } else if (pid == 0) { + execlp(cmd, cmd, NULL); + _exit(1); + } + int status; + waitpid(pid, &status, 0); + + return WIFEXITED(status) && !WEXITSTATUS(status); +} // 1 - при успехе + +int +main(int argc, char **argv) +{ + if (argc != 4) { + return 1; + } + + char *cmd1 = argv[1]; + char *cmd2 = argv[2]; + char *cmd3 = argv[3]; + + return !((run(cmd1) || run(cmd2)) && run(cmd3)); +} diff --git a/3sem/cnts/contest12/03.c b/3sem/cnts/contest12/03.c new file mode 100755 index 0000000..8211e4b --- /dev/null +++ b/3sem/cnts/contest12/03.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +int +check(void) +{ + int succes = 0; + int status; + + while (wait(&status) != -1) { + if (WIFEXITED(status) && !WEXITSTATUS(status)) { + succes++; + } + } + + return succes; +} + +void +run(char *cmd) +{ + pid_t pid = fork(); + if (pid == -1) { + exit(1); + } else if (pid == 0) { + execlp(cmd, cmd, NULL); + _exit(1); + } + + return; +} // 1 - при успехе + +int +main(int argc, char **argv) +{ + int succes = 0; + + for (int i = 1; i < argc; ++i) { + if (argv[i][0] == 's') { + succes += check(); + run(argv[i] + 1); + succes += check(); + } else if (argv[i][0] == 'p') { + run(argv[i] + 1); + } else { + fprintf(stderr, "Error in arguments\n"); + exit(1); + } + } + + succes += check(); + + printf("%d\n", succes); + + return 0; +} diff --git a/3sem/cnts/contest12/04.c b/3sem/cnts/contest12/04.c new file mode 100755 index 0000000..f5399f5 --- /dev/null +++ b/3sem/cnts/contest12/04.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + if (argc < 2) { + return 1; + } + + char script_template[] = "#!/usr/bin/env python3\n" + "import os\n" + "print("; + char script_end[] = ")\n" + "os.remove(__file__)\n"; + + size_t script_size = strlen(script_template) + strlen(script_end) + 1; + for (int i = 1; i < argc; i++) { + script_size += strlen(argv[i]) + 1; + } + + char *script_content; + if (!(script_content = malloc(script_size))) { + return 1; + } + + strcpy(script_content, script_template); + + for (int i = 1; i < argc; i++) { + strcat(script_content, argv[i]); + + if (i < argc - 1) { + strcat(script_content, "*"); + } + } + + strcat(script_content, script_end); + + char *tmpdir = getenv("XDG_RUNTIME_DIR"); + if (!tmpdir) { + tmpdir = getenv("TMPDIR"); + + if (!tmpdir) { + tmpdir = "/tmp"; + } + } + + char script_path[PATH_MAX]; + int r = snprintf(script_path, sizeof(script_path), "%s/%d", tmpdir, (int) (getpid() * time(NULL) % 1000000)); + if (r < 0 || r > PATH_MAX) { + exit(1); + } + + int fd = open(script_path, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd == -1) { + free(script_content); + return 1; + } + + FILE *script_file = fdopen(fd, "w"); + if (!script_file) { + close(fd); + unlink(script_path); + free(script_content); + return 1; + } + + fprintf(script_file, "%s", script_content); + fclose(script_file); + free(script_content); + + if (chmod(script_path, 0700) == -1) { + unlink(script_path); + return 1; + } + + execl(script_path, script_path, (char *) NULL); + unlink(script_path); + + return 1; +} diff --git a/3sem/cnts/contest13/01.c b/3sem/cnts/contest13/01.c new file mode 100755 index 0000000..a2c9ced --- /dev/null +++ b/3sem/cnts/contest13/01.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include + +enum +{ + YEAR_OFFSET = 1900 +}; + +int +main(void) +{ + + int fd[2]; + pipe(fd); + time_t delta; + struct tm *dt; + + pid_t pid = fork(); + if (pid == 0) { + pid = fork(); + + if (pid == 0) { + pid = fork(); + + if (pid == 0) { + close(fd[0]); + + delta = time(NULL); + if (write(fd[1], &delta, sizeof(delta)) == -1 || write(fd[1], &delta, sizeof(delta)) == -1 || + write(fd[1], &delta, sizeof(delta)) == -1) { + _exit(1); + } + } else if (pid == -1) { + _exit(1); + } + close(fd[1]); + wait(NULL); + if (read(fd[0], &delta, sizeof(delta)) == -1) { + _exit(1); + } + dt = localtime(&delta); + printf("D:%02d\n", dt->tm_mday); + fflush(stdout); + _exit(0); + } else if (pid == -1) { + _exit(1); + } + + close(fd[1]); + wait(NULL); + if (read(fd[0], &delta, sizeof(delta)) == -1) { + _exit(1); + } + dt = localtime(&delta); + printf("M:%02d\n", dt->tm_mon + 1); + fflush(stdout); + _exit(0); + } else if (pid == -1) { + _exit(1); + } + close(fd[1]); + wait(NULL); + if (read(fd[0], &delta, sizeof(delta)) == -1) { + _exit(1); + } + dt = localtime(&delta); + printf("Y:%04d\n", dt->tm_year + YEAR_OFFSET); + fflush(stdout); + + return 0; +} diff --git a/3sem/cnts/contest13/03.c b/3sem/cnts/contest13/03.c new file mode 100755 index 0000000..aba530b --- /dev/null +++ b/3sem/cnts/contest13/03.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include + +enum +{ + ACCESS_FILE = 0660 +}; + +int +main(int argc, char **argv) +{ + char *cmd1 = argv[1]; + char *cmd2 = argv[2]; + char *cmd3 = argv[3]; + char *file1 = argv[4]; + char *file2 = argv[5]; + + int fd1 = open(file1, O_RDONLY); + int fd2 = open(file2, O_WRONLY | O_APPEND | O_CREAT, ACCESS_FILE); + if (fd1 == -1 || fd2 == -1) { + exit(1); + } + + int fd[2]; + if (pipe(fd) == -1) { + return 1; + } + + pid_t pid = fork(); + if (pid == 0) { + close(fd[0]); + if (dup2(fd[1], 1) == -1) { + _exit(1); + } + + pid = fork(); + if (pid == 0) { + + if (dup2(fd1, 0) == -1) { + _exit(1); + } + + execlp(cmd1, cmd1, NULL); + _exit(1); + } else if (pid == -1) { + exit(1); + } + + int status; + wait(&status); + + if (WIFEXITED(status) && !WEXITSTATUS(status)) { + pid = fork(); + if (pid == 0) { + execlp(cmd2, cmd2, NULL); + _exit(1); + } else if (pid == -1) { + exit(1); + } + + wait(NULL); + } + + _exit(0); + } else if (pid == -1) { + exit(1); + } + + close(fd[1]); + pid = fork(); + if (pid == 0) { + + if (dup2(fd2, 1) == -1 || dup2(fd[0], 0)) { + _exit(1); + } + + execlp(cmd3, cmd3, NULL); + _exit(1); + } else if (pid == -1) { + exit(1); + } + + close(fd[0]); + + while (wait(NULL) != -1) + ; + return 0; +} diff --git a/3sem/cnts/contest13/04.c b/3sem/cnts/contest13/04.c new file mode 100755 index 0000000..6abfc4c --- /dev/null +++ b/3sem/cnts/contest13/04.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +void +ex(void) +{ + // разослать SIGKILL + // а некому. + + exit(1); +} + +void +swap(int *a, int *b) +{ + int tmp = *a; + *a = *b; + *b = tmp; + + return; +} + +int +main(int argc, char **argv) +{ + int fd1[2]; + int fd2[2]; + if (close(2) == -1 || pipe(fd1) == -1 || pipe(fd2)) { + ex(); + } + + for (int i = 1; i < argc; ++i) { + pid_t pid = fork(); + if (pid == 0) { + + if (i != 1 && i != argc - 1) { + if (dup2(fd2[1], 1) == -1 || dup2(fd1[0], 0) == -1) { + ex(); + } + } else if (i == 1) { + if (dup2(fd2[1], 1) == -1) { + ex(); + } + } else { + if (dup2(fd1[0], 0) == -1) { + ex(); + } + } + + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd2[1]); + + execlp(argv[i], argv[i], NULL); + _exit(1); + } else if (pid == -1) { + ex(); + } + + swap(&fd1[0], &fd2[0]); + swap(&fd1[1], &fd2[1]); + wait(NULL); + } + + return 0; +} diff --git a/3sem/cnts/contest13/05.c b/3sem/cnts/contest13/05.c new file mode 100755 index 0000000..75ca331 --- /dev/null +++ b/3sem/cnts/contest13/05.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int n = (int) strtoll(argv[1], NULL, 10); + + int fd1[2]; + int fd2[2]; + pipe(fd1); + pipe(fd2); + + int tmp = 1; + write(fd2[1], &tmp, sizeof(tmp)); + + if (!fork()) { + int i = 0; + close(fd1[0]); + close(fd2[1]); + + while (i < n) { + if (read(fd2[0], &i, sizeof(i)) == -1) { + return 0; + } + if (i >= n) { + write(fd1[1], &i, sizeof(i)); + break; + } + printf("%d %d\n", 1, i); + fflush(stdout); + i++; + write(fd1[1], &i, sizeof(i)); + } + + return 0; + } else if (!fork()) { + int i = 0; + close(fd2[0]); + close(fd1[1]); + + while (i < n) { + if (read(fd1[0], &i, sizeof(i)) == -1) { + return 0; + } + if (i >= n) { + write(fd1[1], &i, sizeof(i)); + break; + } + printf("%d %d\n", 2, i); + fflush(stdout); + i++; + write(fd2[1], &i, sizeof(i)); + } + + return 0; + } + + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd2[1]); + + while (wait(NULL) != -1) + ; + + printf("Done\n"); + + return 0; +} diff --git a/3sem/cnts/contest14/01.c b/3sem/cnts/contest14/01.c new file mode 100755 index 0000000..2937105 --- /dev/null +++ b/3sem/cnts/contest14/01.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +volatile int cnt = 0; + +void +f(int n) +{ + if (cnt == 5) { + exit(0); + } + + printf("%d\n", cnt++); + fflush(stdout); + + return; +} + +int +main(int argc, char *argv[]) +{ + sigaction(SIGHUP, &(struct sigaction){.sa_handler = f, .sa_flags = SA_RESTART}, NULL); + + printf("%d\n", getpid()); + fflush(stdout); + + for (;;) { + pause(); + } + + return 0; +} diff --git a/3sem/cnts/contest14/02.c b/3sem/cnts/contest14/02.c new file mode 100755 index 0000000..521988e --- /dev/null +++ b/3sem/cnts/contest14/02.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +volatile int mode = 0; // 0 - + 1 - * + +void +mul(int n) +{ + mode = 1; + + return; +} + +void +sum(int n) +{ + mode = 0; + + return; +} + +int +main(int argc, char *argv[]) +{ + sigaction(SIGINT, &(struct sigaction){.sa_handler = sum, .sa_flags = SA_RESTART}, NULL); + sigaction(SIGQUIT, &(struct sigaction){.sa_handler = mul, .sa_flags = SA_RESTART}, NULL); + + printf("%d\n", getpid()); + fflush(stdout); + + int res = 0, tmp; + + while (scanf("%d", &tmp) == 1) { + if (mode == 0) { + __builtin_add_overflow(res, tmp, &res); + } else { + __builtin_mul_overflow(res, tmp, &res); + } + printf("%d\n", res); + fflush(stdout); + } + + // for (;;) { + // pause(); + // } + + return 0; +} diff --git a/3sem/cnts/contest14/04.c b/3sem/cnts/contest14/04.c new file mode 100755 index 0000000..ab77eca --- /dev/null +++ b/3sem/cnts/contest14/04.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int n = (int) strtoll(argv[1], NULL, 10); + + int fd[2]; + pipe(fd); + + int tmp = 1; + write(fd2[1], &tmp, sizeof(tmp)); + + if (!fork()) { + int i = 0; + close(fd[0]); + + while (i < n) { + if (read(fd2[0], &i, sizeof(i)) == -1) { + return 0; + } + if (i >= n) { + write(fd1[1], &i, sizeof(i)); + break; + } + printf("%d %d\n", 1, i); + fflush(stdout); + i++; + write(fd1[1], &i, sizeof(i)); + } + + return 0; + } else if (!fork()) { + int i = 0; + close(fd2[0]); + close(fd1[1]); + + while (i < n) { + if (read(fd1[0], &i, sizeof(i)) == -1) { + return 0; + } + if (i >= n) { + write(fd1[1], &i, sizeof(i)); + break; + } + printf("%d %d\n", 2, i); + fflush(stdout); + i++; + write(fd2[1], &i, sizeof(i)); + } + + return 0; + } + + close(fd[0]); + close(fd[1]); + + while (wait(NULL) != -1) + ; + + printf("Done\n"); + + return 0; +} diff --git a/3sem/cnts/contest14/04a.c b/3sem/cnts/contest14/04a.c new file mode 100755 index 0000000..62bb25f --- /dev/null +++ b/3sem/cnts/contest14/04a.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include + +volatile sig_atomic_t sigusr1_received = 0; + +void +sigusr1_handler(int signum) +{ + sigusr1_received = 1; +} + +int +main(int argc, char **argv) +{ + int n = (int) strtol(argv[1], NULL, 10); + + int fd[2]; + pipe(fd); + + signal(SIGUSR1, sigusr1_handler); + + if (!fork()) { + close(fd[0]); + FILE *out = fdopen(fd[1], "w"); + + int i = 1; + while (i <= n) { + printf("1 %d\n", i); + fflush(stdout); + fprintf(out, "%d\n", i); + fflush(out); + kill(getppid(), SIGUSR1); + pause(); + if (i >= n) { + break; + } + i++; + } + + fclose(out); + return 0; + } else if (!fork()) { + close(fd[1]); + FILE *in = fdopen(fd[0], "r"); + + int i; + while (1) { + if (i >= n) { + break; + } + i++; + printf("2 %d\n", i); + fflush(stdout); + kill(getppid(), SIGUSR1); + pause(); + } + + fclose(in); + return 0; + } + + close(fd[0]); + close(fd[1]); + + while (wait(NULL) != -1) + ; + + printf("Done\n"); + + return 0; +} diff --git a/3sem/cnts/contest14/05.c b/3sem/cnts/contest14/05.c new file mode 100755 index 0000000..9eee975 --- /dev/null +++ b/3sem/cnts/contest14/05.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include + +volatile int last_prime = 0; +volatile int cnt = 0; + +void +f(int n) +{ + if (++cnt == 4) { + exit(0); + } + + printf("%d\n", last_prime); + fflush(stdout); + + return; +} + +void +exit_term(int n) +{ + exit(0); + + return; +} + +int +is_prime(int n) +{ + if (n < 2) { + return 0; + } + + for (int i = 2; i * i <= n; ++i) { + if (n % i == 0) { + return 0; + } + } + + return 1; +} + +int +main(int argc, char *argv[]) +{ + sigaction(SIGINT, &(struct sigaction){.sa_handler = f, .sa_flags = SA_RESTART}, NULL); + sigaction(SIGTERM, &(struct sigaction){.sa_handler = exit_term, .sa_flags = SA_RESTART}, NULL); + + printf("%d\n", getpid()); + fflush(stdout); + + int a, b; + scanf("%d", &a); + scanf("%d", &b); + + a = (a < 2) ? 2 : a; + + for (int i = a; i < b; ++i) { + if (is_prime(i)) { + last_prime = i; + } + } + + printf("-1\n"); + fflush(stdout); + + return 0; +} diff --git a/3sem/cnts/contest14/t1.c b/3sem/cnts/contest14/t1.c new file mode 100755 index 0000000..6d61c89 --- /dev/null +++ b/3sem/cnts/contest14/t1.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +volatile int count = 0; + +void +func(int sign) +{ + if (count < 5) { + printf("%d\n", count); + fflush(stdout); + count++; + } else { + exit(0); + } +} + +int +main(int argc, char *argv[]) +{ + printf("%d\n", getpid()); + fflush(stdout); + + if (signal(SIGHUP, func) == SIG_ERR) { + exit(1); + } + for (;;) { + pause(); + } + + return 0; +} diff --git a/3sem/cnts/contest2/01.c b/3sem/cnts/contest2/01.c new file mode 100755 index 0000000..f0164cc --- /dev/null +++ b/3sem/cnts/contest2/01.c @@ -0,0 +1,27 @@ +// #include + +typedef int STYPE; +typedef unsigned int UTYPE; + +STYPE +bit_reverse(STYPE value) +{ + UTYPE result = 0; + UTYPE uvalue = (UTYPE) value; + for (int i = 0; i < sizeof(STYPE) * 8; i++) { + result <<= 1; + result |= uvalue & 1; + uvalue >>= 1; + } + return (STYPE) result; +} + +// int main(void) { + +// STYPE value = 0b10101010; +// STYPE result = bit_reverse(value); +// printf("%d\n", result); +// printf("%ld\n", sizeof(STYPE)); + +// return 0; +// } diff --git a/3sem/cnts/contest2/02.c b/3sem/cnts/contest2/02.c new file mode 100755 index 0000000..a3c54d3 --- /dev/null +++ b/3sem/cnts/contest2/02.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + long long res_pos = 0, res_neg = 0; + + for (int i = 1; i < argc; i++) { + char *p; + errno = 0; + long long val = strtol(argv[i], &p, 10); + if (*p || errno || (int32_t) val != val || argv[i] == p) { + return 1; + } + // int32_t tmp; + if (val >= 0) { + // if (!__builtin_add_overflow(res_pos, val, &tmp)) { + res_pos += val; + // } + } else { + // if (!__builtin_add_overflow(res_neg, val, &tmp)) { + res_neg += val; + // } + } + } + + // if (!(res_neg && res_pos)) { + // printf("0\n"); + // } else { + // printf("%d\n", res_pos); + // printf("%d\n", res_neg); + // } + + printf("%lld\n", res_pos); + printf("%lld\n", res_neg); + + return 0; +} diff --git a/3sem/cnts/contest2/03.c b/3sem/cnts/contest2/03.c new file mode 100755 index 0000000..7fe7fd1 --- /dev/null +++ b/3sem/cnts/contest2/03.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +enum +{ + PRCN = 10000, +}; + +int +main(int argc, char *argv[]) +{ + long double a = 0; + + for (int i = 1; i < argc; i++) { + char *p; + errno = 0; + long double val = strtod(argv[i], &p); + if (*p || errno || argv[i] == p) { + return 1; + } + + if (i == 1) { + a = val * PRCN; + } else { + a = round(a * (100.L + val) / 100.L); + } + } + + if (argc == 1) { + return 1; + } + + printf("%.4Lf\n", a / PRCN); + + return 0; +} diff --git a/3sem/cnts/contest2/04.c b/3sem/cnts/contest2/04.c new file mode 100755 index 0000000..3dd3eec --- /dev/null +++ b/3sem/cnts/contest2/04.c @@ -0,0 +1,22 @@ +#include + +enum +{ + MY_INT_MAX = ~0u >> (!0), + MY_INT_MIN = ~(~0u >> (!0)) +}; + +int +satsum(int v1, int v2) +{ + int sum; + if (!__builtin_add_overflow(v1, v2, &sum)) { + return sum; + } else if (v1 > 0) { + return MY_INT_MAX; + } else { + return MY_INT_MIN; + } + + return 0; +} diff --git a/3sem/cnts/contest3/04.c b/3sem/cnts/contest3/04.c new file mode 100755 index 0000000..16f3c33 --- /dev/null +++ b/3sem/cnts/contest3/04.c @@ -0,0 +1,19 @@ +enum +{ + MY_INT_MAX = ~0u >> (!0), + MY_INT_MIN = ~(~0u >> (!0)) +}; + +int +satsum(int v1, int v2) +{ + if (v1 > 0 && (signed int) MY_INT_MAX - v1 < v2) { + return MY_INT_MAX; + } + + if (v1 < 0 && (signed int) MY_INT_MIN - v1 > v2) { + return MY_INT_MIN; + } + + return v1 + v2; +} diff --git a/3sem/cnts/contest3/05.c b/3sem/cnts/contest3/05.c new file mode 100755 index 0000000..66380f8 --- /dev/null +++ b/3sem/cnts/contest3/05.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +enum +{ + CHAR_IN_INT = 12 +}; + +struct Elem +{ + struct Elem *next; + char *str; +}; + +struct Elem * +dup_elem(struct Elem *head) +{ + if (head == NULL) { + return NULL; + } + + head->next = dup_elem(head->next); + + errno = 0; + char *p; + long n = strtol(head->str, &p, 10); + if (errno || (int) n != n || n == INT_MAX || *p || p == head->str) { + return head; + } + + struct Elem *new = calloc(1, sizeof(*new)); + if (new == NULL) { + exit(1); + } + + char *str = calloc(CHAR_IN_INT, sizeof(*str)); + snprintf(str, CHAR_IN_INT, "%d", (int) n + 1); + + new->str = str; + new->next = head; + + return new; +} diff --git a/3sem/cnts/contest4/01.c b/3sem/cnts/contest4/01.c new file mode 100755 index 0000000..b2e37f3 --- /dev/null +++ b/3sem/cnts/contest4/01.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include + +enum +{ + PEN_CHAR_BIT = 12 +}; + +int +safe_write(int fd, void *buf, size_t count) +{ + errno = 0; + size_t bytes_written = 0; + while (bytes_written < count) { + ssize_t res = write(fd, buf + bytes_written, count - bytes_written); + + if (res < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + + fprintf(stderr, "Error writing to file descriptor %d\n", fd); + close(fd); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + bytes_written += res; + } + + return bytes_written; +} + +int +main(int argc, char **argv) +{ + int fdout = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fdout == -1) { + return 1; + } + + unsigned char res[4]; + unsigned tmp; + while (scanf("%u", &tmp) == 1) { + res[0] = (tmp & (0x0F << (CHAR_BIT + PEN_CHAR_BIT))) >> (CHAR_BIT + PEN_CHAR_BIT); + res[1] = (tmp & (0xFF << PEN_CHAR_BIT)) >> PEN_CHAR_BIT; + res[2] = (tmp & (0x0F << CHAR_BIT)) >> CHAR_BIT; + res[3] = tmp & 0xFF; + safe_write(fdout, res, sizeof(res)); + } + + close(fdout); + + return 0; +} diff --git a/3sem/cnts/contest4/02.c b/3sem/cnts/contest4/02.c new file mode 100755 index 0000000..6e624d5 --- /dev/null +++ b/3sem/cnts/contest4/02.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +safe_write(int fd, void *buf, size_t count) +{ + errno = 0; + size_t bytes_written = 0; + while (bytes_written < count) { + ssize_t res = write(fd, buf + bytes_written, count - bytes_written); + + if (res < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + + fprintf(stderr, "Error writing to file descriptor %d\n", fd); + close(fd); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + bytes_written += res; + } + + return bytes_written; +} + +int +main(int argc, char **argv) +{ + if (argc < 3) { + return 1; + } + + long long n; + str_to_ll(argv[2], &n); + + int fd = open(argv[1], O_RDWR); + if (fd == -1) { + return 1; + } + + int is_first = 1; + double prev; + + for (int i = 0; i < n; ++i) { + double tmp; + int r = read(fd, &tmp, sizeof(tmp)); + if (r == -1 || (r && r != sizeof(tmp))) { + return 1; + } + if (r < 1) { + break; + } + + if (!is_first) { + tmp -= prev; + } else { + is_first = 0; + } + + if (lseek(fd, -sizeof(tmp), SEEK_CUR) == -1) { + return 1; + } + safe_write(fd, &tmp, sizeof(tmp)); + prev = tmp; + } + + close(fd); + + return 0; +} diff --git a/3sem/cnts/contest4/03-test.c b/3sem/cnts/contest4/03-test.c new file mode 100755 index 0000000..b83b2c4 --- /dev/null +++ b/3sem/cnts/contest4/03-test.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include + +ssize_t +my_write(int fd, void *buf, size_t count) +{ + size_t count_1 = 0; + ssize_t count_2; + while (count_1 != count) { + count_2 = write(fd, buf, count - count_1); + if (count_2 == -1) { + return -1; + } else if (count_2 == 0) { + return (ssize_t) count_1; + } else { + count_1 += (size_t) count_2; + } + } + return (ssize_t) count_1; +} + +ssize_t +my_read(int fd, void *buf, size_t count) +{ + size_t count_1 = 0; + ssize_t count_2; + while (count_1 != count) { + count_2 = read(fd, buf, count - count_1); + if (count_2 == -1) { + return -1; + } else if (count_2 == 0) { + return (ssize_t) count_1; + } else { + count_1 += (size_t) count_2; + } + } + return (ssize_t) count_1; +} + +int +main(int argc, char **argv) +{ + if (argc < 2) { + return 1; + } + + int fd; + if ((fd = open(argv[1], O_RDWR)) == -1) { + return 1; + } + + long long num, min, shift = 0; + + if (my_read(fd, &min, sizeof(min)) < sizeof(min)) { + if (errno) { + close(fd); + return 1; + } + close(fd); + return 0; + } + + for (int i = (int) sizeof(num); my_read(fd, &num, sizeof(min)) == sizeof(min); i += (int) sizeof(num)) { + if (num < min) { + min = num; + shift = i; + } + } + + lseek(fd, shift, 0); + if (errno) { + close(fd); + return 1; + } + + if (min != LLONG_MIN) { + min = -min; + } + + if (my_write(fd, &min, sizeof(min)) != sizeof(min)) { + close(fd); + return 1; + } + + close(fd); + if (errno) { + return 1; + } +} diff --git a/3sem/cnts/contest4/03.c b/3sem/cnts/contest4/03.c new file mode 100755 index 0000000..362a24d --- /dev/null +++ b/3sem/cnts/contest4/03.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum +{ + ARGS_NUM = 2, +}; + +int +safe_read(int fd, void *buf, size_t count) +{ + errno = 0; + size_t bytes_read = 0; + while (bytes_read < count) { + ssize_t res = read(fd, buf + bytes_read, count - bytes_read); + + if (res < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + + fprintf(stderr, "Error reading from file descriptor %d\n", fd); + close(fd); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + if (res == 0) { + break; + } + + bytes_read += res; + } + + return bytes_read; +} + +int +safe_write(int fd, void *buf, size_t count) +{ + errno = 0; + size_t bytes_written = 0; + while (bytes_written < count) { + ssize_t res = write(fd, buf + bytes_written, count - bytes_written); + + if (res < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + + fprintf(stderr, "Error writing to file descriptor %d\n", fd); + close(fd); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + bytes_written += res; + } + + return bytes_written; +} + +int +main(int argc, char *argv[]) +{ + if (argc != ARGS_NUM) { + fprintf(stderr, "Wrong number of arguments\n"); + return 1; + } + + int fd = open(argv[1], O_RDWR); + if (fd == -1) { + fprintf(stderr, "Error opening file %s\n", argv[1]); + + return 1; + } + + long long num, min_num = LLONG_MAX; + off_t pt_min = -1; + + while (safe_read(fd, &num, sizeof(num)) == sizeof(num)) { + if (num < min_num || pt_min == -1) { + min_num = num; + + if ((pt_min = lseek(fd, 0, SEEK_CUR) - sizeof(num)) == -1) { + fprintf(stderr, "Error in navigate file %s\n", argv[1]); + + return 1; + } + } + } + + if (min_num != LLONG_MIN && pt_min != -1) { + min_num = -min_num; + if (lseek(fd, pt_min, SEEK_SET) == -1) { + fprintf(stderr, "Error in navigate file %s\n", argv[1]); + + return 1; + } + + if (safe_write(fd, &min_num, sizeof(min_num)) != sizeof(num)) { + printf("Error while writing"); + + return 1; + } + } + + close(fd); + + return 0; +} diff --git a/3sem/cnts/contest4/04-copy.c b/3sem/cnts/contest4/04-copy.c new file mode 100755 index 0000000..4ea7842 --- /dev/null +++ b/3sem/cnts/contest4/04-copy.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Node +{ + int32_t key; + int32_t left_idx; + int32_t right_idx; +}; + +void +read_struct(int fd, struct Node *node, int is_le) +{ + unsigned char buf[sizeof(*node)]; + int n = 0; + while (n != sizeof(*node)) { + ssize_t off = read(fd, buf + n, sizeof(*node) - n); + if (off == -1) { + close(fd); + exit(1); + } + n += off; + } + // int r = read(fd, buf, sizeof(*node)); + // if (r == -1) { + // close(fd); + // exit(1); + // } + + int n_byte = sizeof(int32_t); + node->key = 0; + node->left_idx = 0; + node->right_idx = 0; + + for (int j = 0; j < n_byte; ++j) { + int off = (is_le) ? (CHAR_BIT * (sizeof(uint32_t) - (j + 1))) : (CHAR_BIT * j); + + node->key |= (uint32_t) buf[j] << off; + node->left_idx |= (uint32_t) buf[j + n_byte * 1] << off; + node->right_idx |= (uint32_t) buf[j + n_byte * 2] << off; + } +} + +void +inorder_traversal(int fd, int32_t idx, int is_le) +{ + if (idx == 0) { + return; + } + if (idx == -1) { + idx = 0; + } + + struct Node tmp; + if (lseek(fd, idx * sizeof(struct Node), SEEK_SET) == -1) { + close(fd); + exit(1); + } + read_struct(fd, &tmp, is_le); + + inorder_traversal(fd, tmp.right_idx, is_le); + printf("%d\n", tmp.key); + inorder_traversal(fd, tmp.left_idx, is_le); + + return; +} + +int +main(int argc, char **argv) +{ + if (argc != 2) { + return 1; + } + + int test = 1; + int is_le = 0; + if (*(char *) &test == 1) { + is_le = 1; + } + + int fd = open(argv[1], O_RDONLY); + if (fd == -1) { + return 1; + } + + inorder_traversal(fd, -1, is_le); + putchar('\n'); + close(fd); + + return 0; +} diff --git a/3sem/cnts/contest4/04-test.c b/3sem/cnts/contest4/04-test.c new file mode 100755 index 0000000..8453634 --- /dev/null +++ b/3sem/cnts/contest4/04-test.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct Node +{ + int32_t key; + int32_t left_idx; + int32_t right_idx; +} Node; + +int +convert_num_to_sys(char num[]) +{ + unsigned res = 0; + for (int i = 0; i < sizeof(res); ++i) { + unsigned cur = (unsigned char) num[sizeof(res) - i - 1]; + res ^= (cur << (CHAR_BIT * i)); + } + return (int) res; +} + +int +read_int(int fd) +{ + int res = 0; + char buf[sizeof(res)]; + int pos = 0; + while (pos != sizeof(res)) { + ssize_t off = read(fd, buf + pos, sizeof(res) - pos); + if (off == -1) { + printf("Error, can't read from file\n"); + exit(1); + } + pos += off; + } + res = convert_num_to_sys(buf); + return res; +} + +Node +read_node(int fd) +{ + Node new_node; + new_node.key = read_int(fd); + new_node.right_idx = read_int(fd); + new_node.left_idx = read_int(fd); + return new_node; +} + +void +dfs(Node head, int fd) +{ + if (head.left_idx != 0) { + if (lseek(fd, head.left_idx * sizeof(Node), SEEK_SET) == -1) { + printf("Error? can't seek throw file\n"); + exit(1); + } + Node left_node = read_node(fd); + dfs(left_node, fd); + } + printf("%d\n", head.key); + if (head.right_idx != 0) { + if (lseek(fd, head.right_idx * sizeof(Node), SEEK_SET) == -1) { + printf("Error? can't seek throw file\n"); + exit(1); + } + Node right_node = read_node(fd); + dfs(right_node, fd); + } +} + +int +main(int argc, char *argv[]) +{ + if (argc < 2) { + printf("Error: Not enough argumens\n"); + exit(1); + } + int fd = open(argv[1], O_RDONLY, 0600); + if (fd < 0) { + printf("Error: Can't open file\n"); + exit(1); + } + struct stat st; + if (stat(argv[1], &st) == -1) { + printf("Error, can't get info about file\n"); + exit(1); + } + if (st.st_size == 0) { + return 0; + } + Node head = read_node(fd); + dfs(head, fd); + close(fd); +} diff --git a/3sem/cnts/contest4/04.c b/3sem/cnts/contest4/04.c new file mode 100755 index 0000000..82193da --- /dev/null +++ b/3sem/cnts/contest4/04.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct Node +{ + int32_t key; + int32_t left_idx; + int32_t right_idx; +}; + +void +inorder_traversal(struct Node *mas, int32_t idx, int32_t *keys, int32_t *pos) +{ + if (idx == 0) { + return; + } + if (idx == -1) { + idx = 0; + } + + inorder_traversal(mas, mas[idx].left_idx, keys, pos); + keys[(*pos)++] = mas[idx].key; + inorder_traversal(mas, mas[idx].right_idx, keys, pos); + + return; +} + +int +main(int argc, char **argv) +{ + if (argc < 2) { + return 1; + } + + int test = 1; + int is_le = 0; + if (*(char *) &test == 1) { + is_le = 1; + } + + int fd = open(argv[1], O_RDONLY); + if (fd == -1) { + return 1; + } + + int n = lseek(fd, 0, SEEK_END) / sizeof(struct Node); + lseek(fd, 0, SEEK_SET); + + struct Node *mas = calloc(n, sizeof(struct Node)); + + for (int i = 0; i < n; ++i) { + struct Node tmp; + + unsigned char buf[sizeof(tmp)]; + int r = read(fd, buf, sizeof(tmp)); + if (r == -1) { + free(mas); + close(fd); + return 1; + } + if (r < 12) { + break; + } + int n_byte = sizeof(int32_t); + tmp.key = 0; + tmp.left_idx = 0; + tmp.right_idx = 0; + if (is_le) { + for (int j = 0; j < n_byte; ++j) { + tmp.key |= (u_int32_t) buf[j] << (CHAR_BIT * j); + tmp.left_idx |= (u_int32_t) buf[j + n_byte * 1] << (CHAR_BIT * j); + tmp.right_idx |= (u_int32_t) buf[j + n_byte * 2] << (CHAR_BIT * j); + } + } else { + for (int j = 0; j < n_byte; ++j) { + tmp.key |= (u_int32_t) buf[j] << (CHAR_BIT * (sizeof(u_int32_t) - (j + 1))); + tmp.left_idx |= (u_int32_t) buf[j + n_byte * 1] << (CHAR_BIT * (sizeof(u_int32_t) - (j + 1))); + tmp.right_idx |= (u_int32_t) buf[j + n_byte * 2] << (CHAR_BIT * (sizeof(u_int32_t) - (j + 1))); + } + } + + mas[i] = tmp; + } + + int32_t *keys = calloc(n, sizeof(int32_t)); + int32_t pos = 0; + inorder_traversal(mas, -1, keys, &pos); + + for (int32_t i = 0; i < pos; ++i) { + printf("%d\n", keys[i]); + } + + free(keys); + free(mas); + close(fd); + + return 0; +} diff --git a/3sem/cnts/contest4/04cc.c b/3sem/cnts/contest4/04cc.c new file mode 100755 index 0000000..9850034 --- /dev/null +++ b/3sem/cnts/contest4/04cc.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +struct Node +{ + int32_t key, left_idx, right_idx; +}; +void +inorder_traversal(struct Node *mas, int32_t idx, int32_t *keys, int32_t *pos) +{ + if (idx == 0) { + return; + } + if (idx == -1) { + idx = 0; + } + inorder_traversal(mas, mas[idx].left_idx, keys, pos), keys[(*pos)++] = mas[idx].key, + inorder_traversal(mas, mas[idx].right_idx, keys, pos); + return; +} +int +main(int argc, char **argv) +{ + if (argc < 2) { + return 1; + } + int test = 1, is_le = 0; + if (*(char *) &test == 1) { + is_le = 1; + } + int fd = open(argv[1], O_RDONLY); + if (fd == -1) { + return 1; + } + int n = lseek(fd, 0, SEEK_END) / sizeof(struct Node); + lseek(fd, 0, SEEK_SET); + struct Node *mas = calloc(n, sizeof(struct Node)); + for (int i = 0; i < n; ++i) { + struct Node tmp; + unsigned char buf[sizeof(tmp)]; + int r = read(fd, buf, sizeof(tmp)); + if (r == -1) { + free(mas), close(fd); + return 1; + } + if (r < 12) { + break; + } + int n_byte = sizeof(int32_t); + tmp.key = 0, tmp.left_idx = 0, tmp.right_idx = 0; + if (is_le) { + for (int j = 0; j < n_byte; ++j) { + tmp.key |= (u_int32_t) buf[j] << (CHAR_BIT * j), + tmp.left_idx |= (u_int32_t) buf[j + n_byte * 1] << (CHAR_BIT * j), + tmp.right_idx |= (u_int32_t) buf[j + n_byte * 2] << (CHAR_BIT * j); + } + } else { + for (int j = 0; j < n_byte; ++j) { + tmp.key |= (u_int32_t) buf[j] << (CHAR_BIT * (sizeof(u_int32_t) - (j + 1))), + tmp.left_idx |= (u_int32_t) buf[j + n_byte * 1] << (CHAR_BIT * (sizeof(u_int32_t) - (j + 1))), + tmp.right_idx |= (u_int32_t) buf[j + n_byte * 2] << (CHAR_BIT * (sizeof(u_int32_t) - (j + 1))); + } + } + mas[i] = tmp; + } + int32_t *keys = calloc(n, sizeof(int32_t)), pos = 0; + inorder_traversal(mas, -1, keys, &pos); + for (int32_t i = 0; i < pos; ++i) { + printf("%d\n", keys[i]); + } + free(keys), free(mas), close(fd); + return 0; +} diff --git a/3sem/cnts/contest4/05.c b/3sem/cnts/contest4/05.c new file mode 100755 index 0000000..92dc6c7 --- /dev/null +++ b/3sem/cnts/contest4/05.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int +main(int argc, char *argv[]) +{ + if (argc != 4) { + return 1; + } + + int fdin = open(argv[1], O_RDONLY); + int fdout = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fdin == -1 || fdout == -1) { + return 1; + } + + char *p; + errno = 0; + long long mod = strtoll(argv[3], &p, 10); + if (errno || *p || p == argv[3] || !mod || (int32_t) mod != mod) { + return 1; + } + + unsigned long long res = 0; + unsigned long long num = 1; + unsigned char buf; + int r = read(fdin, &buf, sizeof(buf)); + if (r && r != sizeof(buf)) { + return 1; + } + while (r > 0) { + for (int i = 0; i < CHAR_BIT; i++) { + num %= mod; + res += (num * num) % mod; + res %= mod; + + if (buf & (1 << i)) { + int32_t res32 = res; + + if (write(fdout, &res32, sizeof(res32)) == -1) { + return 1; + } + } + num++; + } + r = read(fdin, &buf, sizeof(buf)); + if (r && r != sizeof(buf)) { + return 1; + } + } + + if (r == -1) { + return 1; + } + + close(fdin); + close(fdout); + + return 0; +} diff --git a/3sem/cnts/contest4/test.c b/3sem/cnts/contest4/test.c new file mode 100755 index 0000000..a59ca0c --- /dev/null +++ b/3sem/cnts/contest4/test.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct Node +{ + int32_t key; + int32_t left_idx; + int32_t right_idx; +}; + +void +create_binary_file(const char *filename, struct Node *nodes, int n) +{ + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + perror("open"); + exit(EXIT_FAILURE); + } + for (int i = 0; i < n; ++i) { + struct Node node = nodes[i]; + node.key = htonl(node.key); + node.left_idx = htonl(node.left_idx); + node.right_idx = htonl(node.right_idx); + write(fd, &node, sizeof(struct Node)); + } + close(fd); +} + +char * +execute_program(const char *filename) +{ + char command[256]; + snprintf(command, sizeof(command), "./04 %s", filename); + FILE *fp = popen(command, "r"); + if (fp == NULL) { + perror("popen"); + exit(EXIT_FAILURE); + } + char *output = malloc(1024); + fread(output, 1, 1024, fp); + pclose(fp); + return output; +} + +void +test_case(struct Node *nodes, int n, const char *expected_output) +{ + const char *filename = "test.bin"; + create_binary_file(filename, nodes, n); + char *output = execute_program(filename); + assert(strcmp(output, expected_output) == 0); + free(output); +} + +int +main() +{ + struct Node nodes1[] = {{10, 1, 2}, {5, 0, 0}, {15, 0, 0}}; + test_case(nodes1, 3, "15 10 5 \n"); + + struct Node nodes2[] = {{20, 1, 2}, {10, 0, 0}, {30, 0, 0}}; + test_case(nodes2, 3, "30 20 10 \n"); + + printf("All tests passed.\n"); + return 0; +} diff --git a/3sem/cnts/contest4/test.py b/3sem/cnts/contest4/test.py new file mode 100755 index 0000000..e5d05f3 --- /dev/null +++ b/3sem/cnts/contest4/test.py @@ -0,0 +1,32 @@ +import struct + +# Define the Node structure +class Node: + def __init__(self, key, left_idx, right_idx): + self.key = key + self.left_idx = left_idx + self.right_idx = right_idx + +# Create a binary search tree +nodes = [ + Node(20, 1, 2), # Root node + Node(-10, 3, 4), # Left child of root + Node(30, 5, 6), # Right child of root + Node(-5, 0, 0), # Left child of node with key 10 + Node(15, 0, 0), # Right child of node with key 10 + Node(25, 0, 0), # Left child of node with key 30 + Node(35, 0, 0) # Right child of node with key 30 +] + +# Write the nodes to a binary file in Big-Endian format +with open('test_tree.bin', 'wb') as f: + for node in nodes: + # Pack the data in Big-Endian format + f.write(struct.pack('>i', node.key)) + f.write(struct.pack('>i', node.left_idx)) + f.write(struct.pack('>i', node.right_idx)) + +# Verify the content of the file +with open('test_tree.bin', 'rb') as f: + content = f.read() + print("Binary content:", bytes(content).hex()) \ No newline at end of file diff --git a/3sem/cnts/contest5/01.c b/3sem/cnts/contest5/01.c new file mode 100755 index 0000000..dd05c4b --- /dev/null +++ b/3sem/cnts/contest5/01.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +enum +{ + KIBIBYTE = 1024 +}; + +int +main(int argc, char *argv[]) +{ + long long int sum = 0; + + for (int i = 1; i < argc; ++i) { + struct stat st; + + if (!(lstat(argv[i], &st) < 0 || st.st_nlink != 1 || !S_ISREG(st.st_mode) || st.st_size % KIBIBYTE != 0)) { + sum += st.st_size; + } + } + + printf("%lld\n", sum); + + return 0; +} diff --git a/3sem/cnts/contest5/02.c b/3sem/cnts/contest5/02.c new file mode 100755 index 0000000..14e7070 --- /dev/null +++ b/3sem/cnts/contest5/02.c @@ -0,0 +1,32 @@ +#include +#include +#include + +enum +{ + MAX_MODE = 0777, +}; + +int +main(int argc, char *argv[]) +{ + const char s[] = "rwxrwxrwx"; + + for (int i = 1; i < argc; ++i) { + char *p; + errno = 0; + int n = strtol(argv[i], &p, 8); + + if (errno || *p || p == argv[i] || n > MAX_MODE || n < 0) { + return 1; + } + + for (int j = 0; j < sizeof(s) - 1; ++j) { + putchar((n & (1 << (sizeof(s) - 2 - j))) ? s[j] : '-'); + } + + printf("\n"); + } + + return 0; +} diff --git a/3sem/cnts/contest5/03.c b/3sem/cnts/contest5/03.c new file mode 100755 index 0000000..a1f1ec6 --- /dev/null +++ b/3sem/cnts/contest5/03.c @@ -0,0 +1,36 @@ +#include + +enum +{ + RWX_PERMISSIONS = 0777, +}; + +int +parse_rwx_permissions(const char *str) +{ + if (str == NULL) { + return -1; + } + + const char expected[] = "rwxrwxrwx"; + + unsigned res = 0; + int i = 0; + while (str[i]) { + res <<= 1; + + if (str[i] == expected[i] && expected[i]) { + res |= 1; + } else if (str[i] != '-' || !expected[i]) { + return -1; + } + + ++i; + } + + if (res > RWX_PERMISSIONS || res < 0 || expected[i]) { + return -1; + } + + return res; +} diff --git a/3sem/cnts/contest5/04.c b/3sem/cnts/contest5/04.c new file mode 100755 index 0000000..9b6791d --- /dev/null +++ b/3sem/cnts/contest5/04.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct File +{ + char *pathname; + __ino_t st_ino; + __dev_t st_dev; +}; + +int +cmp_structs(struct File elem1, struct stat elem2) +{ + return elem1.st_dev == elem2.st_dev && elem1.st_ino == elem2.st_ino; +} + +int +cmp_mas(const void *a, const void *b) +{ + struct File elem1 = *(struct File *) a; + struct File elem2 = *(struct File *) b; + + return strcmp(elem1.pathname, elem2.pathname); +} + +int +main(int argc, char **argv) +{ + struct File *mas = calloc(10, sizeof(struct File)); + if (mas == NULL) { + fprintf(stderr, "Error! Can't calloc mas\n"); + + return 1; + } + int n = 0, capacity = 10; + + for (int i = 1; i < argc; ++i) { + + struct stat st; + if (stat(argv[i], &st) < 0) { + continue; + } + + int flag = 0; + for (int j = 0; j < n; ++j) { + if (cmp_structs(mas[j], st)) { // 1 if equal + flag = 1; + + if (strcmp(mas[j].pathname, argv[i]) < 0) { + mas[j].pathname = argv[i]; + } + + break; + } + } + + if (!flag) { + if (n == capacity) { + capacity *= 2; + + while (!realloc(mas, capacity * sizeof(mas[0])) && capacity > n) { + capacity--; + } + + if (capacity == n) { + fprintf(stderr, "Error! Can't realloc mas\n"); + + return 1; + } + } + + mas[n++] = (struct File){argv[i], st.st_ino, st.st_dev}; + } + } + + qsort(mas, n, sizeof(mas[0]), cmp_mas); + + for (int i = 0; i < n; ++i) { + printf("%s\n", mas[i].pathname); + } + + free(mas); + + return 0; +} diff --git a/3sem/cnts/contest5/05-old.c b/3sem/cnts/contest5/05-old.c new file mode 100755 index 0000000..bfb0394 --- /dev/null +++ b/3sem/cnts/contest5/05-old.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +char * +relativize_path(const char *path1, const char *path2) +{ + char *spath1 = calloc(strlen(path1) + 2, sizeof(char)); + strcpy(spath1, path1); + spath1[strlen(path1)] = '\0'; + if (spath1[strlen(path1) - 1] != '/') { + strcat(spath1, "/"); + } + + char *res; + if ((res = calloc(PATH_MAX, sizeof(char))) == NULL) { + exit(1); + } + + int i = 0; + int ptr = 0; + while (spath1[i] == path2[i] && spath1[i]) { + if (spath1[i] == '/') { + ptr = i; + } + i++; + } + + int deep1 = 0; + while (spath1[i]) { + if (spath1[i] == '/') { + deep1++; + } + + i++; + } + + if (!deep1 && path2[strlen(path2) - 1] == '/') { + snprintf(res, PATH_MAX, "."); + return res; + } + + int deep2 = 0; + i = ptr + 1; + while (path2[i]) { + if (path2[i] == '/') { + deep2++; + } + + i++; + } + + for (int j = 0; j < deep1; j++) { + res[j * 3] = '.'; + res[j * 3 + 1] = '.'; + res[j * 3 + 2] = '/'; + } + + if (deep2 == 0 && deep1) { + if (res[strlen(res) - 1] == '/') { + res[strlen(res) - 1] = '\0'; + } + return res; + } + + snprintf(res + deep1 * 3, PATH_MAX - deep1 * 3, "%s", path2 + ptr + 1); + + if (res[strlen(res) - 1] == '/') { + res[strlen(res) - 1] = '\0'; + } + + return res; +} + +int +main() +{ + const char *path1 = "/home/krosh/cmc/contest5"; + const char *path2 = "/home/krosh/cmc/contest5/subdir/file.txt"; + + char *relative_path = relativize_path(path1, path2); + printf("Relative path: %s\n", relative_path); + + const char *path3 = "/a/b/c/d"; + const char *path4 = "/a/e/f"; + + printf("Relative path: %s\n", relativize_path(path3, path4)); + + const char *path5 = "/a/f/g/h/j"; + const char *path6 = "/a/f/g/h"; + printf("Relative path: %s\n", relativize_path(path5, path6)); + + const char *path7 = "/a"; + const char *path8 = "/a"; + printf("Relative path: %s\n", relativize_path(path7, path8)); + + return 0; +} diff --git a/3sem/cnts/contest5/05.c b/3sem/cnts/contest5/05.c new file mode 100755 index 0000000..bfb0394 --- /dev/null +++ b/3sem/cnts/contest5/05.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +char * +relativize_path(const char *path1, const char *path2) +{ + char *spath1 = calloc(strlen(path1) + 2, sizeof(char)); + strcpy(spath1, path1); + spath1[strlen(path1)] = '\0'; + if (spath1[strlen(path1) - 1] != '/') { + strcat(spath1, "/"); + } + + char *res; + if ((res = calloc(PATH_MAX, sizeof(char))) == NULL) { + exit(1); + } + + int i = 0; + int ptr = 0; + while (spath1[i] == path2[i] && spath1[i]) { + if (spath1[i] == '/') { + ptr = i; + } + i++; + } + + int deep1 = 0; + while (spath1[i]) { + if (spath1[i] == '/') { + deep1++; + } + + i++; + } + + if (!deep1 && path2[strlen(path2) - 1] == '/') { + snprintf(res, PATH_MAX, "."); + return res; + } + + int deep2 = 0; + i = ptr + 1; + while (path2[i]) { + if (path2[i] == '/') { + deep2++; + } + + i++; + } + + for (int j = 0; j < deep1; j++) { + res[j * 3] = '.'; + res[j * 3 + 1] = '.'; + res[j * 3 + 2] = '/'; + } + + if (deep2 == 0 && deep1) { + if (res[strlen(res) - 1] == '/') { + res[strlen(res) - 1] = '\0'; + } + return res; + } + + snprintf(res + deep1 * 3, PATH_MAX - deep1 * 3, "%s", path2 + ptr + 1); + + if (res[strlen(res) - 1] == '/') { + res[strlen(res) - 1] = '\0'; + } + + return res; +} + +int +main() +{ + const char *path1 = "/home/krosh/cmc/contest5"; + const char *path2 = "/home/krosh/cmc/contest5/subdir/file.txt"; + + char *relative_path = relativize_path(path1, path2); + printf("Relative path: %s\n", relative_path); + + const char *path3 = "/a/b/c/d"; + const char *path4 = "/a/e/f"; + + printf("Relative path: %s\n", relativize_path(path3, path4)); + + const char *path5 = "/a/f/g/h/j"; + const char *path6 = "/a/f/g/h"; + printf("Relative path: %s\n", relativize_path(path5, path6)); + + const char *path7 = "/a"; + const char *path8 = "/a"; + printf("Relative path: %s\n", relativize_path(path7, path8)); + + return 0; +} diff --git a/3sem/cnts/contest6/01.c b/3sem/cnts/contest6/01.c new file mode 100755 index 0000000..e6c24da --- /dev/null +++ b/3sem/cnts/contest6/01.c @@ -0,0 +1,55 @@ +#include // Standard I/O functions +#include // Standard library functions: memory allocation, process control, conversions, etc. +#include // POSIX API: read, write, close, etc. +#include // Data types used in system calls +#include // Data returned by the functions fstat(), lstat(), and stat() +#include // Sizes of basic types +#include // Directory entry format +#include // String handling functions + +enum +{ + ARGS_NUM = 2, +}; + +int +main(int argc, char *argv[]) +{ + if (argc != ARGS_NUM) { + fprintf(stderr, "Wrong number of arguments\n"); + return 1; + } + + int n = 0; + + DIR *ddir = opendir(argv[1]); + struct dirent *de; + while ((de = readdir(ddir))) { + char *name = calloc(PATH_MAX, sizeof(char)); + if (!name) { + return 1; + } + + int ret = snprintf(name, PATH_MAX, "%s/%s", argv[1], de->d_name); + if (ret < 0 || ret >= PATH_MAX) { + free(name); + return 1; + } + + struct stat st; + if (stat(name, &st) < 0) { + continue; + } + char ext[] = ".exe"; + if (S_ISREG(st.st_mode) && !access(name, X_OK) && strlen(name) >= 4 && + !strcmp(name + strlen(name) - (sizeof(ext) - 1), ext)) { + ++n; + } + } + + printf("%d\n", n); + + closedir(ddir); + + return 0; +} diff --git a/3sem/cnts/contest6/02-t.c b/3sem/cnts/contest6/02-t.c new file mode 100755 index 0000000..4db6534 --- /dev/null +++ b/3sem/cnts/contest6/02-t.c @@ -0,0 +1,68 @@ +long long +stlen(char *buf) +{ + long long i = 0; + for (; buf[i] != '\0'; ++i) { + } + return i; +} + +long long +shift(char *buf, long long st, long long sh, long long len) +{ + long long i = st; + if (i + sh > len) { + return len; + } + for (; i + sh <= len; ++i) { + buf[i] = buf[i + sh]; + } + return len - sh; +} + +void +normalize_path(char *buf) +{ + long long len = stlen(buf); + for (int i = 1; buf[i]; ++i) { + if (buf[i] == '.' && buf[i - 1] == '/') { + if (buf[i + 1] == '.' && (buf[i + 2] == '/' buf[i + 2] == '\0')) { + if (i - 2 >= 0) { + int j; + for (j = i - 2; buf[j] != '/'; --j) { + } + ++j; + if (buf[i + 2] == '/') { + len = shift(buf, j, i + 3 - j, len); + i = j - 1; + } else if (!buf[i + 2]) { + len = shift(buf, j, i + 2 - j, len); + i = j - 1; + } + } else { + if (buf[i + 2] == '/') { + len = shift(buf, i, 3, len); + --i; + } else if (!buf[i + 2]) { + len = shift(buf, i, 2, len); + --i; + } + } + } else if (buf[i + 1] == '/' buf[i + 1] == '\0') { + if (buf[i + 1] == '/') { + len = shift(buf, i, 2, len); + --i; + } else if (!buf[i + 1]) { + len = shift(buf, i, 1, len); + --i; + } + } + } + } + len = stlen(buf); + if (len != 1) { + if (buf[len - 1] == '/') { + buf[len - 1] = '\0'; + } + } +} diff --git a/3sem/cnts/contest6/02-ttt.c b/3sem/cnts/contest6/02-ttt.c new file mode 100755 index 0000000..221a4e2 --- /dev/null +++ b/3sem/cnts/contest6/02-ttt.c @@ -0,0 +1,110 @@ +#include // Standard I/O functions +#include // Standard library functions: memory allocation, process control, conversions, etc. +#include // File control options +#include // POSIX API: read, write, close, etc. +#include // File control options +#include // Data types used in system calls +#include // Data returned by the functions fstat(), lstat(), and stat() +#include // Sizes of basic types +#include // Sizes of basic types +#include // Error reporting macros +#include // Exact-width integer types +#include // Mathematical functions +#include // Directory entry format +#include // String handling functions +#include // Data returned by the functions fstat(), lstat(), and stat() + +// переписать на strcmp. + +void +normalize_path(char *buf) +{ + unsigned long long pt_real = 0, pt_res = 0; + + unsigned long long len = 0; // проверить правильное вычисление длины + while (buf[len++] != '\0') + ; + len--; + + while (pt_real < len) { + printf("pt: %lld -- %d %d %d\n", pt_real, pt_real - 2 == len, buf[pt_real] == '.', + buf[pt_real + 1] == '.'); // может вызвать выход за массив + if ((len - pt_real >= 3 && buf[pt_real] == '.' && buf[pt_real + 1] == '.' && buf[pt_real + 2] == '/') || + (pt_real - 2 == len && buf[pt_real] == '.' && buf[pt_real + 1] == '.')) { + printf("meow\n"); + if (pt_real > 0 && buf[pt_real - 1] == '/') { + pt_real += 3; + + if (pt_res == 1) { + continue; + } + + if (pt_res == 0) { // impossible ? + pt_res = 1; + continue; + } + pt_res -= 2; + while (pt_res > 0 && buf[pt_res] != '/') { + pt_res--; + } + + pt_res++; + continue; + } + } else if ((len - pt_real >= 2 && buf[pt_real] == '.' && buf[pt_real + 1] == '/') || + (len == pt_real - 1 && buf[pt_real] == '.')) { + if (pt_real > 0 && buf[pt_real - 1] == '/') { + // printf("paw\n"); + pt_real += 2; + + continue; + } + } + + buf[pt_res] = buf[pt_real]; + pt_real++; + pt_res++; + } + + // if (pt_real > 1 && buf[pt_real - 1] == '.') { + // if (pt_real > 2 && buf[pt_real - 2] == '.' && buf[pt_real - 3] == '/') { + // if (pt_res > 1) { + // pt_res -= 2; + // while (pt_res > 0 && buf[pt_res - 1] != '/') { + // pt_res--; + // } + // } + // } else if (pt_real > 1 && buf[pt_real - 2] == '/') { + // if (pt_res > 0) { + // pt_res--; + // } + // } + // } + + buf[pt_res] = '\0'; + + if (pt_res > 1 && buf[pt_res - 1] == '/') { + buf[pt_res - 1] = '\0'; + } + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + char path[PATH_MAX]; + strncpy(path, argv[1], PATH_MAX - 1); + path[PATH_MAX - 1] = '\0'; + + normalize_path(path); + + printf("Normalized path: %s\n", path); + + return EXIT_SUCCESS; +} diff --git a/3sem/cnts/contest6/02.c b/3sem/cnts/contest6/02.c new file mode 100755 index 0000000..e288b87 --- /dev/null +++ b/3sem/cnts/contest6/02.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +size_t +len(const char *buf) +{ + size_t i = 0; + while (buf[i] != '\0') { + ++i; + } + return i; +} + +size_t +shift_left(char *str, size_t st, size_t shift_amount, size_t length) +{ + size_t i = st; + if (i + shift_amount > length) { + return length; + } + + while (i + shift_amount < length) { + str[i] = str[i + shift_amount]; + ++i; + } + + return length - shift_amount; +} + +void +normalize_path(char *path) +{ + size_t length = len(path); + + size_t i = 1; + while (path[i]) { + if (path[i - 1] == '/' && path[i] == '.') { + if (path[i + 1] == '.' && (path[i + 2] == '/' || !path[i + 2])) { + if (i < 1) { + if (path[i + 2] == '/') { + length = shift_left(path, i, 3, length); + --i; + } else if (!path[i + 2]) { + length = shift_left(path, i, 2, length); + --i; + } + } else { + size_t j = i - 2; + + while (j > 0 && path[j] != '/') { + --j; + } + + ++j; + + if (path[i + 2] == '/') { + length = shift_left(path, j, i + 3 - j, length); + i = j - 1; + } else if (!path[i + 2]) { + length = shift_left(path, j, i + 2 - j, length); + i = j - 1; + } + } + } else if (path[i + 1] == '/' || !path[i + 1]) { + if (path[i + 1] == '/') { + length = shift_left(path, i, 2, length); + --i; + } else if (!path[i + 1]) { + length = shift_left(path, i, 1, length); + --i; + } + } + } + + ++i; + } + + if (len(path) != 1 && path[len(path) - 1] == '/') { + path[len(path) - 1] = '\0'; + } + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + char path[PATH_MAX]; + strncpy(path, argv[1], PATH_MAX - 1); + path[PATH_MAX - 1] = '\0'; + + normalize_path(path); + + printf("Normalized path: %s\n", path); + + return EXIT_SUCCESS; +} diff --git a/3sem/cnts/contest6/03.c b/3sem/cnts/contest6/03.c new file mode 100755 index 0000000..bd82238 --- /dev/null +++ b/3sem/cnts/contest6/03.c @@ -0,0 +1,36 @@ +#include + +struct s1 +{ + char f1; + long long f2; + char f3; +}; + +struct s2 +{ + char f1; + char f3; + long long f2; +}; + +size_t +compactify(void *ptr, size_t size) +{ + if (size == 0) { + return 0; + } + + size_t count = size / sizeof(struct s1); + struct s1 *src = (struct s1 *) ptr; + struct s2 *dst = (struct s2 *) ptr; + + for (size_t i = 0; i < count; ++i) { + struct s1 tmp = src[i]; + dst[i].f1 = tmp.f1; + dst[i].f3 = tmp.f3; + dst[i].f2 = tmp.f2; + } + + return count * sizeof(struct s2); +} diff --git a/3sem/cnts/contest6/04.c b/3sem/cnts/contest6/04.c new file mode 100755 index 0000000..391d630 --- /dev/null +++ b/3sem/cnts/contest6/04.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +enum +{ + ARGS_NUM = 3, + MAX_DIRS = 1000, +}; + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +void +list_files(char *path_from, const int start, size_t max_size, int depth) +{ + if (depth > 4) { + return; + } + + DIR *dir = opendir(path_from); + if (dir == NULL) { + return; + } + + char **dirs = (char **) calloc(MAX_DIRS, sizeof(char *)); + if (dirs == NULL) { + exit(1); + } + + int cnt = 0; + + struct dirent *dd; + while ((dd = readdir(dir))) { + if (!(strcmp(dd->d_name, ".") && strcmp(dd->d_name, ".."))) { + continue; + } + + char name[PATH_MAX]; + int ret = snprintf(name, sizeof(name), "%s/%s", path_from, dd->d_name); + if (ret < 0 || ret >= PATH_MAX) { + exit(1); + } + + struct stat st; + if (lstat(name, &st) < 0) { + continue; + } + + if (S_ISDIR(st.st_mode)) { + dirs[cnt] = (char *) calloc(PATH_MAX, sizeof(char)); + memcpy(dirs[cnt], name, strlen(name)); + cnt++; + } else if (st.st_size <= max_size && !access(name, R_OK) && S_ISREG(st.st_mode)) { + ret = snprintf(name, sizeof(name), "%s/%s", path_from + start + 1, dd->d_name); + + if (ret < 0 || ret >= PATH_MAX) { + exit(1); + } + + printf("%s\n", name + (name[0] == '/')); + } + } + + for (int i = 0; i < cnt; i++) { + list_files(dirs[i], start, max_size, depth + 1); + + free(dirs[i]); + } + + closedir(dir); + free(dirs); + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != ARGS_NUM) { + return 1; + } + + int len_arg = strlen(argv[1]); + char *dir_path = calloc(PATH_MAX, sizeof(char)); + memcpy(dir_path, argv[1], len_arg - (argv[1][len_arg - 1] == '/')); + + int len_path = strlen(dir_path); + if (!len_path) { + dir_path[0] = '/'; + dir_path[1] = '\0'; + } + + long long max_size; + str_to_ll(argv[2], &max_size); + + list_files(dir_path, len_path, max_size, 1); + + free(dir_path); + + return EXIT_SUCCESS; +} diff --git a/3sem/cnts/contest7/01-old.c b/3sem/cnts/contest7/01-old.c new file mode 100755 index 0000000..b2f7622 --- /dev/null +++ b/3sem/cnts/contest7/01-old.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + const char const_str[] = "18446744073709551616"; + + char tmp_str[PATH_MAX]; + + while (scanf("%s", tmp_str) == 1) { + int64_t res = 0; + uint64_t base = 1; + + int is_overflow = 0; + + for (int i = strlen(tmp_str) - 1; i >= 0; i--) { + char ch = tmp_str[i]; + + if (ch == 'a') { + if (__builtin_sub_overflow(res, base, &res)) { + is_overflow = 1; + + break; + } + } else if (ch == '1') { + if (__builtin_add_overflow(res, base, &res)) { + is_overflow = 1; + + break; + } + } else if (ch != '0') { + fprintf(stderr, "Invalid input\n"); + + return 1; + } + + if (__builtin_mul_overflow(base, 3, &base) && i != 0) { + is_overflow = 1; + + break; + } + } + + if (is_overflow) { + printf("%s\n", const_str); + } else { + printf("%lld\n", res); + } + } + + return 0; +} diff --git a/3sem/cnts/contest7/01-test.c b/3sem/cnts/contest7/01-test.c new file mode 100755 index 0000000..b906a5f --- /dev/null +++ b/3sem/cnts/contest7/01-test.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +enum +{ + MAX_SYM_THREE_LEN = 64, + SYS_BASE = 3, +}; + +const char ERROR_OUTPUT[] = "18446744073709551616"; + +int +main(void) +{ + int cur_num = getchar(); + while (cur_num != EOF && isspace(cur_num)) { + cur_num = getchar(); + } + long long res = 0; + bool overflow = false; + bool printed = false; + bool read = false; + while (cur_num != EOF) { + char cur_ch = cur_num; + if (isspace(cur_num)) { + if (!printed) { + if (overflow) { + printf("%s\n", ERROR_OUTPUT); + } else { + printf("%lld\n", res); + } + res = 0; + overflow = false; + printed = true; + } + } else { + read = true; + printed = false; + if (cur_ch == '1') { + long long temp = 0; + if (res < 0) { + if (__builtin_mul_overflow(res + 1, 3, &temp)) { + overflow = true; + } + if (__builtin_add_overflow(temp, 1, &res)) { + overflow = true; + } + if (__builtin_sub_overflow(res, 3, &temp)) { + overflow = true; + } + res = temp; + } else { + if (__builtin_mul_overflow(res, 3, &temp)) { + overflow = true; + } + if (__builtin_add_overflow(temp, 1, &res)) { + overflow = true; + } + } + + } else if (cur_ch == 'a') { + long long temp = 0; + if (res > 0) { + if (__builtin_mul_overflow(res - 1, 3, &temp)) { + overflow = true; + } + if (__builtin_sub_overflow(temp, 1, &res)) { + overflow = true; + } + if (__builtin_add_overflow(res, 3, &temp)) { + overflow = true; + } + res = temp; + } else { + if (__builtin_mul_overflow(res, 3, &temp)) { + overflow = true; + } + if (__builtin_sub_overflow(temp, 1, &res)) { + overflow = true; + } + } + } else if (cur_ch == '0') { + long long temp = 0; + if (__builtin_mul_overflow(res, 3, &temp)) { + overflow = true; + } + res = temp; + } + } + cur_num = getchar(); + } + if (cur_num == EOF && !printed && !overflow && read) { + printf("%lld\n", res); + } +} diff --git a/3sem/cnts/contest7/01.c b/3sem/cnts/contest7/01.c new file mode 100755 index 0000000..2218948 --- /dev/null +++ b/3sem/cnts/contest7/01.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + const char const_str[] = "18446744073709551616"; + int ch, index = 0; + int64_t res = 0; + int is_overflow = 0; + + while ((ch = getchar()) != EOF) { + if (!isspace(ch)) { + index = 1; + int64_t tmp = 0; + if (ch == 'a') { + if (res > 0) { + if (__builtin_mul_overflow(res - 1, 3, &tmp)) { + is_overflow = 1; + } + if (__builtin_sub_overflow(tmp, 1, &res)) { + is_overflow = 1; + } + if (__builtin_add_overflow(res, 3, &tmp)) { + is_overflow = 1; + } + res = tmp; + } else { + if (__builtin_mul_overflow(res, 3, &tmp)) { + is_overflow = 1; + } + if (__builtin_sub_overflow(tmp, 1, &res)) { + is_overflow = 1; + } + } + + } else if (ch == '1') { + if (res > 0) { + if (__builtin_mul_overflow(res, 3, &tmp)) { + is_overflow = 1; + } + if (__builtin_add_overflow(tmp, 1, &res)) { + is_overflow = 1; + } + } else { + if (__builtin_mul_overflow(res + 1, 3, &tmp)) { + is_overflow = 1; + } + if (__builtin_add_overflow(tmp, 1, &res)) { + is_overflow = 1; + } + if (__builtin_sub_overflow(res, 3, &tmp)) { + is_overflow = 1; + } + res = tmp; + } + } else if (ch == '0') { + if (__builtin_mul_overflow(res, 3, &res)) { + is_overflow = 1; + } + } + } else { + if (index) { + if (is_overflow) { + printf("%s\n", const_str); + } else { + printf("%lld\n", res); + } + + index = 0; + res = 0; + is_overflow = 0; + } + } + } + + if (index) { + if (is_overflow) { + printf("%s\n", const_str); + } else { + printf("%lld\n", res); + } + } + + return 0; +} diff --git a/3sem/cnts/contest7/02.c b/3sem/cnts/contest7/02.c new file mode 100755 index 0000000..18d9812 --- /dev/null +++ b/3sem/cnts/contest7/02.c @@ -0,0 +1,54 @@ +#include +#include +#include + +enum +{ + THURSDAY = 4, + YEAR_OFFSET = 1900, + LAST_DIGIT_REM = 3, + GOOD_THURSDAY1 = 2, + GOOD_THURSDAY2 = 4 +}; + +int +main(int argc, char *argv[]) +{ + int year; + if (scanf("%d", &year) != 1) { + fprintf(stderr, "Invalid input\n"); + + return 1; + } + + struct tm t = {0}; + t.tm_isdst = -1; + t.tm_mday = 1; + t.tm_year = year - YEAR_OFFSET; + + int num_of_thursdays = 0, last_month = 0; + + while (t.tm_year == year - YEAR_OFFSET) { + mktime(&t); + + if (t.tm_mon != last_month) { + last_month = t.tm_mon; + num_of_thursdays = 0; + } + + if (t.tm_wday == THURSDAY) { + num_of_thursdays++; + + if (t.tm_mday % LAST_DIGIT_REM != 0 && + (num_of_thursdays == GOOD_THURSDAY1 || num_of_thursdays == GOOD_THURSDAY2)) { + printf("%d %d\n", t.tm_mon + 1, t.tm_mday); + } + + t.tm_mday += 7; + } else { + t.tm_mday++; + } + } + + return 0; +} diff --git a/3sem/cnts/contest7/03.c b/3sem/cnts/contest7/03.c new file mode 100755 index 0000000..f311030 --- /dev/null +++ b/3sem/cnts/contest7/03.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +check_and_sum_files(const char *dir1, const char *dir2, off_t *total_size) +{ + DIR *d1 = opendir(dir1); + if (!d1) { + return; + } + + struct dirent *entry; + while ((entry = readdir(d1)) != NULL) { + char path1[PATH_MAX]; + int r = snprintf(path1, sizeof(path1), "%s/%s", dir1, entry->d_name); + if (r < 0 || r >= sizeof(path1)) { + _exit(1); + } + + struct stat st1; + if (lstat(path1, &st1) == -1 || !S_ISREG(st1.st_mode)) { + continue; + } + + if (access(path1, W_OK) == 0) { + char path2[PATH_MAX]; + r = snprintf(path2, sizeof(path2), "%s/%s", dir2, entry->d_name); + if (r < 0 || r >= sizeof(path2)) { + _exit(1); + } + + struct stat st2; + if (stat(path2, &st2) == -1) { + continue; + } + + if (S_ISREG(st2.st_mode) && st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) { + *total_size += st1.st_size; + } + } + } + + closedir(d1); +} + +int +main(int argc, char *argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + off_t total_size = 0; + check_and_sum_files(argv[1], argv[2], &total_size); + + printf("%ld\n", total_size); + + return 0; +} diff --git a/3sem/cnts/contest7/04.c b/3sem/cnts/contest7/04.c new file mode 100755 index 0000000..e69de29 diff --git a/3sem/cnts/contest7/05.c b/3sem/cnts/contest7/05.c new file mode 100755 index 0000000..4769a6a --- /dev/null +++ b/3sem/cnts/contest7/05.c @@ -0,0 +1,104 @@ +#include +#include + +enum +{ + SYNODIC_PERIOD_DAYS = 29, + SYNODIC_PERIOD_HOURS = 12, + SYNODIC_PERIOD_MINUTES = 44, + FULL_MOON_YEAR = 2021, + FULL_MOON_MONTH = 5, + FULL_MOON_DAY = 26, + FULL_MOON_HOUR = 11, + FULL_MOON_MINUTE = 14, +}; + +void +add_synodic_period(struct tm *tm) +{ + tm->tm_mday += SYNODIC_PERIOD_DAYS; + tm->tm_hour += SYNODIC_PERIOD_HOURS; + tm->tm_min += SYNODIC_PERIOD_MINUTES; + timegm(tm); +} + +void +sub_synodic_period(struct tm *tm) +{ + tm->tm_mday -= SYNODIC_PERIOD_DAYS; + tm->tm_hour -= SYNODIC_PERIOD_HOURS; + tm->tm_min -= SYNODIC_PERIOD_MINUTES; + timegm(tm); +} + +struct tm +find_full_moon_after(struct tm start) +{ + struct tm full_moon = {0}; + full_moon.tm_isdst = -1; + full_moon.tm_year = FULL_MOON_YEAR - 1900; + full_moon.tm_mon = FULL_MOON_MONTH - 1; + full_moon.tm_mday = FULL_MOON_DAY; + full_moon.tm_hour = FULL_MOON_HOUR; + full_moon.tm_min = FULL_MOON_MINUTE; + timegm(&full_moon); + + while (timegm(&full_moon) < timegm(&start)) { + add_synodic_period(&full_moon); + } + + while (timegm(&full_moon) > timegm(&start)) { + sub_synodic_period(&full_moon); + } + + add_synodic_period(&full_moon); + + return full_moon; +} + +struct tm +find_fourth_monday_after(struct tm start) +{ + struct tm date = start; + date.tm_mday++; + + int num_of_mondays = 0; + while (num_of_mondays < 4) { + timegm(&date); + + if (date.tm_wday == 1) { + num_of_mondays++; + } + + date.tm_mday++; + } + + date.tm_mday--; + + timegm(&date); + + return date; +} + +int +main() +{ + int year; + if (scanf("%d", &year) != 1) { + return 1; + } + + struct tm start = {0}; + start.tm_isdst = -1; + start.tm_year = year - 1900; + start.tm_mday = 257; + + timegm(&start); + + struct tm full_moon = find_full_moon_after(start); + struct tm event_date = find_fourth_monday_after(full_moon); + + printf("%04d-%02d-%02d\n", event_date.tm_year + 1900, event_date.tm_mon + 1, event_date.tm_mday); + + return 0; +} diff --git a/3sem/cnts/contest7/input b/3sem/cnts/contest7/input new file mode 100755 index 0000000..d2b9008 --- /dev/null +++ b/3sem/cnts/contest7/input @@ -0,0 +1,20 @@ + + + a a1 10a +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +a1 +0 +0 + 00 0 +1a1a1110011100a101aa11a01010a0a011a0a10a1 +1a1a1110011100a101aa11a01010a0a011a0a100a +a1a1aaa00aaa001a0a11aa10a0a01010aa101a001 +a1a1aaa00aaa001a0a11aa10a0a01010aa101a00a +a1a1aaa00aaa001a0a11aa10a0a01010aa101a01a +1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +1 1 + +1 +1 \ No newline at end of file diff --git a/3sem/exam/2019/1 b/3sem/exam/2019/1 new file mode 100755 index 0000000..cf68a51 --- /dev/null +++ b/3sem/exam/2019/1 @@ -0,0 +1,32 @@ +В ОЗУ 16-разрядного компьютера используется контроль целостности данных по +четности. Описать возможную структуру ячейки памяти и ее побитовое содержимое +для случая хранения в машинном слове восьмеричного числа 17735. + +64 6 +128 7 +256 8 + +2 pow 10 = 1024 +2 pow 11 = 2048 +2 pow 12 = 4096 +2 pow 13 = 8192 +2 pow 14 = 16384 + +17735 - +16384 = +01351 - +01024 = +00327 - +00256 = +00071 - +00064 = +00007 + + +0010 0010 1010 0111 + +xor all = 1 - somewhere + +всё сверху хуйня, число восьмиричное +001 111 111 011 101 +xor = 1 diff --git a/3sem/exam/2019/2 b/3sem/exam/2019/2 new file mode 100755 index 0000000..d4e8d8b --- /dev/null +++ b/3sem/exam/2019/2 @@ -0,0 +1,9 @@ +Пусть дано восьмеричное число 173357, являющееся адресом оперативной памяти, +расслоенной по 16 банкам. Банку с каким номером принадлежит заданный адрес? +001 111 011 011 101 111 + +1111 0110 1110 1111 + +4 bit + +15? diff --git a/3sem/exam/2021/1.c b/3sem/exam/2021/1.c new file mode 100755 index 0000000..abad33b --- /dev/null +++ b/3sem/exam/2021/1.c @@ -0,0 +1,21 @@ +#include + +typedef struct segment +{ + unsigned int base; + unsigned int size; +} segment; + +// 8-ми сегментная +unsigned int +VirtIntoPhys(segment *segTable, unsigned int VirtAdr) +{ + unsigned int SegNum = VirtAdr >> 29; + unsigned int offset = (VirtAdr << 3) >> 3; + + if (offset > segTable[SegNum].size) { + _exit(25); + } + + return segTable[SegNum].base + offset; +} diff --git a/3sem/exam/2021/2-wrong.c b/3sem/exam/2021/2-wrong.c new file mode 100755 index 0000000..70bc902 --- /dev/null +++ b/3sem/exam/2021/2-wrong.c @@ -0,0 +1,55 @@ +#include +#include + +// Стоит добавить проверки на успешность системных вызовов + +enum +{ + BlockSize = 16, +} + +int fds[4]; +unsigned int sizes[4]; +char **list = [ "Disk0", "Disk0", "Disk0", "Disk0" ]; + +void +Ini_Raid0(void) +{ + struct stat st; + for (int i = 0; i < 4; ++i) { + fds[i] = open(list[i], O_RDWR); + lstat(list[i], &st); + sizes[i] = st.st_size; + if (i != 0) { + sizes[i] += sizes[i - 1]; + } + } + + return; +} + +void +Read_Raid0(int num, char *buf) +{ + unsigned int byte = num * BlockSize; + int now_disk = 0; + + for (int i = 0; i < BlockSize; ++i) { + while (byte > sizes[now_disk]) { + now_disk++; + } + + if (now_disk > 3) { + _exit(1); + } + + if (now_disk != 0) { + lseek(fds[now_disk], byte - sizes[now_disk - 1]); + } else { + lseek(fds[now_disk], byte); + } + read(fds[now_disk], 1, buf + i); + } + + return; +} diff --git a/3sem/exam/2021/2.c b/3sem/exam/2021/2.c new file mode 100755 index 0000000..cec16a7 --- /dev/null +++ b/3sem/exam/2021/2.c @@ -0,0 +1,43 @@ +#include +#include + +enum +{ + BlockSize = 16, +} + +int fds[4]; +unsigned int sizes[4]; +char **list = [ "Disk0", "Disk0", "Disk0", "Disk0" ]; + +void +Ini_Raid0(void) +{ + struct stat st; + for (int i = 0; i < 4; ++i) { + fds[i] = open(list[i], O_RDWR); + lstat(list[i], &st); + sizes[i] = st.st_size / BlockSize; + if (i != 0) { + sizes[i] += sizes[i - 1]; + } + } + + return; +} + +void +Read_Raid0(int num, char *buf) +{ + int now_disk = 0; + int now_block = 0; + while (now_block != num) { + if (sizes[now_disk] + + now_disk++; + now_block++; + now_disk %= 4; + } + + return; +} diff --git a/3sem/exam/2021/3 b/3sem/exam/2021/3 new file mode 100755 index 0000000..86a7082 --- /dev/null +++ b/3sem/exam/2021/3 @@ -0,0 +1,35 @@ +Что будет выведено на экран? Прокомментировать, почему? Если возможны несколько вариантов – привести все. Предполагается, что +обращение к функции вывода на экран прорабатывает атомарно и без буферизации. Все системные вызовы прорабатывают успешно. +Подключение заголовочных файлов опущено. + +int main() { + int pid; + int fd[2]; + char c = 'a'; + pipe(fd); + + if( (pid = fork()) > 0 ) { + read(fd[0], &c, 1); + kill(pid, SIGKILL); + wait(NULL); + } else { + putchar(c); + c = 'b'; + write(fd[1], &c, 1); + c = 'c'; + } + + putchar(c); + return 0; +} + +(Вес задачи: 2 балла) + +Answer: +1) начнётся с a т.к. отец заблокируется на считывании +2) сын записал б в канал, дальше либо отец может отправить его "на убийство", либо сын проработает быстрее. У сына с +3) только после смерти сына отец выведет б + +aсб +aб + diff --git a/3sem/exam/2021/4 b/3sem/exam/2021/4 new file mode 100755 index 0000000..a1874b6 --- /dev/null +++ b/3sem/exam/2021/4 @@ -0,0 +1,42 @@ +Сколько раз система обратится к содержимому индексных дескрипторов при вызове: open("/dir1/dir2/dir3/file", O_RDONLY)? +Прокомментировать, почему? Считаем, что ни один из элементов пути к файлу не является символической ссылкой. (Вес задачи: 1 балл) + +$$ Answer: +1) система будет последовательно пробегать по каждому из каталогов. + 1) будет искать, есть ли файл в каталоге. + 2) будет проверять, является ли сам файл каталогом. + +2) сначала корень. ищем в нём dir1.<#> Первое обращение. Проверяем dir1 на каталог.<#> Второе обращение +find dir2 in dir1.<#> dir2 is dir?<#> +find dir3 in dir2.<#> dir3 is dir?<#> +find file in dir3.<#> + +=> всего нам надо 7 обращений к содержимому индексных дескрипторов + + +$$ Ответ GPT: + При вызове open("/dir1/dir2/dir3/file", O_RDONLY) система обращается к индексным дескрипторам (inode) для каждого элемента пути. + +Основные этапы: + + Корневая директория /: + Первое обращение к индексному дескриптору (inode) — система обращается к inode корневого каталога /. + + Директория dir1: + Второе обращение — система читает содержимое inode корневого каталога и ищет запись для dir1, после чего обращается к inode для dir1. + + Директория dir2: + Третье обращение — система читает inode для dir1, затем ищет в его содержимом запись о dir2 и обращается к соответствующему inode. + + Директория dir3: + Четвёртое обращение — система аналогично читает inode для dir2, находит запись для dir3 и обращается к inode для dir3. + + Файл file: + Пятое обращение — система читает inode для dir3, находит запись о файле file и обращается к inode для файла. + +Итог: + Таким образом, система обращается к содержимому индексных дескрипторов 5 раз (по количеству элементов пути /, dir1, dir2, dir3, file). + +Почему: + Каждая директория в Unix-подобных файловых системах представлена как файл каталога, содержащий список файлов и подкаталогов. + Чтобы найти нужный файл, система последовательно открывает каждый inode, пока не доберётся до конечного файла. diff --git a/3sem/exam/a.execute b/3sem/exam/a.execute new file mode 100755 index 0000000..59f0e12 --- /dev/null +++ b/3sem/exam/a.execute @@ -0,0 +1 @@ +cal \ No newline at end of file diff --git a/3sem/exam/a.out b/3sem/exam/a.out new file mode 100755 index 0000000..73ff10a Binary files /dev/null and b/3sem/exam/a.out differ diff --git a/3sem/exam/bitmas.c b/3sem/exam/bitmas.c new file mode 100755 index 0000000..df8e2f5 --- /dev/null +++ b/3sem/exam/bitmas.c @@ -0,0 +1,54 @@ +#include +#include +#include + +int +return_bit_int(int *mas, int n) +{ + unsigned int byte = mas[n / (sizeof(int) * 8)]; // (sizeof(int) * 8) == 32 + int offset = 32 - 1 - n % 32; + + return (byte & (1 << offset)) >> offset; +} + +int +return_bit_byte(unsigned char *mas, int n) +{ + unsigned int byte = mas[n / (sizeof(char) * 8)]; // (sizeof(char) * 8) == 8 + int offset = 8 - 1 - n % 8; + + return (byte & (1 << offset)) >> offset; +} + +// пусть битовый массив записан в файл. Массив - свободные блоки ФС. Вывести максимальную длину свободных блоков. + +int +main(int argc, char **argv) +{ + int fd = open(argv[1], O_RDONLY); + + int size = lseek(fd, 0, SEEK_END); + unsigned char *mas = malloc(size); + + lseek(fd, 0, 0); // SEEK_CUR == 0, SEEK_SET == 1, SEEK_END == 2 + + for (int i = 0; i < size; ++i) { + read(fd, mas + i, 1); // читаем из файла массив + } + + int max_len = 0; + int tmp = 0; // для хранения текущей длины + for (int i = 0; i < size * 8; ++i) { // пробегаем по всем битам + if (return_bit_byte(mas, i) == 1) { + tmp++; + } else { + max_len = (max_len > tmp) ? max_len : tmp; + tmp = 0; + } + } + max_len = (max_len > tmp) ? max_len : tmp; // если последний бит был 1, то надо доп проверку + + printf("%d\n", max_len); + + return 0; +} diff --git a/3sem/exam/prog-tmp.c b/3sem/exam/prog-tmp.c new file mode 100755 index 0000000..6182ba7 --- /dev/null +++ b/3sem/exam/prog-tmp.c @@ -0,0 +1,24 @@ +// на вход подаётся имя каталога. +// пробежать рекурсивно по всему каталогу и папкам в нём. Если встретился регулярный файл с именем, которое +// заканчивается на .exeсute, открыть, прочесть путь, запустить по нему прогу. + +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + DIR *d = opendir(argv[1]); + struct dirent *dd; + while ((dd = readdir(d))) { + char str[PATH_MAX]; + snprintf(str, PATH_MAX, "%s/%s", argv[1], dd->d_name); + + write(1, str, strlen(str)); + write(1, "\n", 1); + } + + return 0; +} diff --git a/3sem/exam/prog.c b/3sem/exam/prog.c new file mode 100755 index 0000000..4386f1e --- /dev/null +++ b/3sem/exam/prog.c @@ -0,0 +1,42 @@ +// на вход подаётся имя каталога. +// пробежать рекурсивно по всему каталогу и папкам в нём. Если встретился регулярный файл с именем, которое +// заканчивается на .exeсute, открыть, прочесть путь, запустить по нему прогу. + +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + DIR *d = opendir(argv[1]); + struct dirent *dd; + struct stat st; + while ((dd = readdir(d))) { + if (strcmp(dd->d_name, ".") == 0 || strcmp(dd->d_name, "..") == 0) { + continue; + } + + char str[PATH_MAX]; + snprintf(str, PATH_MAX, "%s/%s", argv[1], dd->d_name); + lstat(str, &st); + if (S_ISREG(st.st_mode) && st.st_size < strtol(argv[2], NULL, 10)) { + if (strlen(str) >= 8 && strcmp(str + strlen(str) - 8, ".execute") == 0) { + int fd = open(str, O_RDONLY); + char s[PATH_MAX + 1]; + // memset(s, 0, PATH_MAX); + s[read(fd, s, PATH_MAX)] = '\0'; + if (!fork()) { + execlp(s, s, NULL); + _exit(1); + } + close(fd); + } + } + } + + return 0; +} diff --git a/3sem/exam/raid.c b/3sem/exam/raid.c new file mode 100755 index 0000000..cec16a7 --- /dev/null +++ b/3sem/exam/raid.c @@ -0,0 +1,43 @@ +#include +#include + +enum +{ + BlockSize = 16, +} + +int fds[4]; +unsigned int sizes[4]; +char **list = [ "Disk0", "Disk0", "Disk0", "Disk0" ]; + +void +Ini_Raid0(void) +{ + struct stat st; + for (int i = 0; i < 4; ++i) { + fds[i] = open(list[i], O_RDWR); + lstat(list[i], &st); + sizes[i] = st.st_size / BlockSize; + if (i != 0) { + sizes[i] += sizes[i - 1]; + } + } + + return; +} + +void +Read_Raid0(int num, char *buf) +{ + int now_disk = 0; + int now_block = 0; + while (now_block != num) { + if (sizes[now_disk] + + now_disk++; + now_block++; + now_disk %= 4; + } + + return; +} diff --git a/3sem/exam/raid4.c b/3sem/exam/raid4.c new file mode 100755 index 0000000..aee47b0 --- /dev/null +++ b/3sem/exam/raid4.c @@ -0,0 +1,33 @@ +#include +#include + +enum +{ + BlockSize = 16, +} + +int fds[5]; +void +Write_Raid4(int num, char *buf) +{ + unsigned char tmp1[BlockSize]; + unsigned char tmp2[BlockSize]; + int num_disk = num % 4; + + lseek(fd[num_disk], num * BlockSize); + lseek(fd[4], num * BlockSize); + read(fd[num_disk], tmp1, BlockSize); + read(fd[4], tmp2, BlockSize); + + for (int i = 0; i < BlockSize; ++i) { + tmp2[i] ^= tmp1[i]; + tmp2[i] ^= buf[i]; + } + + lseek(fd[num_disk], num * BlockSize); + lseek(fd[4], num * BlockSize); + write(fd[num_disk], buf, BlockSize); + write(fd[4], tmp2, BlockSize); + + return; +} diff --git a/3sem/exam/sem2.c b/3sem/exam/sem2.c new file mode 100755 index 0000000..c5426b8 --- /dev/null +++ b/3sem/exam/sem2.c @@ -0,0 +1,24 @@ +// суть - предсказываем поведение кэша. + +#include +#include + +enum +{ + CACHE_LEN = 1024, + BLOCK_SIZE = 512, +}; + +int +main(void) +{ + unsigned addrs[CACHE_LEN]; + memset(addrs, -1, CACHE_LEN); + + unsigned addr, cnt = 0; + while (scanf("%u", &addr) == 1) { + int i = (addr / BLOCK_SIZE) % CACHE_LEN; + cnt += (addrs[i] != -1) && (addrs[i] != addr); + addrs[i] = addr; + } +} diff --git a/3sem/exam/sem3.c b/3sem/exam/sem3.c new file mode 100755 index 0000000..12a861f --- /dev/null +++ b/3sem/exam/sem3.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +struct record +{ + double dbl, int num, +} + +int +main(int argc, char **argv) +{ + int shm_key = shmget(IPC_PRIVATE, sizeof(record), IPC_CREAT | 0666); + int sem_key = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); + + record *mem = shmat(shm_key, NULL, 0); + + for (int i = 1; i < argc; ++i) { + int fd = open(argv[i], O_RDONLY); + double sum = 0; + int num = 0; + double tmp; + + while (read(fd, &tmp, sizeof(tmp)) { + num++; + sum += tmp; + } + semop(sem_key, &(struct sembuf){.sem_num = 0, .sem_op = -2}, 1); + *mem = (struct record){.dbl = sum, .num = num}; + semop(sem_key, &(struct sembuf){.sem_num = 0, .sem_op = -1}, 1); + } + + while (wait(NULL) != -1) { + } + + return 0; +} diff --git a/3sem/kr/001.c b/3sem/kr/001.c new file mode 100755 index 0000000..72c3426 --- /dev/null +++ b/3sem/kr/001.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv){ + + int id_of_shm = shmget(argv[1], sizeof(double) * 2, IPC_CREAT | 0666); + float* start_of_shm = shmat(id_of_shm, NULL, 0); + + int sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); + semctl(sem_id, 0, SETVAL, 1); + + struct sembuf p = {0, -1, 0}, v = {0,1,0}; + + + for(int i = 2; i < argc; i++){ + pid_t pid = fork(); + + if (pid == 0) { + FILE* in_file = fopen(argv[i], "r"); + float sum = 0, n = 0; + float buf; + while(fscanf(in_file, "%f", &buf) != EOF){ + sum += buf; + n++; + } + + semop(sem_id, &p, 1); + start_of_shm[1] += sum; + start_of_shm[0] += n; + semop(sem_id, &v, 1); + + fclose(in_file); + + return 0; + } + + } + + + while (wait(NULL) != -1 ){ + } + printf("%f\n", start_of_shm[1] / start_of_shm[0]); + + semctl(sem_id, 0, IPC_RMID); + shmctl(id_of_shm, IPC_RMID, NULL); + + + return 0; +} diff --git a/3sem/kr/002.c b/3sem/kr/002.c new file mode 100755 index 0000000..2fff9bb --- /dev/null +++ b/3sem/kr/002.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +volatile int counter = 0; +volatile int signals = 0; + +int fd2; + +void handler(int sig) { + ++signals; + if (signals < 3) { + printf("%d\n", counter / 2); + } else { + lseek(fd2, 0, SEEK_SET); + char buf; + while (read(fd2, &buf, 1) > 0) { + write(1, &buf, 1); + } + exit(0); + } + +} + +int main(int argc, char** argv) { + signal(SIGINT, handler); + + int fd1 = open(argv[1], O_RDONLY, 0666); + fd2 = open(argv[2], O_CREAT | O_WRONLY); + + char buf; + while (read(fd1, &buf, 1) > 0) { + if (counter % 2 == 0) { + write(fd2, &buf, 1); + } + ++counter; + } + + return 0; +} \ No newline at end of file diff --git a/3sem/kr/01.c b/3sem/kr/01.c new file mode 100755 index 0000000..dffbb9c --- /dev/null +++ b/3sem/kr/01.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int fd[2]; + pipe(fd); + + if (!fork()) { + close(fd[1]); + dup2(fd[0], 0); + execlp("wc", "wc", NULL); + _exit(1); + } + + close(fd[0]); + int file = open(argv[1], O_RDONLY); + + char test = argv[2][0]; + char buf[8]; + while (read(file, buf, 8) == 8) { + if (buf[0] != test) { + continue; + } + printf("%s\n", buf); + + write(fd[1], buf, 8); + } + close(fd[1]); + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/kr/02.c b/3sem/kr/02.c new file mode 100755 index 0000000..389fdd6 --- /dev/null +++ b/3sem/kr/02.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int file = open(argv[1], O_RDONLY); + int file_out = open("tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666); + + dup2(file, 0); + dup2(file_out, 1); + + char buf[101]; + while (fgets(buf, 100, stdin) != NULL) { + for (int i = 0; i < strlen(buf); i++) { + if (!strncmp(buf + i, "begin", 5)) { + printf("{"); + i += 4; + } else if (!strncmp(buf + i, "end", 3)) { + printf("}"); + i += 2; + } else { + printf("%c", buf[i]); + } + } + } + + rename("tmp", argv[1]); + + return 0; +} diff --git a/3sem/kr/03.c b/3sem/kr/03.c new file mode 100755 index 0000000..6a18209 --- /dev/null +++ b/3sem/kr/03.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int mas[5] = {0, 0, 0, 0, 0}; + + int num = 5, tmp; + + while (scanf("%d", &tmp) == 1) { + for (int i = 0; i < 4; i++) { + mas[i] = mas[i + 1]; + } + mas[4] = tmp; + num--; + } + + // if (num < 0) { + // num = 0; + // } + num = num < 0 ? 0 : num; + + for (int i = num; i < 5; i++) { + printf("%d ", mas[i]); + } + printf("\n"); + + return 0; +} diff --git a/3sem/kr/signal.c b/3sem/kr/signal.c new file mode 100755 index 0000000..cd6b75c --- /dev/null +++ b/3sem/kr/signal.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + + return 0; +} diff --git a/3sem/kr16/01-ai.c b/3sem/kr16/01-ai.c new file mode 100755 index 0000000..401e01d --- /dev/null +++ b/3sem/kr16/01-ai.c @@ -0,0 +1,20 @@ +#include +#include + +int +main() +{ + uint64_t num; + int free_blocks = 0; + + while (scanf("%lx", &num) != EOF) { + for (int i = 0; i < 64; i += 2) { + if (((num >> i) & 0x3) == 0x0) { + free_blocks++; + } + } + } + + printf("%d\n", free_blocks); + return 0; +} diff --git a/3sem/kr16/01.c b/3sem/kr16/01.c new file mode 100755 index 0000000..2499d4c --- /dev/null +++ b/3sem/kr16/01.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + long long unsigned int tmp, res = 0; + + while (scanf("%llu", &tmp) != EOF) { + for (int i = 0; i < sizeof(tmp) * 8; i += 2) { + if (!((tmp >> i) & 0x3)) { + res++; + } + } + } + + printf("%llu\n", res); + + return 0; +} diff --git a/3sem/kr16/02.c b/3sem/kr16/02.c new file mode 100755 index 0000000..cd315be --- /dev/null +++ b/3sem/kr16/02.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int fd[2]; + pipe(fd); + pid_t pid = fork(); + if (!pid) { + close(fd[0]); + dup2(fd[1], 1); + execlp("gpg", "gpg", "-d", "--batch", "--passphrase", argv[2], "--pinentry-mode", "loopback", "--quiet", + "--no-tty", "--no-keyring", argv[1], NULL); + _exit(1); + } else if (pid == -1) { + exit(1); + } + close(fd[1]); + wait(NULL); + + dup2(fd[0], 0); + + int tmp; + int64_t sum = 0; + while (scanf("%d", &tmp) != EOF) { + sum += tmp; + } + + printf("%ld\n", sum); + + return 0; +} diff --git a/3sem/kr16/04.c b/3sem/kr16/04.c new file mode 100755 index 0000000..85efc35 --- /dev/null +++ b/3sem/kr16/04.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include + +volatile unsigned char cell; +int fd[2]; + +void +usr_hndl(int sig) +{ + write(fd[1], &cell, 1); + kill(getppid(), SIGUSR1); + + return; +} + +void +usr_hndl1(int sig) +{ + read(fd[0], &cell, 1); + + return; +} + +int +main(int argc, char **argv) +{ + pipe(fd); + + pid_t *mas = malloc((argc - 1) * sizeof(pid_t)); + int n = argc - 1; + + int64_t size = 0; + for (int i = 1; i < argc; ++i) { + struct stat st; + lstat(argv[i], &st); + size = st.st_size; + + pid_t pid = fork(); + if (!pid) { + int file = open(argv[i], O_RDONLY); + close(fd[0]); + + signal(SIGUSR1, usr_hndl); + for (;;) { + pause(); + } + _exit(1); + } + mas[i - 1] = pid; + } + close(fd[1]); + + signal(SIGUSR1, usr_hndl1); + unsigned int adr; + while (scanf("%u", &adr) != -1) { + kill(mas[adr % n], SIGUSR1); + } + + return 0; +} diff --git a/3sem/seminars/l10/01.c b/3sem/seminars/l10/01.c new file mode 100755 index 0000000..613aa0e --- /dev/null +++ b/3sem/seminars/l10/01.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +// cmd < file1 >> file2 + +int +main(int argc, char **argv) +{ + char *file1 = argv[2]; + char *file2 = argv[3]; + char *cmd = argv[1]; + + if (!fork()) { + int fin = open(file1, O_RDONLY); + int fout = open(file2, O_WRONLY | O_APPEND | O_CREAT, 0666); + + dup2(fin, 0); + dup2(fout, 1); + + execlp(cmd, cmd, NULL); + _exit(1); + } else { + wait(NULL); + } + + return 0; +} diff --git a/3sem/seminars/l10/02.c b/3sem/seminars/l10/02.c new file mode 100755 index 0000000..068d4a7 --- /dev/null +++ b/3sem/seminars/l10/02.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +// cmd1 | cmd2 + +int +main(int argc, char **argv) +{ + char *cmd1 = argv[1]; + char *cmd2 = argv[2]; + + int fd[2]; + pipe(fd); + + if (!fork()) { + dup2(fd[1], 1); + close(fd[0]); + + execlp(cmd1, cmd1, NULL); + _exit(1); + } else if (!fork()) { + dup2(fd[0], 0); + close(fd[1]); + + execlp(cmd2, cmd2, NULL); + _exit(1); + } else { + close(fd[0]); + close(fd[1]); + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/seminars/l10/03.c b/3sem/seminars/l10/03.c new file mode 100755 index 0000000..5c1dd00 --- /dev/null +++ b/3sem/seminars/l10/03.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int n = strtoll(argv[1], NULL, 10); + + int fd1[2]; + int fd2[2]; + pipe(fd1); + pipe(fd2); + + int tmp = 1; + write(fd2[1], &tmp, sizeof(tmp)); + + if (!fork()) { + int i = 0; + close(fd1[0]); + close(fd2[1]); + + while (i < n) { + read(fd2[0], &i, sizeof(i)); + if (i > n) { + break; + } + printf("Channel %d: %d\n", 1, i); + i++; + write(fd1[1], &i, sizeof(i)); + } + + return 0; + } else if (!fork()) { + int i = 0; + close(fd2[0]); + close(fd1[1]); + + while (i < n) { + read(fd1[0], &i, sizeof(i)); + if (i > n) { + break; + } + printf("Channel %d: %d\n", 2, i); + i++; + write(fd2[1], &i, sizeof(i)); + } + + return 0; + } else { + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd2[1]); + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/seminars/l11/01-2.c b/3sem/seminars/l11/01-2.c new file mode 100755 index 0000000..02bd4b2 --- /dev/null +++ b/3sem/seminars/l11/01-2.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + key_t key = ftok("/dev/null", 0); + + int semid = semget(key, 2, 0666 | IPC_CREAT); + int shmid = shmget(key, sizeof(int), 0666 | IPC_CREAT); + + int *shm = shmat(shmid, NULL, 0); + + pid_t pid = fork(); + if (!pid) { + while (scanf("%d", shm) != -1) { + semop(semid, &(struct sembuf){.sem_num = 0, .sem_op = 1}, 1); + + semop(semid, &(struct sembuf){.sem_num = 1, .sem_op = -1}, 1); + } + + semctl(semid, 2, IPC_RMID, NULL); + exit(0); + } else if (pid == -1) { + exit(1); + } + + pid = fork(); + if (!pid) { + for (;;) { + if (semop(semid, &(struct sembuf){.sem_num = 0, .sem_op = -1}, 1) == -1) { + break; + } + + printf("$ %d\n", *shm); + + if (semop(semid, &(struct sembuf){.sem_num = 1, .sem_op = 1}, 1) == -1) { + break; + } + } + exit(0); + } else if (pid == -1) { + exit(1); + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/seminars/l11/01.c b/3sem/seminars/l11/01.c new file mode 100755 index 0000000..2ec3b6d --- /dev/null +++ b/3sem/seminars/l11/01.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + key_t key = ftok("/dev/null", 0); + + int semid = semget(key, 2, 0666 | IPC_CREAT); + int shmid = shmget(key, sizeof(int), 0666 | IPC_CREAT); + + int *shm = shmat(shmid, NULL, 0); + semctl(semid, 0, SETVAL, 1); + semctl(semid, 1, SETVAL, 1); + + pid_t pid = fork(); + if (!pid) { + for (;;) { + semop(semid, &(struct sembuf){.sem_num = 0, .sem_op = -1}, 1); + semop(semid, &(struct sembuf){.sem_num = 1, .sem_op = -1}, 1); + + int r = scanf("%d", shm); + if (r == -1) { + break; + } + semop(semid, &(struct sembuf){.sem_num = 0, .sem_op = 1}, 1); + } + semctl(semid, 2, IPC_RMID, NULL); + exit(0); + } else if (pid == -1) { + exit(1); + } + + pid = fork(); + if (!pid) { + for (;;) { + if (semop(semid, &(struct sembuf){.sem_num = 0, .sem_op = -1}, 1) == -1) { + break; + } + + printf("$ %d\n", *shm); + if (semop(semid, &(struct sembuf){.sem_num = 0, .sem_op = 1}, 1) == -1) { + break; + } + if (semop(semid, &(struct sembuf){.sem_num = 1, .sem_op = 1}, 1) == -1) { + break; + } + } + exit(0); + } else if (pid == -1) { + exit(1); + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/seminars/l11/02.c b/3sem/seminars/l11/02.c new file mode 100755 index 0000000..d017dfd --- /dev/null +++ b/3sem/seminars/l11/02.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// пинг понг для n процессов + +int +main(int argc, char **argv) +{ + int n = (int) strtoll(argv[1], NULL, 10); + int max_n = (int) strtoll(argv[2], NULL, 10); + + for (int i = 0; i < n; ++i) { + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/seminars/l3/01.c b/3sem/seminars/l3/01.c new file mode 100755 index 0000000..56bb5b5 --- /dev/null +++ b/3sem/seminars/l3/01.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + + char *fin = argv[1]; + char *fout = argv[2]; + + // printf("fdin: %d\n", fin); + + int fdin = open(fin, O_RDONLY); + if (fdin == -1) { + return 1; + } + + int fdout = open(fout, O_WRONLY | O_CREAT | O_TRUNC, 0777); + for (;;) { + char c[1024]; + int r = read(fdin, c, 1024); + if (r == -1) { + return 1; + } + if (r == 0) { + break; + } + write(fdout, c, r); + } + + close(fdin); + close(fdout); + + return 0; +} diff --git a/3sem/seminars/l3/02.c b/3sem/seminars/l3/02.c new file mode 100755 index 0000000..4b7e5df --- /dev/null +++ b/3sem/seminars/l3/02.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int fdin = open("in", O_RDWR); + if (fdin == -1) { + return 1; + } + + double num1, num2; + + // Read the first double + if (read(fdin, &num1, sizeof(double)) != sizeof(double)) { + close(fdin); + return 1; + } + + // Read the second double + if (read(fdin, &num2, sizeof(double)) != sizeof(double)) { + close(fdin); + return 1; + } + + // Move the file pointer back to the beginning + if (lseek(fdin, 0, SEEK_SET) == -1) { + close(fdin); + return 1; + } + + // Write the second double first + if (write(fdin, &num2, sizeof(double)) != sizeof(double)) { + close(fdin); + return 1; + } + + // Write the first double second + if (write(fdin, &num1, sizeof(double)) != sizeof(double)) { + close(fdin); + return 1; + } + + close(fdin); + + return 0; +} diff --git a/3sem/seminars/l3/03.с b/3sem/seminars/l3/03.с new file mode 100755 index 0000000..f74e7bf --- /dev/null +++ b/3sem/seminars/l3/03.с @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + int fdout = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fdout == -1) { + return 1; + } + + unsigned short x; + + while (scanf("%hu", &x) == 1) { + unsigned char buf[2]; + buf[0] = x >> 8; + buf[1] = x & 0xff; + write(fdout, &x, 2); + } + + close(fdout); + + return 0; +} \ No newline at end of file diff --git a/3sem/seminars/l3/04.c b/3sem/seminars/l3/04.c new file mode 100755 index 0000000..18b4053 --- /dev/null +++ b/3sem/seminars/l3/04.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int fdin = open(argv[1], O_RDONLY); + if (fdin == -1) { + return 1; + } + + unsigned int res = 0, tmp; + unsigned char num[4]; // не пишем в int, т.к. неизвестно, какой порядок байтов + + while (read(fdin, num, 4) == 4) { + // unsigned int tmp = (unsigned int) num << 24 | (unsigned int) num << + // 16 | + // (unsigned int) num << 8 | (unsigned int) num; + for (int i = 0; i < 4; i++) { + tmp = tmp << 8 | num[i]; + } + res += tmp; + } + + printf("%u\n", res); + + close(fdin); + + return 0; +} diff --git a/3sem/seminars/l3/in b/3sem/seminars/l3/in new file mode 100755 index 0000000..f5b833a Binary files /dev/null and b/3sem/seminars/l3/in differ diff --git a/3sem/seminars/l3/out b/3sem/seminars/l3/out new file mode 100755 index 0000000..81bb6ee --- /dev/null +++ b/3sem/seminars/l3/out @@ -0,0 +1 @@ +123 234 \ No newline at end of file diff --git a/3sem/seminars/l4/01.c b/3sem/seminars/l4/01.c new file mode 100755 index 0000000..e41445f --- /dev/null +++ b/3sem/seminars/l4/01.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include + +void +premission_to_char(char *m, int n, mode_t mode) +{ + for (int i = 0; i < n; ++i) { + if (!(mode & 1)) { + m[n - i - 1] = '-'; + } + mode >>= 1; + } +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + + for (int i = 1; i < argc; i++) { + if (lstat(argv[i], &st) < 0) { + continue; + } + + char type; + if (S_ISREG(st.st_mode)) { + type = '-'; + } else if (S_ISDIR(st.st_mode)) { + type = 'd'; + } else if (S_ISLNK(st.st_mode)) { + type = 'l'; + } else { + type = '?'; + } + + char m[] = "rwxrwxrwx"; + for (int j = 0; j < 9; j++) { + if (!((st.st_mode >> j) & 1)) { + m[8 - j] = '-'; + } + } + + printf("%c%s %lu %hu %lu %ld %s\n", type, m, st.st_nlink, st.st_uid, st.st_size, st.st_ctime, argv[i]); + } + return 0; +} diff --git a/3sem/seminars/l4/02.c b/3sem/seminars/l4/02.c new file mode 100755 index 0000000..244ff34 --- /dev/null +++ b/3sem/seminars/l4/02.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include + +int +acs(const char *name, int mode) +{ + struct stat st; + + if (lstat(name, &st) < 0) { + return -1; + } + uid_t uid = getuid(); + if (uid == 0) { + return 0; + } + + uid_t st_mode = st.st_mode; + if (st.st_mode == uid) { + st_mode >>= 6; + } else if (st.st_gid == getgid()) { + st_mode >>= 3; + } + st_mode &= 7; + + // for (int i = 0; i < 3; ++i) { + // if (st_mode ^ mode & 1) { + // return -1; + // } + // st_mode >>= 1; + // mode >>= 1; + // } + + if (st_mode & mode == mode) { + return 0; + } + + return -1; +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + + for (int i = 1; i < argc; i++) { + if (lstat(argv[i], &st) < 0) { + continue; + } + + char type; + if (S_ISREG(st.st_mode)) { + type = '-'; + } else if (S_ISDIR(st.st_mode)) { + type = 'd'; + } else if (S_ISLNK(st.st_mode)) { + type = 'l'; + } else { + type = '?'; + } + + char m[] = "rwxrwxrwx"; + for (int j = 0; j < 9; j++) { + if (!((st.st_mode >> j) & 1)) { + m[8 - j] = '-'; + } + } + + printf("%c%s %lu %hu %lu %ld %s\n", type, m, st.st_nlink, st.st_uid, st.st_size, st.st_ctime, argv[i]); + } + return 0; +} diff --git a/3sem/seminars/l4/03.c b/3sem/seminars/l4/03.c new file mode 100755 index 0000000..d93f743 --- /dev/null +++ b/3sem/seminars/l4/03.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + struct stat st; + + if (lstat(argv[1], &st) < 0) { + exit(1); + } + + if (S_ISDIR(st.st_mode)) { + char *file = calloc(strlen(argv[1]) + 30, sizeof(char)); + + snprintf(file, strlen(argv[1]) + 30, "%s/%s.uid", argv[1], argv[0]); + + sprintf(file, "%s/%s.uid", argv[1], argv[0]); + + int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC); + uid_t uid = getuid(); + write(fd, &uid, sizeof(uid_t)); + + close(fd); + } else if (S_ISREG(st.st_mode)) { + int fd = open(argv[1], O_WRONLY | O_TRUNC); + write(fd, st.st_uid, sizeof(uid_t)); + + close(fd); + } else { + exit(1); + } +} diff --git a/3sem/seminars/l5/01.c b/3sem/seminars/l5/01.c new file mode 100755 index 0000000..cbdbe5f --- /dev/null +++ b/3sem/seminars/l5/01.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + DIR *dir = opendir(argv[1]); + unsigned long long sum = 0; + struct dirent *de; + while (de = readdir(dir)) { + char *name = calloc(PATH_MAX, sizeof(char)); + snprintf(name, PATH_MAX, "%s/%s", argv[1], de->d_name); + + struct stat st; + if (lstat(name, &st) < 0) { + continue; + } + if (S_ISREG(st.st_mode)) { + sum += st.st_size; + } + } + + closedir(dir); + + printf("%d\n", sum); + + return 0; +} diff --git a/3sem/seminars/l5/02.c b/3sem/seminars/l5/02.c new file mode 100755 index 0000000..d2ccdbc --- /dev/null +++ b/3sem/seminars/l5/02.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + DIR *dir = opendir(argv[1]); + struct dirent *de; + while (de = readdir(dir)) { + char *name = calloc(PATH_MAX, sizeof(char)); + snprintf(name, PATH_MAX, "%s/%s", argv[1], de->d_name); + + struct stat st; + if (lstat(name, &st) < 0) { + continue; + } + if (!(S_ISREG(st.st_mode))) { + continue; + } + + if (access(name, 3)) { + continue; + } + int len = strlen(name); + + if (name[len - 1] == '~' || (len >= 4 && strcmp(name + strlen(name) - 4, ".bak") == 0)) { + unlink(name); + } + } + + closedir(dir); + return 0; +} diff --git a/3sem/seminars/l5/03.c b/3sem/seminars/l5/03.c new file mode 100755 index 0000000..b966b78 --- /dev/null +++ b/3sem/seminars/l5/03.c @@ -0,0 +1,66 @@ +// подкаталог пустой +// совпадают айдишники +// есть права у остальных на запись +// rmdir + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + DIR *dir = opendir(argv[1]); + struct dirent *de; + while (de = readdir(dir)) { + if ((de->d_name[0] == '.' && strlen(de->d_name) == 1) || + (strlen(de->d_name) == 2) && !strcmp(de->d_name, "..")) { + continue; + } + char *name = calloc(PATH_MAX, sizeof(char)); + snprintf(name, PATH_MAX, "%s/%s", argv[1], de->d_name); + + struct stat st; + if (lstat(name, &st) < 0) { + continue; + } + if (!(S_ISDIR(st.st_mode))) { + continue; + } + + if (st.st_uid != getuid()) { + continue; + } + + if (!(st.st_mode & 2)) { + continue; + } + + int num_files = 0; + DIR *dirt = opendir(name); + while (readdir(dirt)) { + num_files++; + if (num_files > 2) { + break; + } + } + + if (num_files > 2) { + continue; + } + + closedir(dirt); + rmdir(name); + } + + closedir(dir); + return 0; +} diff --git a/3sem/seminars/l6/01.c b/3sem/seminars/l6/01.c new file mode 100755 index 0000000..05e4753 --- /dev/null +++ b/3sem/seminars/l6/01.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Files +{ + char *pathname; + __ino_t st_ino; + __dev_t st_dev; +}; + +int +main(int argc, char **argv) +{ + struct stat st; + if (lstat(".", &st) == -1) { + printf("stat error\n"); + return 1; + } + + DIR *dir = opendir(".."); + struct dirent *de; + while ((de = readdir(dir))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { + continue; + } + + struct stat sttmp; + + char buf[PATH_MAX]; + snprintf(buf, PATH_MAX, "%s/%s", "..", de->d_name); + if (lstat(buf, &sttmp) == -1) { + printf("lstat error\n"); + return 1; + } + printf("%s\n", de->d_name); + if (sttmp.st_dev == st.st_dev && sttmp.st_ino == st.st_ino) { + printf("%s\n", de->d_name); + } + } + + return 0; +} diff --git a/3sem/seminars/l6/02.c b/3sem/seminars/l6/02.c new file mode 100755 index 0000000..1d73378 --- /dev/null +++ b/3sem/seminars/l6/02.c @@ -0,0 +1,33 @@ +#include +#include + +void +f(int *y, int *m, int *d, int offset) +{ // offset in seconds + struct tm t = {0}; + // struct tm* tptr = calloc(1, sizeof(struct tm)); + t.tm_isdst = -1; + t.tm_year = *y - 1900; + t.tm_mon = *m - 1; + t.tm_mday = *d; + time_t time = mktime(&t); + time += offset; + localtime_r(&time, &t); + *y = t.tm_year + 1900; + *m = t.tm_mon + 1; + *d = t.tm_mday; + + return; +} + +int +main(void) +{ + int y = 2021; + int m = 1; + int d = 1; + f(&y, &m, &d, 65 * 60 * 60 * 24); + printf("%d-%d-%d\n", y, m, d); + + return 0; +} diff --git a/3sem/seminars/l6/03.c b/3sem/seminars/l6/03.c new file mode 100755 index 0000000..9adadcd --- /dev/null +++ b/3sem/seminars/l6/03.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +main(int argc, char **argv) +{ + long long year, day, dw, res = 0; + str_to_ll(argv[1], &year); + str_to_ll(argv[2], &day); + str_to_ll(argv[3], &dw); + + struct tm t = {0}; + t.tm_isdst = -1; + t.tm_mday = 1; + t.tm_year = year - 1900; + + while (t.tm_year == year - 1900) { + mktime(&t); + if (t.tm_mday == day && dw == t.tm_wday) { + res++; + } + t.tm_mday++; + } + + printf("%d\n", (int) res); + + return 0; +} diff --git a/3sem/seminars/l6/04.c b/3sem/seminars/l6/04.c new file mode 100755 index 0000000..045a289 --- /dev/null +++ b/3sem/seminars/l6/04.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +main(int argc, char **argv) +{ + long long year, mth, res = 0; + str_to_ll(argv[1], &year); + str_to_ll(argv[2], &mth); + + struct tm t = {0}; + t.tm_isdst = -1; + t.tm_mday = 1; + t.tm_mon = mth - 1; + t.tm_year = year - 1900; + + while (t.tm_mon == mth - 1) { + if (t.tm_wday > 0 && t.tm_wday < 5) { + res += 8; + } else if (t.tm_wday == 5) { + res += 6; + } + t.tm_mday++; + mktime(&t); + } + + printf("%d\n", (int) res); + + return 0; +} diff --git a/3sem/seminars/l7/01.c b/3sem/seminars/l7/01.c new file mode 100755 index 0000000..f62b1d1 --- /dev/null +++ b/3sem/seminars/l7/01.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int fd = open(argv[1], O_RDWR | O_CREAT, 0666); + + struct stat st; + lseek(fd, 0, SEEK_END); + stat(argv[1], &st); + char *addr = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + for (int i = 0; i < st.st_size / 2; i++) { + char tmp = addr[i]; + addr[i] = addr[st.st_size - i - 1]; + addr[st.st_size - i - 1] = tmp; + } + + close(fd); + munmap(addr, st.st_size); + + return 0; +} diff --git a/3sem/seminars/l7/02.c b/3sem/seminars/l7/02.c new file mode 100755 index 0000000..2db52c7 --- /dev/null +++ b/3sem/seminars/l7/02.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int fdin = open(argv[1], O_RDONLY); + int fdout = open(argv[2], O_RDWR | O_CREAT, 0666); + + off_t len = lseek(fdin, 0, SEEK_END); + char *fin = mmap(NULL, len, PROT_READ, MAP_SHARED, fdin, 0); + + ftruncate(fdout, len); + char *fout = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0); + + memcpy(fout, fin, len); + + close(fdin); + close(fdout); + munmap(fin, len); + munmap(fout, len); + + return 0; +} diff --git a/3sem/seminars/l8/01-1.c b/3sem/seminars/l8/01-1.c new file mode 100755 index 0000000..979a868 --- /dev/null +++ b/3sem/seminars/l8/01-1.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + long long deepth; + str_to_ll(argv[1], &deepth); + + // long long i = 1; + + // while (deepth > 0) { + // printf("Deepth: %lld\n", i++); + + // if (deepth == 1) { + // break; + // } + + // if (!fork()) { + // deepth--; + // } else { + // wait(NULL); + + // break; + // } + // } + + for (int i = 1; i <= deepth; i++) { + if (i == deepth || fork() > 0) { + wait(NULL); + printf("Deepth: %d\n", i); + + break; + } + } + + return 0; +} diff --git a/3sem/seminars/l8/01.c b/3sem/seminars/l8/01.c new file mode 100755 index 0000000..828b869 --- /dev/null +++ b/3sem/seminars/l8/01.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +void +make_proc(int deepth, int max_deepth) +{ + if (deepth == max_deepth) { + return; + } + + printf("Deepth: %d\n", deepth); + + pid_t pid = fork(); + if (pid < 0) { + fprintf(stderr, "Fork failed\n"); + exit(1); + } else if (pid == 0) { + make_proc(deepth + 1, max_deepth); + exit(0); + } else { + wait(NULL); + } + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + long long deepth; + str_to_ll(argv[1], &deepth); + make_proc(0, deepth); + + return 0; +} diff --git a/3sem/seminars/l8/02.c b/3sem/seminars/l8/02.c new file mode 100755 index 0000000..6d4157f --- /dev/null +++ b/3sem/seminars/l8/02.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + long long deepth; + str_to_ll(argv[1], &deepth); + + for (int i = 1; i <= deepth; i++) { + if (fork() == 0) { + int fd = open(argv[2], O_CREAT | O_WRONLY, 0666); + + lseek(fd, (deepth - i) * sizeof(int), SEEK_SET); + write(fd, &i, sizeof(int)); + + close(fd); + + return 0; + } + } + + return 0; +} diff --git a/3sem/seminars/l8/03.c b/3sem/seminars/l8/03.c new file mode 100755 index 0000000..ee7da25 --- /dev/null +++ b/3sem/seminars/l8/03.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + long long deepth; + str_to_ll(argv[1], &deepth); + + truncate(argv[2], sizeof(int) * deepth); + int fd = open(argv[2], O_CREAT | O_RDWR, 0666); + int *addr = mmap(NULL, sizeof(int) * deepth, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + for (int i = 1; i <= deepth; i++) { + if (fork() == 0) { + addr[deepth - i] = i; + + return 0; + } + } + + // for (int i = 1; i <= deepth; i++) { + // wait(NULL); + // } + + while (wait(NULL) != -1) + ; + + munmap(addr, sizeof(int) * argc); + + return 0; +} diff --git a/3sem/seminars/l9/01.c b/3sem/seminars/l9/01.c new file mode 100755 index 0000000..b6c3503 --- /dev/null +++ b/3sem/seminars/l9/01.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +int +main(int argc, char *argv[]) +{ + for (int i = 0; i < 3; ++i) { + pid_t pid = fork(); + + if (pid == -1) { + return 1; + } + if (pid == 0) { + char buf[8] = {0}; + read(0, buf, 7); + + // long long t; + // str_to_ll(buf, &t); + + int t = (int) strtol(buf, NULL, 10); + + printf("%d\n", t * t); + return 0; + } else { + continue; + } + } + + while (wait(NULL) != -1) + ; + + return 0; +} diff --git a/3sem/seminars/l9/02.c b/3sem/seminars/l9/02.c new file mode 100755 index 0000000..46ba3c8 --- /dev/null +++ b/3sem/seminars/l9/02.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include + +// 8-ми сегментная таблица сегментов +// 32-х разрядная система + +typedef struct +{ + int size; + int base; +} segment; + +unsigned int +f(segment *segtable, unsigned int VAdr) +{ + int bit = 3; + unsigned int segnum = VAdr >> (32 - bit); + unsigned int segoff = VAdr & ((1 << (32 - bit)) - 1); + + int addr = segtable[segnum].base + segoff; + int size = segtable[segnum].size; + + if (segoff >= size) { + return 25; + // exit(1); + } + + return addr; +} + +int +main(int argc, char *argv[]) +{ + segment segtable[8] = {}; + + return 0; +} diff --git a/3sem/seminars/l9/03.c b/3sem/seminars/l9/03.c new file mode 100755 index 0000000..94cac4e --- /dev/null +++ b/3sem/seminars/l9/03.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include + +// инвертированная сегментная таблица сегментов +// 32-х разрядная система + +typedef struct +{ + pid_t pid; + unsigned int VirtNum; +} page_record; + +unsigned int +f(page_record *pagetable, unsigned int VAdr, int size_segtable) +{ + pid_t pid = getpid(); + + unsigned int pagenum = VAdr >> (12); // 12 - размер страницы + + for (int i = 0; i < size_segtable; i++) { + if (pagetable[i].VirtNum == pagenum && pagetable[i].pid == pid) { + return i << (32 - 12) + (VAdr << 20 >> 20); + } + } + + return -1; +} + +int +main(int argc, char *argv[]) +{ + return 0; +} diff --git a/3sem/seminars/l9/04.c b/3sem/seminars/l9/04.c new file mode 100755 index 0000000..2dcc4e9 --- /dev/null +++ b/3sem/seminars/l9/04.c @@ -0,0 +1,16 @@ + +// по номеру начального размер блока и указатель на таблицу файлов +// вывести размер файла + +unsigned int +f(unsigned int n, unsigned int *table) +{ + unsigned int size = 0; + int first_block = table[n]; + while (first_block) { + size++; // размер блока + first_block = table[first_block]; + } + + return size; +} diff --git a/3sem/seminars/l9/in_01 b/3sem/seminars/l9/in_01 new file mode 100755 index 0000000..b453c1e --- /dev/null +++ b/3sem/seminars/l9/in_01 @@ -0,0 +1,3 @@ +000007 +000010 +000009 diff --git a/3sem/templates.c b/3sem/templates.c new file mode 100755 index 0000000..1841bb2 --- /dev/null +++ b/3sem/templates.c @@ -0,0 +1,171 @@ +/** + * @file templates.c + * @brief This file contains various template functions and includes necessary headers for file operations, memory + * management, mathematical computations, and system calls. + * + * The following libraries are included: + * - stdio.h: Provides functionalities for file operations such as fopen, fclose, fprintf, fscanf, printf, and scanf. + * - stdlib.h: Provides functionalities for memory management, conversions, and other utility functions such as exit, + * malloc, free, atoi, strtol, strtoul, atof, strtod, abs, labs, llabs, div, ldiv, and lldiv. + * - fcntl.h: Provides file control options such as O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, + * O_NONBLOCK, O_SYNC, O_DSYNC, O_RSYNC, O_FSYNC, O_ASYNC, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, O_NOCTTY, O_TMPFILE, + * O_DIRECT, O_LARGEFILE, O_NOATIME, O_PATH, and O_NDELAY. + * - unistd.h: Provides access to the POSIX operating system API. + * - sys/file.h: Provides file control options. + * - sys/types.h: Defines data types used in system calls such as mode_t, off_t, pid_t, uid_t, gid_t, dev_t, ino_t, + * nlink_t, blksize_t, blkcnt_t, fsblkcnt_t, and fsfilcnt_t. + * - sys/stat.h: Defines the structure of the data returned by the functions fstat(), lstat(), and stat(). + * - limits.h: Defines the sizes of basic types. + * - errno.h: Defines macros for reporting and retrieving error conditions through error codes. + * - stdint.h: Provides a set of typedefs that specify exact-width integer types. + * - math.h: Provides mathematical functions. + * - dirent.h: Defines the format of directory entries. + * - string.h: Provides string handling functions. + * + * The following functions are implemented: + * - void safe_read(int fd, void *buf, size_t count): Reads data from a file descriptor safely, handling interruptions + * and errors. + * - void safe_write(int fd, void *buf, size_t count): Writes data to a file descriptor safely, handling interruptions + * and errors. + * - void str_to_ll(char *str, long long *num): Converts a string to a long long integer, handling errors. + * - void endian_swap(void *src, void *dst, size_t size): Swaps the endianness of a block of memory. + * + * The main function: + * - int main(int argc, char *argv[]): Template main function that checks the number of arguments, opens input and + * output files, and closes them. + */ + +#include // Standard I/O functions +#include // Standard library functions: memory allocation, process control, conversions, etc. +#include // File control options +#include // POSIX API: read, write, close, etc. +#include // File control options +#include // Data types used in system calls +#include // Data returned by the functions fstat(), lstat(), and stat() +#include // Sizes of basic types +#include // Error reporting macros +#include // Exact-width integer types +#include // Mathematical functions +#include // Directory entry format +#include // String handling functions +#include // Data returned by the functions fstat(), lstat(), and stat() + +// Function declarations +int safe_read(int fd, void *buf, size_t count); // Reads data from a file descriptor safely +int safe_write(int fd, void *buf, size_t count); // Writes data to a file descriptor safely +void str_to_ll(char *str, long long *num); // Converts a string to a long long integer +void endian_swap(void *src, void *dst, size_t size); // Swaps the endianness of a block of memory + +int +safe_read(int fd, void *buf, size_t count) +{ + errno = 0; + size_t bytes_read = 0; + while (bytes_read < count) { + ssize_t res = read(fd, buf + bytes_read, count - bytes_read); + + if (res < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + + fprintf(stderr, "Error reading from file descriptor %d\n", fd); + close(fd); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + if (res == 0) { + break; + } + + bytes_read += res; + } + + return bytes_read; +} + +int +safe_write(int fd, void *buf, size_t count) +{ + errno = 0; + size_t bytes_written = 0; + while (bytes_written < count) { + ssize_t res = write(fd, buf + bytes_written, count - bytes_written); + + if (res < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + + fprintf(stderr, "Error writing to file descriptor %d\n", fd); + close(fd); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + bytes_written += res; + } + + return bytes_written; +} + +void +str_to_ll(char *str, long long *num) +{ + errno = 0; + char *endptr; + *num = strtoll(str, &endptr, 10); + + if (*endptr || errno || endptr == str) { + fprintf(stderr, "Invalid number: %s\n", str); + exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок + } + + return; +} + +void +endian_swap(void *src, void *dst, size_t size) +{ + for (size_t i = 0; i < size; i++) { + ((char *) dst)[i] = ((char *) src)[size - i - 1]; + } + + return; +} + +// template main function +enum +{ + ARGS_NUM = 4, +}; + +int +main(int argc, char *argv[]) +{ + if (argc != ARGS_NUM) { + fprintf(stderr, "Wrong number of arguments\n"); + return 1; + } + + int fdin = open(argv[1], O_RDONLY); + if (fdin == -1) { + fprintf(stderr, "Error opening file %s\n", argv[1]); + + return 1; + } + + int fdout = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fdout == -1) { + fprintf(stderr, "Error opening file %s\n", argv[2]); + close(fdin); + + return 1; + } + + close(fdin); + close(fdout); + + return 0; +} diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..0a67b30 --- /dev/null +++ b/compile.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Check if the correct number of arguments are provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +CPP_FILE=$1 +ARGUMENT=$2 + +# Format the C++ file with clang-format +clang-format -i -style=file "$CPP_FILE" + +# Compile the C++ file +g++ "$CPP_FILE" -o run + +# Check if the compilation was successful +if [ $? -ne 0 ]; then + echo "Compilation failed" + exit 1 +fi + +# Run the compiled program with the provided argument +./run "$ARGUMENT" \ No newline at end of file diff --git a/contests/1contest/1.cpp b/contests/1contest/1.cpp new file mode 100644 index 0000000..896778b --- /dev/null +++ b/contests/1contest/1.cpp @@ -0,0 +1,14 @@ +class Sum +{ +private: + int a, b; + +public: + int + get() const { + return a + b; + } + + Sum(int a, int b) : a(a), b(b) {}; + Sum(Sum sum, int b) : a(sum.get()), b(b) {}; +}; diff --git a/contests/1contest/2.cpp b/contests/1contest/2.cpp new file mode 100755 index 0000000..1d3a446 --- /dev/null +++ b/contests/1contest/2.cpp @@ -0,0 +1,27 @@ +#include + +class A { +private: + int x; + bool to_print; +public: + A() { + x = 0; + to_print = false; + } + + A(const A& a) { + std::cin >> x; + int t; + std::cin >> t; + x += t; + to_print = true; + } + + ~A() { + if (to_print) { + std::cout << x << std::endl; + } + } + +}; \ No newline at end of file diff --git a/contests/1contest/3.cpp b/contests/1contest/3.cpp new file mode 100755 index 0000000..9f5ee07 --- /dev/null +++ b/contests/1contest/3.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +int main() { + int c; + c = getchar(); + + bool is_num = false; + + while (c != EOF) { + if (c == '0' && !is_num) { + int old = c; + c = getchar(); + + if (!(c == EOF || !isdigit(c))) { + continue; + } + + putchar(old); + } else if (isdigit(c)) { + is_num = true; + } else { + is_num = false; + } + + putchar(c); + c = getchar(); + } + + if (c != '\n') { + putchar('\n'); + } + + return 0; +} \ No newline at end of file diff --git a/contests/1contest/4 copy.cpp b/contests/1contest/4 copy.cpp new file mode 100755 index 0000000..07082b4 --- /dev/null +++ b/contests/1contest/4 copy.cpp @@ -0,0 +1,33 @@ +#include + +int main() { + int x1_1, y1_1, x1_2, y1_2; + int x2_1, y2_1, x2_2, y2_2; + std::cin >> x1_1 >> y1_1 >> x1_2 >> y1_2; + std::cin >> x2_1 >> y2_1 >> x2_2 >> y2_2; + + double k1, k2; + k1 = static_cast(y1_2 - y1_1) / (x1_2 - x1_1); + k2 = static_cast(y2_2 - y2_1) / (x2_2 - x2_1); + + if (k1 == k2) { + if (y1_1 - k1 * x1_1 == y2_1 - k2 * x2_1) { + std::cout << 2 << std::endl; + } else { + std::cout << 0 << std::endl; + } + + return 0; + } + + double b1 = y1_1 - k1 * x1_1; + double b2 = y2_1 - k2 * x2_1; + + double x_intersect = (b2 - b1) / (k1 - k2); + double y_intersect = k1 * x_intersect + b1; + + std::cout.precision(6); + std::cout << std::fixed << x_intersect << " " << y_intersect << std::endl; + + return 0; +} \ No newline at end of file diff --git a/contests/1contest/4.cpp b/contests/1contest/4.cpp new file mode 100755 index 0000000..60e960e --- /dev/null +++ b/contests/1contest/4.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +int main() { + double tmp, arip = 0, squar = 0; + int n = 0; + while (std::cin >> tmp) { + ++n; + arip += (tmp - arip) / n; + squar += (tmp * tmp - squar) / n; + } + + std::cout << std::setprecision(10); + + std::cout << arip << std::endl << std::sqrt(squar - arip * arip) << std::endl; + + return 0; +} \ No newline at end of file diff --git a/contests/2contest/1.cpp b/contests/2contest/1.cpp new file mode 100644 index 0000000..defab24 --- /dev/null +++ b/contests/2contest/1.cpp @@ -0,0 +1,12 @@ +class C { +public: + static const char c; + static void f() {}; +}; + +// const char C::c = '+'; +// int main() { +// C ob; +// C::f(); +// return 0; +// } \ No newline at end of file diff --git a/contests/2contest/2.cpp b/contests/2contest/2.cpp new file mode 100644 index 0000000..74041e0 --- /dev/null +++ b/contests/2contest/2.cpp @@ -0,0 +1,42 @@ +class C +{ + int x; +public: + C() { x = 0; } + C(double tmp) { x = 0; } + C(int tmp) { x = tmp; } + C(const C o1, const C o2) { x = o1.x + o2.x; } + C(const C* o) {} + friend C + operator+(const C& o1, const C& o2) { + return C(o1.x + o2.x); + } + C + operator++() { + return C(++x); + } + int operator~() const { return ~x; } + int + operator*(const C* obj2) { + return 0; + } +}; + +/* +C +func1(const C& v1, int v2) { + return C(v2 + v1, ~v1); +} + +void +func2(const C* p1, double p2) { + C v1 = p2; + C v2[2][2]; + C v3 = func1(func1(func1(&p1[3], p2), ~p1[2]), ++v1 * v2[1]); +} + +int +main() { + return 0; +} +*/ \ No newline at end of file diff --git a/contests/2contest/4.cpp b/contests/2contest/4.cpp new file mode 100644 index 0000000..0f51e31 --- /dev/null +++ b/contests/2contest/4.cpp @@ -0,0 +1,28 @@ +#include +using namespace std; + +class BinaryNumber +{ + string str; +public: + BinaryNumber(const string& s = "0") { + str = s; + } + operator string () const { + return str; + } + const BinaryNumber& operator++() { + std::string::iterator i = str.end() - 1; + while (*i == '1' && i != str.begin()) { + *i = '0'; + --i; + } + if (i == str.begin()) { + str.insert(str.begin(), '1'); + } else { + *i = '1'; + } + + return *this; + } +}; diff --git a/contests/2contest/5.cpp b/contests/2contest/5.cpp new file mode 100644 index 0000000..a3c19e9 --- /dev/null +++ b/contests/2contest/5.cpp @@ -0,0 +1,56 @@ +#include +using namespace std; + +class Row +{ +public: + int* const cells = new int[3]; + + int* + begin() const { + return cells; + } + + int* + end() const { + return cells + 3; + } + + int& operator[](int ind) const { + return cells[ind]; + } +}; + +class Matrix +{ +public: + const Row r[3]; + + const Row* + begin() const { + return r; + } + + const Row* + end() const { + return r + 3; + } + + int& + operator[](int ind1, int ind2) { + return r[ind1][ind2]; + } +}; + +// int +// main() { +// Matrix m; +// m[1, 1] = 5; + +// for (const auto& row : m) { +// for (auto cell : row) { +// cout << cell << " "; +// } +// cout << "\n"; +// } +// } diff --git a/contests/3contest/1.cpp b/contests/3contest/1.cpp new file mode 100644 index 0000000..d29e0ca --- /dev/null +++ b/contests/3contest/1.cpp @@ -0,0 +1,81 @@ +#include +#include + +namespace numbers { + class complex { + double c_re, c_im; + public: + complex(double r = 0, double i = 0) : c_re(r), c_im(i) {} + explicit complex(const std::string& s) { + sscanf(s.c_str(), "(%lf,%lf)", &c_re, &c_im); + } + double re() const { + return c_re; + } + double im() const { + return c_im; + } + double abs2() const { + return c_re * c_re + c_im * c_im; + } + double abs() const { + return sqrt(abs2()); + } + std::string to_string() const { + char buf[100]; + sprintf(buf, "(%.10g,%.10g)", c_re, c_im); + + return std::string(buf); + } + complex& operator+=(const complex& other) { + c_re += other.c_re; + c_im += other.c_im; + + return *this; + } + complex& operator-=(const complex& other) { + c_re -= other.c_re; + c_im -= other.c_im; + + return *this; + } + complex& operator*=(const complex& other) { + double r = c_re * other.c_re - c_im * other.c_im; + double i = c_re * other.c_im + c_im * other.c_re; + c_re = r; + c_im = i; + + return *this; + } + complex& operator/=(const complex& other) { + double r = (c_re * other.c_re + c_im * other.c_im) / other.abs2(); + double i = (c_im * other.c_re - c_re * other.c_im) / other.abs2(); + c_re = r; + c_im = i; + + return *this; + } + friend complex operator+(const complex& C, const complex& other) { + return complex(C.c_re + other.c_re, C.c_im + other.c_im); + } + friend complex operator-(const complex& C, const complex& other) { + return complex(C.c_re - other.c_re, C.c_im - other.c_im); + } + friend complex operator*(const complex& C, const complex& other) { + return complex(C.c_re * other.c_re - C.c_im * other.c_im, C.c_re * other.c_im + C.c_im * other.c_re); + } + friend complex operator/(const complex& C, const complex& other) { + double r = (C.c_re * other.c_re + C.c_im * other.c_im) / other.abs2(); + double i = (C.c_im * other.c_re - C.c_re * other.c_im) / other.abs2(); + + return complex(r, i); + } + }; + + complex operator-(const complex& C) { + return complex(-C.re(), -C.im()); + } + complex operator~(const complex& C) { + return complex(C.re(), -C.im()); + } +} \ No newline at end of file diff --git a/contests/3contest/4.cpp b/contests/3contest/4.cpp new file mode 100644 index 0000000..aaeae0f --- /dev/null +++ b/contests/3contest/4.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace numbers; + + +int main(int argc, char** argv) { + complex C(argv[1]); + double R = std::stod(argv[2]); + int N = std::stoi(argv[3]); + std::vector record; + for (int i = 4; i < argc; i++) { + record.push_back(argv[i]); + } + + complex I, z, next = C + R; + double h = 2 * M_PI; + double s = h / N; + for (double i = 0; i < h; i += s) { + z = next; + next = C + R * complex(std::cos(i), std::sin(i)); + I += eval(record, (z + next) / 2) * (next - z); + } + + std::cout << I.to_string() << std::endl; + + return 0; +} diff --git a/contests/4contest/1.cpp b/contests/4contest/1.cpp new file mode 100644 index 0000000..226a4cd --- /dev/null +++ b/contests/4contest/1.cpp @@ -0,0 +1,15 @@ +#include +#include + +void process(const std::vector& from, std::vector& into, int step) { + auto iterf = from.begin(); + auto itert = into.rbegin(); + + while (iterf < from.end() && itert != into.rend()) { + *itert += *iterf; + ++itert; + iterf += step; + } + + return; +} \ No newline at end of file diff --git a/contests/4contest/2.cpp b/contests/4contest/2.cpp new file mode 100644 index 0000000..8c921c3 --- /dev/null +++ b/contests/4contest/2.cpp @@ -0,0 +1,35 @@ +#include +#include + +void process(std::vector& mas, int64_t limit) { + auto itert = mas.end(); + int dst = 0; + + for (auto it = mas.begin() + mas.size() - 1; it != mas.begin() - 1; --it) { + dst = it - mas.begin(); + + if (*it >= limit) { + mas.insert(itert, *it); + itert = mas.end(); + } + + it = mas.begin() + dst; + } + + return; +} + +// #include + +// int main() { +// std::vector mas = { 1, 4, 3, 2 }; +// int64_t limit = 3; + +// process(mas, limit); + +// for (const auto& val : mas) { +// std::cout << val << " "; +// } + +// return 0; +// } \ No newline at end of file diff --git a/contests/4contest/3.cpp b/contests/4contest/3.cpp new file mode 100644 index 0000000..28305a7 --- /dev/null +++ b/contests/4contest/3.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +void process(const std::vector& mas1, std::vector& mas2) { + std::set set1(mas1.begin(), mas1.end()); + + if (set1.empty() || mas2.empty()) { + return; + } + + for (auto it = mas2.end() - 1; it != mas2.begin() - 1; --it) { + int dst = it - mas2.begin(); + + if (std::find(set1.begin(), set1.end(), dst) != set1.end()) { + mas2.erase(it); + } + } + + return; +} \ No newline at end of file diff --git a/contests/5contest/1.cpp b/contests/5contest/1.cpp new file mode 100644 index 0000000..61e4bb1 --- /dev/null +++ b/contests/5contest/1.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +bool comp(unsigned int a, unsigned int b) { + int res1 = 0; + while (a != 0) { + res1 += a & 1; + a = a >> 1; + } + + int res2 = 0; + while (b != 0) { + res2 += b & 1; + b = b >> 1; + } + + return res1 < res2; +} + + +int main() { + std::vector v; + unsigned int tmp; + while (std::cin >> tmp) { + v.push_back(tmp); + } + + std::stable_sort(v.begin(), v.end(), comp); + + for (auto x : v) { + std::cout << x << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/contests/5contest/2.cpp b/contests/5contest/2.cpp new file mode 100644 index 0000000..c36fe1e --- /dev/null +++ b/contests/5contest/2.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +int main() { + std::map> mp; + + std::string name; + int grade; + while (std::cin >> name >> grade) { + mp[name].push_back(grade); + } + + for (auto x : mp) { + std::cout << x.first << " "; + + double tmp = 0; + int n = 0; + for (auto i : x.second) { + tmp += i; + ++n; + } + + std::cout << tmp / n << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/contests/5contest/3.cpp b/contests/5contest/3.cpp new file mode 100644 index 0000000..e69de29 diff --git a/contests/5contest/4.cpp b/contests/5contest/4.cpp new file mode 100644 index 0000000..453da20 --- /dev/null +++ b/contests/5contest/4.cpp @@ -0,0 +1,26 @@ +#include +#include + +int main() { + long long mod = 4294967161; + + std::map, long long> mp; + + long long r, c, v; + while (std::cin >> r >> c >> v) { + if (!r && !c && v == mod) break; + + mp[std::make_pair(r, c)] = v; + } + + while (std::cin >> r >> c >> v) { + mp[std::make_pair(r, c)] += v; + mp[std::make_pair(r, c)] %= mod; + } + + for (auto x : mp) { + if (x.second) std::cout << x.first.first << " " << x.first.second << " " << x.second << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/contests/5contest/5.cpp b/contests/5contest/5.cpp new file mode 100644 index 0000000..b3c7164 --- /dev/null +++ b/contests/5contest/5.cpp @@ -0,0 +1,26 @@ +#include +#include + +int main() { + long long mod = 4294967161; + + std::map, long long> mp; + + long long r, c, v; + while (std::cin >> r >> c >> v) { + if (!r && !c && v == mod) break; + + mp[std::make_pair(r, c)] = v; + } + + while (std::cin >> r >> c >> v) { + // mp[std::make_pair(r, c)] *= v; + mp[std::make_pair(r, c)] %= mod; + } + + for (auto x : mp) { + if (x.second) std::cout << x.first.first << " " << x.first.second << " " << x.second << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/contests/6contest/1.cpp b/contests/6contest/1.cpp new file mode 100644 index 0000000..8af70ff --- /dev/null +++ b/contests/6contest/1.cpp @@ -0,0 +1,21 @@ +#include + +template +typename Container::value_type process(const Container& container) { + using ValueType = typename Container::value_type; + + if (container.empty()) { + return ValueType{}; + } + + auto it = container.rbegin(); + ValueType sum = *it; + + for (int i = 0; it != container.rend() && i < 5; ++i, ++it) { + if (i == 2 || i == 4) { + sum += *it; + } + } + + return sum; +} \ No newline at end of file diff --git a/contests/6contest/2.cpp b/contests/6contest/2.cpp new file mode 100644 index 0000000..30117d6 --- /dev/null +++ b/contests/6contest/2.cpp @@ -0,0 +1,16 @@ +// #include +// #include +#include + +template +Container myfilter(const Container& container, Predicate pred) { + Container result; + + for (const auto& x : container) { + if (pred(x)) { + result.insert(result.end(), x); + } + } + + return result; +} diff --git a/contests/6contest/3.cpp b/contests/6contest/3.cpp new file mode 100644 index 0000000..e69de29 diff --git a/contests/6contest/5.cpp b/contests/6contest/5.cpp new file mode 100644 index 0000000..feb8f5b --- /dev/null +++ b/contests/6contest/5.cpp @@ -0,0 +1,19 @@ +#include +#include + +template > +void selection_sort(ForwardIt first, ForwardIt last, Compare comp = Compare()) { + for (auto fit = first; fit != last; ++fit) { + auto min_it = fit; + + for (auto sit = std::next(fit); sit != last; ++sit) { + if (comp(*sit, *min_it)) { + min_it = sit; + } + } + + std::swap(*fit, *min_it); + } + + return; +} diff --git a/contests/7contest/1.cpp b/contests/7contest/1.cpp new file mode 100644 index 0000000..55d9366 --- /dev/null +++ b/contests/7contest/1.cpp @@ -0,0 +1,5 @@ +class Figure { +public: + virtual double get_square() const = 0; + virtual ~Figure() {}; +}; diff --git a/contests/7contest/2.cpp b/contests/7contest/2.cpp new file mode 100644 index 0000000..0179c63 --- /dev/null +++ b/contests/7contest/2.cpp @@ -0,0 +1,58 @@ +#include +#include +#include + +// class Figure { +// public: +// virtual double get_square() const = 0; +// virtual ~Figure() {}; +// }; + +class Rectangle : Figure { + double a; + double b; +public: + Rectangle(double a = 0, double b = 0) : a(a), b(b) {} + double get_square() const { + return a * b; + } + static Rectangle* make(std::string s) { + std::istringstream ss(s); + double a, b; + ss >> a >> b; + + return new Rectangle(a, b); + } +}; + +class Square : Figure { + double a; +public: + Square(double a = 0) : a(a) {} + double get_square() const { + return a * a; + } + static Square* make(std::string s) { + std::istringstream ss(s); + double a; + ss >> a; + + return new Square(a); + } +}; + +class Circle : Figure { + double r; +public: + Circle(double r = 0) : r(r) {} + double get_square() const { + return M_PI * r * r; + } + static Circle* make(std::string s) { + std::istringstream ss(s); + double r; + ss >> r; + + return new Circle(r); + } +}; \ No newline at end of file diff --git a/contests/7contest/5.cpp b/contests/7contest/5.cpp new file mode 100644 index 0000000..e30358c --- /dev/null +++ b/contests/7contest/5.cpp @@ -0,0 +1,36 @@ +class Figure { +public: + virtual bool equals(const Figure*) const = 0; + virtual ~Figure() {} +}; + +class Rectangle : Figure { + int a; + int b; +public: + Rectangle(int a = 0, int b = 0) : a(a), b(b) {} + bool equals(const Figure* fig) const { + const Rectangle* rect = dynamic_cast(fig); + if (rect) { + return a == rect->a && b == rect->b; + } + + return false; + } +}; + +class Triangle : Figure { + int a; + int b; + int c; +public: + Triangle(int a = 0, int b = 0, int c = 0) : a(a), b(b), c(c) {} + bool equals(const Figure* fig) const { + const Triangle* tri = dynamic_cast(fig); + if (tri) { + return a == tri->a && b == tri->b && c == tri->c; + } + + return false; + } +}; \ No newline at end of file diff --git a/contests/8contest/1.cpp b/contests/8contest/1.cpp new file mode 100644 index 0000000..b1395ed --- /dev/null +++ b/contests/8contest/1.cpp @@ -0,0 +1,30 @@ +#include + +class A { + std::string s; +public: + A(const std::string& s) : s(s) {} + ~A() { std::cout << s << std::endl; } +}; + +void f() { + std::string s; + + if (!(std::cin >> s)) { + throw 0; + } + + A a(s); + f(); +} + +int main() { + try { + f(); + } + catch (...) { + + } + + return 0; +} \ No newline at end of file diff --git a/contests/8contest/2.cpp b/contests/8contest/2.cpp new file mode 100644 index 0000000..fbc0305 --- /dev/null +++ b/contests/8contest/2.cpp @@ -0,0 +1,60 @@ +/* +Некоторая рекурсивная функция func от трех целых аргументов a, b, k (a, b >= 1, k >= 0) определена следующим образом: + + func(a, b, k) == a + b при k == 0 + func(a, b, k) == a при k > 0, b == 1 + func(a, b, k) == f(a, f(a, b - 1, k), k - 1) при k > 0, b > 1 + +На стандартном потоке ввода подаются тройки чисел: два 64-битных знаковых целых положительных числа a, b и 32-битное целое неотрицательное число k. Для каждой тройки чисел на стандартный поток вывода напечатайте значение описанной выше функции. + +Параметры на входе будут таковы, что вычисление завершится за разумное время. Для вычислений достаточно 64-битного целого знакового типа. + +Для возврата значения из рекурсии используйте исключения. Выход из рекурсивной функции с помощью явного или неявного return запрещен. + +Напишите свой класс (например, Result) для передачи результата вычислений вместе с исключением. Не используйте выбрасывание исключений базовых (например, int) типов. + +В комментарии в начале программы опишите, что из себя представляет эта рекурсивная функция. +*/ + +#include +#include + +class Result { + long long val; +public: + Result(long long val) : val(val) {} + long long value() const { return val; } +}; + +// Функция определена по условию. Выкидывает результат в виде exception +void f(long long a, long long b, int k) { + if (k == 0) { + throw Result(a + b); + } + + if (b == 1) { + throw Result(a); + } + + try { + f(a, b - 1, k); + } + catch (const Result& result) { + f(a, result.value(), k - 1); + } +} + +int main() { + long long a, b; + int k; + while (std::cin >> a >> b >> k) { + try { + f(a, b, k); + } + catch (const Result& result) { + std::cout << result.value() << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/contests/8contest/3.cpp b/contests/8contest/3.cpp new file mode 100644 index 0000000..688bbd8 --- /dev/null +++ b/contests/8contest/3.cpp @@ -0,0 +1,91 @@ +/* +Реализуйте класс S следующим образом: + + Класс хранит целое число (типа int). + Число считывается со стандартного потока ввода в конструкторе. + Число выводится на стандартный поток вывода в деструкторе. + Следующая программа: + + using namespace std; + void func(S v) + { + if (v) { + func(move(v)); + } + } + + int main() + { + func(S()); + } + + считывает последовательность целых чисел и выводит на стандартный поток вывода их сумму. + Если входная последовательность пустая, программа не выводит ничего. + +Проверка на переполнение не требуется. + +Глобальные переменные, static, mutable запрещены. + +Сдаваемый на проверку класс должен подключать необходимые заголовочные файлы. +Examples +Input + +1 2 3 + +Output + +6 +*/ + +#include + +class S { + int v; + int sum; + bool last; + bool first; +public: + S(S&& s) { + int val; + first = false; + + if (std::cin >> val) { + v = val; + last = false; + sum = s.sum + v; + } else { + last = true; + sum = s.sum; + } + + } + ~S() { + if (last && !first) { + std::cout << sum << std::endl; + } + } + S() : v(0), sum(0), last(true), first(true) { + int val; + + if (std::cin >> val) { + v = val; + last = false; + sum = v; + } + } + + operator bool() const { + return !last; + } +}; + +// using namespace std; +// void func(S v) { +// if (v) { +// func(move(v)); +// } +// } + +// int main() { +// func(S()); +// } \ No newline at end of file diff --git a/lectures/BlackHole.cpp b/lectures/BlackHole.cpp new file mode 100644 index 0000000..f5c6826 --- /dev/null +++ b/lectures/BlackHole.cpp @@ -0,0 +1,165 @@ +// #include +// #include +// #include + +class BlackHole { + int mass; +public: + BlackHole(size_t mass) : mass(mass) {} + + size_t get_mass() const { + return mass; + } + + template + void consume(T* arg) { + if (arg == nullptr) { + std::cout << "There is nothing to consume" << std::endl; + return; + } + + size_t arg_mass = sizeof(*arg); + if (std::is_const::value) { + std::cout << "Black hole consumed " << arg_mass << " const bytes" << std::endl; + } else { + std::cout << "Black hole consumed " << arg_mass << " non-const bytes" << std::endl; + } + + mass += arg_mass; + delete arg; + + return; + } + + void consume(void* arg) { + throw std::runtime_error("Black hole has tried to consume void"); + + return; + } + + void consume(const void* arg) { + throw std::runtime_error("Black hole has tried to consume void"); + + return; + } + + void consume(BlackHole* arg) { + if (arg == this) { + throw std::runtime_error("Black hole has tried to consume itself"); + + return; + } + + size_t arg_mass = arg->get_mass(); + if (std::is_const::value) { + std::cout << "Black hole consumed " << arg_mass << " const bytes" << std::endl; + } else { + std::cout << "Black hole consumed " << arg_mass << " non-const bytes" << std::endl; + } + + mass += arg_mass; + delete arg; + + return; + } + + void consume(const BlackHole* arg) { + if (arg == this) { + throw std::runtime_error("Black hole has tried to consume itself"); + + return; + } + + size_t arg_mass = arg->get_mass(); + if (std::is_const::value) { + std::cout << "Black hole consumed " << arg_mass << " const bytes" << std::endl; + } else { + std::cout << "Black hole consumed " << arg_mass << " non-const bytes" << std::endl; + } + + mass += arg_mass; + delete arg; + + return; + } + + template + void consume(T arg) { + throw std::runtime_error("Black hole has tried to consume non-pointer"); + + return; + } + + ~BlackHole() = default; +}; + +/* +Требуется реализовать класс BlackHole. + +1) Конструктор класса должен принимать аргумент типа size_t, задающий массу чёрной дыры. + +2) У класса должен быть метод get_mass() возвращающий текущую массу. + +3) У класса должен быть шаблонный метод consume(arg), предназначенный для "поглощения" указателей (см. ниже) и способный принимать аргументы любых типов. + +Вызов consume должен вести себя следующим образом. + +1) Он должен выбрасывать исключение типа runtime_error (тексты исключений следует взять из примера вывода ниже) в следующих ситуациях: + +- При передаче ему аргумента, не являющегося указателем + +- Если переданный указатель указывает на void (константный или неконстантный) + +- Если чёрная дыра пытается поглотить саму себя + +2) Если в качестве аргумента передан нулевой указатель, следует напечатать "There is nothing to consume" и ничего не делать. + +3) Если ни одно из выше перечисленных условий не сработало, то аргумент считается корректным указателем и для него нужно выполнить следующие действия: + +- Определить "массу" аргумента. Для BlackHole масса определяется через вызов get_mass(), для остальных - через размер указываемого типа в байтах. + +- Напечатать "Black hole consumed N non-const bytes", где вместо N нужно подставить массу аргумента. Если в качестве аргумента передан указатель на константный тип, то вместо non-const следует печатать const. + +- Добавить массу аргумента к текущей массе чёрной дыры. + +- Удалить аргумент через вызов delete. + +При подстановке решения студента, следующий код должен работать: +*/ + +// int main() { +// BlackHole hole(100); +// std::cout << "The initial mass is " << hole.get_mass() << " bytes" << std::endl; + +// hole.consume(new int64_t); +// hole.consume(const_cast (new int64_t)); +// hole.consume(new int32_t); +// hole.consume(static_cast(nullptr)); +// hole.consume(new BlackHole{ 50 }); +// hole.consume(new std::array); + +// try { +// hole.consume(5); +// } +// catch (std::runtime_error& err) { +// std::cout << "Error: " << err.what() << std::endl; +// } + +// try { +// hole.consume(&hole); +// } +// catch (std::runtime_error& err) { +// std::cout << "Error: " << err.what() << std::endl; +// } + +// try { +// hole.consume((void*) nullptr); +// } +// catch (std::runtime_error& err) { +// std::cout << "Error: " << err.what() << std::endl; +// } + +// std::cout << "The total mass is: " << hole.get_mass() << " bytes" << std::endl; + +// return 0; +// } \ No newline at end of file diff --git a/lectures/Count copy.cpp b/lectures/Count copy.cpp new file mode 100644 index 0000000..86ec507 --- /dev/null +++ b/lectures/Count copy.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include + +/* +Количество слов + +Напишите программу, которая для заданного ДКА и заданной максимальной длины N выводит общее количество слов не длинее N, допускаемых данным ДКА. + +На вход программе подаётся описание ДКА в виде непустых строк следующих следующих видов. + +1) Переход из состояния номер 1 в состояние номер 2 по символу "a": + +[1] a [2] + +2) Обозначение того, что состояние номер 3 является допускающим: + +[[3]] + +3) Явное объявление состояния под номером 4 (например, на случай если оно не фигурирует ни в каких переходах и не является допускающим): + +[4] + +После описания ДКА идёт пустая строка, за ней число N. + +Номера состояний - это целые неотрицательные числа, в алфавит ДКА входят только строчные символы латинского алфавита. + +Число N не может быть больше 100, а ответ помещается в тип size_t. + +Начальным состоянием считается то, которое было первым объявлено в описании ДКА (либо в явном виде, либо при описании перехода). +Примеры +Входные данные в файле noMore.in + +[0] a [1] +[1] a [0] +[1] b [0] +[[0]] + +4 + +Результат работы в файле noMore.out + +7 +*/ + +int main() { + std::regex state_declaration_pattern(R"(\[(\d+)\])"); + std::regex transition_pattern(R"(\[(\d+)\]\s*([a-z])\s*\[(\d+)\])"); + std::regex accepting_state_pattern(R"(\[\[(\d+)\]\])"); + + std::map> state_transitions; + std::set accepting_states; + int start_state = -1; + + std::ifstream Input("noMore.in"); + std::string line; + + while (std::getline(Input, line)) { + std::smatch match_result; + + if (start_state == -1 && std::regex_match(line, match_result, state_declaration_pattern)) { + start_state = std::stoi(match_result[1].str()); + } else if (std::regex_match(line, match_result, transition_pattern)) { + start_state = start_state == -1 ? std::stoi(match_result[1].str()) : start_state; + state_transitions[std::stoi(match_result[1].str())][match_result[2].str()[0]] = std::stoi(match_result[3].str()); + } else if (std::regex_match(line, match_result, accepting_state_pattern)) { + accepting_states.insert(std::stoi(match_result[1].str())); + } else if (line.empty()) { + break; + } + } + + int max_length; + Input >> max_length; + Input.close(); + + size_t total_count = 0; + std::vector> dp_table(max_length + 1); + dp_table[0][start_state] = 1; + + for (int length = 1; length <= max_length; ++length) { + for (const auto& [current_state, count] : dp_table[length - 1]) { + for (const auto& [transition_char, next_state] : state_transitions[current_state]) { + dp_table[length][next_state] += count; + } + } + } + + for (int length = 0; length <= max_length; ++length) { + for (const auto& [state, count] : dp_table[length]) { + if (accepting_states.count(state)) { + total_count += count; + } + } + } + + std::ofstream Output("noMore.out"); + Output << total_count << std::endl; + Output.close(); + + return 0; +} diff --git a/lectures/Count.cpp b/lectures/Count.cpp new file mode 100644 index 0000000..e470c31 --- /dev/null +++ b/lectures/Count.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include + +/* +Количество слов + +Напишите программу, которая для заданного ДКА и заданной максимальной длины N выводит общее количество слов не длинее N, допускаемых данным ДКА. + +На вход программе подаётся описание ДКА в виде непустых строк следующих следующих видов. + +1) Переход из состояния номер 1 в состояние номер 2 по символу "a": + +[1] a [2] + +2) Обозначение того, что состояние номер 3 является допускающим: + +[[3]] + +3) Явное объявление состояния под номером 4 (например, на случай если оно не фигурирует ни в каких переходах и не является допускающим): + +[4] + +После описания ДКА идёт пустая строка, за ней число N. + +Номера состояний - это целые неотрицательные числа, в алфавит ДКА входят только строчные символы латинского алфавита. + +Число N не может быть больше 100, а ответ помещается в тип size_t. + +Начальным состоянием считается то, которое было первым объявлено в описании ДКА (либо в явном виде, либо при описании перехода). +Примеры +Входные данные в файле noMore.in + +[0] a [1] +[1] a [0] +[1] b [0] +[[0]] + +4 + +Результат работы в файле noMore.out + +7 +*/ + +int main() { + std::ifstream inputFile("noMore.in"); + + std::string line; + std::regex firstLinePattern(R"(\[(\d+)\])"); + std::regex subsequentLinePattern(R"(\[(\d+)\]\s*([a-z])\s*\[(\d+)\])"); + std::regex finalLinePattern(R"(\[\[(\d+)\]\])"); + std::regex emptyLinePattern(R"(\s*)"); + std::regex numLinePattern(R"(\d+)"); + + // Read the first line + int start_num = -1; + std::map> transitions; + std::set final_states; + + int n = 0; + + // Read subsequent lines + while (std::getline(inputFile, line)) { + std::smatch match; + if (std::regex_match(line, match, firstLinePattern)) { + if (start_num == -1) { + start_num = std::stoi(match[1].str()); + } + } else if (std::regex_match(line, match, subsequentLinePattern)) { + if (start_num == -1) { + start_num = std::stoi(match[1].str()); + } + int fromState = std::stoi(match[1].str()); + char symbol = match[2].str()[0]; + int toState = std::stoi(match[3].str()); + transitions[fromState][symbol] = toState; + } else if (std::regex_match(line, match, finalLinePattern)) { + final_states.insert(std::stoi(match[1].str())); + } else if (std::regex_match(line, match, emptyLinePattern)) { + continue; + } else if (std::regex_match(line, match, numLinePattern)) { + n = std::stoi(match[0].str()); + } else { + break; + } + } + inputFile.close(); + + size_t ans = 0; + std::vector> dp(n + 1); + dp[0][start_num] = 1; + for (int k = 1; k <= n; ++k) { + for (const auto& [state, count] : dp[k - 1]) { + for (const auto& [symbol, nextState] : transitions[state]) { + dp[k][nextState] += count; + } + } + } + for (int k = 0; k <= n; ++k) { + for (const auto& [state, count] : dp[k]) { + if (final_states.count(state)) { + ans += count; + } + } + } + + std::ofstream outputFile("noMore.out"); + outputFile << ans << std::endl; + + outputFile.close(); + + return 0; +} \ No newline at end of file diff --git a/lectures/DataBuffer-Data.cpp b/lectures/DataBuffer-Data.cpp new file mode 100644 index 0000000..4605bc8 --- /dev/null +++ b/lectures/DataBuffer-Data.cpp @@ -0,0 +1,110 @@ +#include +#include + +int increment_counter() { + static int counter = 0; + return counter++; +} + +struct Data { +public: + int value; + Data(int x = 42) : value(x) {} + Data(const Data& data) { + value = data.value; + } + ~Data() { + // std::cout << "~Data() called " << std::endl; + increment_counter(); + } + Data& operator=(const Data& data) { + value = data.value; + + return *this; + } + friend std::ostream& operator<<(std::ostream& os, const Data data) { + os << data.value; + return os; + } +}; + +class DataBuffer { + Data* addr; + size_t size_buf; + friend void std::swap(DataBuffer& a, DataBuffer& b); +public: + DataBuffer(size_t size) { + // std::cout << "called11!" << std::endl; + size_buf = size; + addr = new Data[size_buf]; + } + DataBuffer(const DataBuffer& data_buf) = delete; + const DataBuffer& operator=(const DataBuffer& data_buf) = delete; + DataBuffer(DataBuffer&& data_buf) noexcept : addr(data_buf.addr), size_buf(data_buf.size_buf) { + // std::cout << "Move constructor called!" << std::endl; + data_buf.addr = nullptr; + data_buf.size_buf = 0; + } + DataBuffer& operator=(DataBuffer&& data_buf) noexcept { + // std::cout << "Move assignment operator called!" << std::endl; + if (this != &data_buf) { + delete[] addr; + addr = data_buf.addr; + size_buf = data_buf.size_buf; + data_buf.addr = nullptr; + data_buf.size_buf = 0; + } + return *this; + } + ~DataBuffer() { + // std::cout << "called1!" << std::endl; + delete[] addr; + } + size_t size() const { + return size_buf; + } + Data& operator[](const size_t ind) { + return addr[ind]; + } + const Data& operator[](const size_t ind) const { + return addr[ind]; + } +}; + +namespace std { + template<> + void swap(DataBuffer& a, DataBuffer& b) { + std::swap(a.addr, b.addr); + std::swap(a.size_buf, b.size_buf); + } +} + +void print_buffer(const DataBuffer& buffer) { + for (size_t i = 0; i < buffer.size(); i++) + std::cout << "buffer[" << i << "] == " << buffer[i] << std::endl; +} + +int main() { + { + DataBuffer buffer_1{ 5 }, buffer_2{ 3 }; + + std::cout << "buffer_1.size() == " << buffer_1.size() << std::endl; + std::cout << "buffer_2.size() == " << buffer_2.size() << std::endl; + + for (size_t i = 0; i < buffer_2.size(); i++) + buffer_2[i] = i + 1; + + std::cout << "buffer_1[0] == " << buffer_1[0].value << std::endl; + std::cout << "buffer_2[0] == " << buffer_2[0].value << std::endl; + + std::swap(buffer_1, buffer_2); + // DataBuffer buffer_copy = buffer_1; // forbidden! + + std::cout << "buffer_1.size() == " << buffer_1.size() << std::endl; + std::cout << "buffer_2.size() == " << buffer_2.size() << std::endl; + + print_buffer(buffer_1); + } + std::cout << "~Data() called " << increment_counter() << " times" << std::endl; + return 0; +} \ No newline at end of file diff --git a/lectures/Reverse.cpp b/lectures/Reverse.cpp new file mode 100644 index 0000000..6c4081c --- /dev/null +++ b/lectures/Reverse.cpp @@ -0,0 +1,45 @@ +#include + +class C +{ + unsigned long long x = 0; + bool last = false; + +public: + C() { + if (std::cin >> x) { + return; + } + + last = true; + } + + ~C() { + if (last) { + return; + } + + std::cout << x << " "; + } +}; + +void +f() { + C c; + + if (std::cin.eof()) { + return; + } + + f(); + + return; +} + +int +main() { + f(); + std::cout << std::endl; + + return 0; +} diff --git a/lectures/Sort copy.cpp b/lectures/Sort copy.cpp new file mode 100644 index 0000000..276fd47 --- /dev/null +++ b/lectures/Sort copy.cpp @@ -0,0 +1,81 @@ + +/* +Сортировка + +Необходимо реализовать функцию filter_sort, которая принимает контейнер с произвольным доступом к элементам и три лямбда-функции. Первая лямбда задаёт критерий фильтрации элементов контейнера, вторая - порядок первичной сортировки элементов, третья - вторичной сортировки. Файл с решением должен содержать только реализацию шаблонной функции filter_sort. Тип элементов контейнера при тестировании может быть любым. + +После подстановки вашей реализации, приведенный ниже код должен работать (при тестировании код отличается) и выдавать для примера ввода ниже пример вывода ниже: + +*/ + +#include +#include +#include +#include +#include +#include + +struct Student { + std::string full_name; + int group_no; + + void print() const { + std::cout << group_no << " " << full_name << std::endl; + } + + static std::optional read() { + Student student; + if (!(std::cin >> student.group_no)) + return {}; + std::cin >> std::ws; + if (!std::getline(std::cin, student.full_name)) + return {}; + return student; + } +}; + +// Your filter_sort is here! + +template +void filter_sort(T& mas, Filter filter, PSort psort, SSort ssort) { + auto it = std::remove_if(mas.begin(), mas.end(), [filter](auto a) { return !filter(a); }); + + std::stable_sort(mas.begin(), it, [ssort](auto a, auto b) { return ssort(a, b); }); + std::stable_sort(mas.begin(), it, [psort](auto a, auto b) { return psort(a, b); }); + + mas.erase(it, mas.end()); +} + +int main() { + std::vector students; + while (auto student = Student::read()) + students.push_back(*student); + + filter_sort(students, // the container + [](Student& stud) { return stud.group_no >= 0; }, // filter + [](Student& stud_1, Student& stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort + [](Student& stud_1, Student& stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort + ); + + for (auto& student : students) + student.print(); + + return 0; +} + + +/* +Примеры +Входные данные + +-100 Иванов Иван +300 Забугоркина Афродита +0 Смирнова Настя +0 Смирнова Анастасия + +Результат работы + +0 Смирнова Анастасия +0 Смирнова Настя +300 Забугоркина Афродита +*/ diff --git a/lectures/Sort.cpp b/lectures/Sort.cpp new file mode 100644 index 0000000..ba10612 --- /dev/null +++ b/lectures/Sort.cpp @@ -0,0 +1,90 @@ + +/* +Сортировка + +Необходимо реализовать функцию filter_sort, которая принимает контейнер с произвольным доступом к элементам и три лямбда-функции. Первая лямбда задаёт критерий фильтрации элементов контейнера, вторая - порядок первичной сортировки элементов, третья - вторичной сортировки. Файл с решением должен содержать только реализацию шаблонной функции filter_sort. Тип элементов контейнера при тестировании может быть любым. + +После подстановки вашей реализации, приведенный ниже код должен работать (при тестировании код отличается) и выдавать для примера ввода ниже пример вывода ниже: + +*/ + +// #include +// #include +// #include +// #include +// #include +// #include + +// struct Student { +// std::string full_name; +// int group_no; + +// void print() const { +// std::cout << group_no << " " << full_name << std::endl; +// } + +// static std::optional read() { +// Student student; +// if (!(std::cin >> student.group_no)) +// return {}; +// std::cin >> std::ws; +// if (!std::getline(std::cin, student.full_name)) +// return {}; +// return student; +// } +// }; + +// Your filter_sort is here! + +template +void filter_sort(Container& container, Filter filter, PrimarySort primary_sort, SecondarySort secondary_sort) { + auto it = std::remove_if(container.begin(), container.end(), [=](auto& item) { return !filter(item); }); + container.erase(it, container.end()); + + std::stable_sort(container.begin(), container.end(), [=](auto item1, auto item2) { return secondary_sort(item1, item2); }); + std::stable_sort(container.begin(), container.end(), [=](auto item1, auto item2) { return primary_sort(item1, item2); }); + + return; +} + +// int main() { +// std::vector students; +// while (auto student = Student::read()) +// students.push_back(*student); + +// filter_sort(students, // the container +// [](Student& stud) { return stud.group_no >= 0; }, // filter +// // [](const Student stud_1, const Student stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort +// [](Student& stud_1, Student& stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort +// // [](const Student stud_1, const Student stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort +// [](Student& stud_1, Student& stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort +// ); + +// // filter_sort(students, // the container +// // [](Student& stud) { return stud.group_no >= 0; }, // filter +// // [](Student& stud_1, Student& stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort +// // [](Student& stud_1, Student& stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort +// // ); + +// for (auto& student : students) +// student.print(); + +// return 0; +// } + +/* + +Примеры +Входные данные + +-100 Иванов Иван +300 Забугоркина Афродита +0 Смирнова Настя +0 Смирнова Анастасия + +Результат работы + +0 Смирнова Анастасия +0 Смирнова Настя +300 Забугоркина Афродита +*/ \ No newline at end of file diff --git a/lectures/Tree.cpp b/lectures/Tree.cpp new file mode 100644 index 0000000..8d95aca --- /dev/null +++ b/lectures/Tree.cpp @@ -0,0 +1,137 @@ +// #include +// #include + +// class ASTNode; + +// class NodeOwner { +// ASTNode* node = nullptr; +// public: +// explicit NodeOwner(ASTNode* node) : node(node) {} + +// NodeOwner(const NodeOwner&) = delete; +// NodeOwner& operator=(const NodeOwner&) = delete; +// NodeOwner(NodeOwner&& other) { std::swap(node, other.node); } +// NodeOwner& operator=(NodeOwner&& other) { std::swap(node, other.node); return *this; } + +// ASTNode* operator->() { return node; } +// const ASTNode* operator->() const { return node; } +// operator bool() const { return (bool)node; } + +// ~NodeOwner(); +// }; + +/* + +Реализации классов ASTNode, ASTNumberNode, ASTPlusNode и ASTMinusNode. +Реализации операторов operator+ и operator-. + +*/ + +class ASTNode { +public: + virtual void print() {} + virtual int get_value() { return 0; } + virtual ~ASTNode() {} +}; + +class ASTNumberNode : ASTNode { + int value; +public: + ASTNumberNode(int value) : value(value) {} + static NodeOwner create(int value = 0) { + return NodeOwner(new ASTNumberNode(value)); + } + + void print() { + std::cout << value; + } + + int get_value() { + return value; + } + + ~ASTNumberNode() = default; +}; + +class ASTPlusNode : ASTNode { + NodeOwner left, right; +public: + ASTPlusNode(NodeOwner left, NodeOwner right) : left(std::move(left)), right(std::move(right)) {} + static NodeOwner create(NodeOwner left, NodeOwner right) { + return std::move(NodeOwner(new ASTPlusNode(std::move(left), std::move(right)))); + } + + void print() { + std::cout << "("; + left->print(); + std::cout << " + "; + right->print(); + std::cout << ")"; + } + + int get_value() { + return left->get_value() + right->get_value(); + } + + ~ASTPlusNode() = default; +}; + +class ASTMinusNode : ASTNode { + NodeOwner left, right; +public: + ASTMinusNode(NodeOwner left, NodeOwner right) : left(std::move(left)), right(std::move(right)) {} + static NodeOwner create(NodeOwner left, NodeOwner right) { + return std::move(NodeOwner(new ASTMinusNode(std::move(left), std::move(right)))); + } + + void print() { + std::cout << "("; + left->print(); + std::cout << " - "; + right->print(); + std::cout << ")"; + } + + int get_value() { + return left->get_value() - right->get_value(); + } + + ~ASTMinusNode() = default; + +}; + +NodeOwner operator+(NodeOwner left, NodeOwner right) { + return std::move(NodeOwner(ASTPlusNode::create(std::move(left), std::move(right)))); +} + +NodeOwner operator-(NodeOwner left, NodeOwner right) { + return std::move(NodeOwner(ASTMinusNode::create(std::move(left), std::move(right)))); +} + + +// NodeOwner::~NodeOwner() { +// if (node) +// delete node; +// } + +// int main() { +// // static_assert(std::is_same::value, "ASTNumberNode::create() must return NodeOwner value"); +// // static_assert(std::is_same::value, "ASTPlusNode::create() must return NodeOwner value"); +// // static_assert(std::is_same::value, "(NodeOwner + NodeOwner) must return NodeOwner value"); + +// auto expr_1 = ASTPlusNode::create( +// ASTNumberNode::create(1), +// ASTMinusNode::create( +// ASTNumberNode::create(2), +// ASTNumberNode::create(3) +// ) +// ); +// expr_1->print(); +// std::cout << " = " << expr_1->get_value() << std::endl; + +// auto expr_2 = ASTNumberNode::create(4) - ASTNumberNode::create(5) + ASTNumberNode::create(6); +// expr_2->print(); +// std::cout << " = " << expr_2->get_value() << std::endl; + +// return 0; +// } \ No newline at end of file diff --git a/lectures/Vector.cpp b/lectures/Vector.cpp new file mode 100644 index 0000000..3b9c94b --- /dev/null +++ b/lectures/Vector.cpp @@ -0,0 +1,69 @@ +// #include +// #include +// #include +// #include + +// struct Element { +// int value; +// Element(int value) : value(value) {} +// }; + +// Реализация функции make_safe_vector() + +template +std::vector> make_safe_vector(T&& container) { + std::vector> result; + + for (auto& el : container) + result.emplace_back(std::move(el)); + + container.clear(); + + return result; +} + +// int main() { +// std::vector unsafe_vector; +// unsafe_vector.emplace_back(new Element(0)); +// unsafe_vector.emplace_back(new Element(42)); +// unsafe_vector.emplace_back(new Element(900)); + +// auto safe_vector_1 = make_safe_vector(unsafe_vector); +// unsafe_vector.push_back(new Element(99)); + +// auto safe_vector_2 = make_safe_vector(safe_vector_1); + +// auto safe_vector_3 = make_safe_vector(std::list{new Element(1), new Element(2), new Element(3)}); + +// std::cout << "unsafe_vector: " << std::endl; +// for (auto& el : unsafe_vector) { +// std::cout << el->value << std::endl; +// delete el; +// } + +// std::cout << "safe_vector_1: " << std::endl; +// for (auto& el : safe_vector_1) +// std::cout << el->value << std::endl; + +// std::cout << "safe_vector_2: " << std::endl; +// for (auto& el : safe_vector_2) +// std::cout << el->value << std::endl; + +// std::cout << "safe_vector_3: " << std::endl; +// for (auto& el : safe_vector_3) +// std::cout << el->value << std::endl; +// } + +/* +unsafe_vector: +99 +safe_vector_1: +safe_vector_2: +0 +42 +900 +safe_vector_3: +1 +2 +3 +*/ \ No newline at end of file diff --git a/lectures/t.cpp b/lectures/t.cpp new file mode 100644 index 0000000..0467998 --- /dev/null +++ b/lectures/t.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +int main() { + std::map> trans; + std::set accept_states; + int init_state = -1; + + std::ifstream Input("noMore.in"); + std::string str; + while (std::getline(Input, str)) { + if (str.empty()) break; + if (str.find("[[") != std::string::npos) { + int state; + sscanf(str.c_str(), "[[%d]]", &state); + accept_states.insert(state); + if (init_state == -1) { + init_state = state; + } + } else if (std::count(str.begin(), str.end(), '[') == 2) { + int left_state, right_state; + char symbol; + sscanf(str.c_str(), "[%d] %c [%d]", &left_state, &symbol, &right_state); + if (init_state == -1) { + init_state = left_state; + } + trans[left_state][symbol] = right_state; + } else { + int state; + sscanf(str.c_str(), "[%d]", &state); + if (init_state == -1) { + init_state = state; + } + } + } + + int N; + Input >> N; + + std::vector> dp(N + 1); + dp[0][init_state] = 1; + + for (int k = 1; k <= N; ++k) { + for (auto& [state, count] : dp[k - 1]) { + for (auto& [symbol, right_state] : trans[state]) { + dp[k][right_state] += count; + } + } + } + + size_t ans = 0; + for (int k = 0; k <= N; ++k) { + for (auto& [state, count] : dp[k]) { + if (accept_states.count(state)) { + ans += count; + } + } + } + + std::ofstream Output("noMore.out"); + Output << ans << std::endl; + + Output.close(); + Input.close(); + + return 0; +} diff --git a/seminars/1.md b/seminars/1.md new file mode 100644 index 0000000..5ad517f --- /dev/null +++ b/seminars/1.md @@ -0,0 +1,221 @@ +## Мини-отступление + +```cpp +#include +C f() { + C local var; + + // return local_var - криво + return std::move(local_var) +} +``` + +Благодаря std::move можно не создавать вторую переменную для возвращаемого значения. Входит в стандарт с c++17 и оптимизируется автоматически в c++14. + +--- + +# Перегрузка операций + +## Дружеские функции + +```cpp +class C { + int a; +public: + ... + friend void f(C &x); +}; + +void f(C &x) {cout << x.a} +``` + +функция также может относиться к другому классу + +## Перегргузка операций + +Нельзя перегружать: + +- \# +- :: +- ?: +- . +- .\* +- sizeof +- typeid + +### Бинарные операции + +```cpp +class C{ + double re; + double im; +public: + C (double x = 0.0, double y = 0.0) : re(x), im(y) {} + bool isEqual(C &obj) { + return re == obj.re && im == obj.im; // неявная подстановка this-> + } + + bool operator ==(C &obj) { + return re == obj.re && im == obj.im; + } + + // нужен const, чтобы можно было делать o3 = o1 + 10.0 + C operator+(const C& obj) { + return C(re + obj.re, im + obj.im); + } // o3 = o1 + o2 +}; + +void main() { + C o1, o2, o3; + + o1.isEqual(o2) == (o1 == o2); // the same + + o3 = o1 + o2; + o3 = o1 + 10.0 + +} +``` + +либо для дальнейшей работы и `o1 = 10.0 + o2` изменим перегрузку операнда: + +```cpp +friend C operator+(const C& obj1, const C& obj2) { + return C(obj2.re + obj1.re, obj2.im + obj1.im); + } +``` + +### Унарные операции + +```cpp +C operator-() { + return C(-re, -im); +} // o3 = -o1 +// !! не перегрузит никак бинарную + +``` + +Посткремент и инкремент: + +```cpp +C& operator++() { + re++; + im++; + return *this; +} + +C operator++(int NU) { // not used var + С tmp(re, im); + re++; + im++; + return tmp; +} + +void main() { + o3 = ++o1; + o3 = o1++; +} +``` + +`o3 = (o1++)++;` не проработает!! (изменит временную переменную) + +### Перегрузка =, [], () + +> не перегружаются как дружественные! + +```cpp +C &operator=(const C &obj) { + re = obj.re; + im = obj.im; + + return *this; +} // по умолчанию так перегружается +``` + +## Итоговый пример + +```cpp +int +main() { + string s1("abcd"), s2("qw"), s3; + s2[1] = 'A'; + s2.print(); + s3 = s1 + s2; + + s3.print(); +} +``` + +Итоговый код, чтобы условие выше выполнялось: + +```cpp +#include +#include +#include +#include + +class string +{ + int len; // количество памяти + char* str; + +public: + string(const char* s = "") { + len = strlen(s) + 1; + str = new char[len]; + strcpy(str, s); + } + + char& + operator[](int n) { + return str[n]; + } + + string + operator+(string s) { + string tmp; + tmp.len = s.len + len - 1; + tmp.str = new char[tmp.len]; + + strcpy(tmp.str, str); + strcpy(tmp.str + len - 1, s.str); + + return tmp; + } + + string + operator=(string s) { + if (s.str == str) { + return s; + } + + delete[] str; + len = s.len; + str = new char[len]; + strcpy(str, s.str); + + return *this; + } + + // ~string() { delete[] str; } почему-то с ним не работает (?) + + void + print() { + std::cout << str << " " << len << std::endl; + } +}; +``` + +версия присваивания получше: + +```cpp +void string::swap(string& a) { + std::swap(str, a.str); + std::swap(len, a.len); +} + +string& string::operator=(string a) { + swap(a); + + return *this; +} +``` diff --git a/seminars/2.md b/seminars/2.md new file mode 100644 index 0000000..a887e6d --- /dev/null +++ b/seminars/2.md @@ -0,0 +1,204 @@ +# + +## Про оптимизации + +```cpp +A obj = A(10); // A(const A&) +obj1 = obj; // A(A&) +``` + +при отключении оптимизации будет: + +- преобразования +- копирования +- деструктор + +На экзе во всех задачах _вероятно_ отключена оптимизация + +```cpp +A f(...) { + A local; + return local; +} +``` + +будет создаваться 2 переменные. + +## Перегрузка (продолжение) + +### Приведение типов + +```cpp +operator double() { + return re; +} +double x = 3.1, y; +y = C1 + x; // !error - не понятно, к какому типу +y = double(C1) + x == C1 + C(x); +``` + +### Ввод/вывод + +```cpp +friend ostream & operator<<(ostream &os, C&a) { + os << "re=" << a.re << ...; + return os; +} + +int main() { + C obj(1,2); + cout << obj; // ostream and class + return 0; +} +``` + +### Перегрузка вызова функции + +```cpp +struct Pred { + bool operator()(int v) { + return v < 10; + } +}; + +void f(int *mas, int n, Pred(c)) { + for (int i = 0; i < n; ++i) { + if (c(mas[i])) { + mas[i] *= 2; + } + } +} +``` + +--- + +## Перегрузка функций + +Алгоритм для поиска наиболее подходящей функции для вызова + +1. по количеству параметров +2. отбросить недопустимые преобразования +3. точные совпадения (на typedef): + 1. T <-> T& + 2. T[] <-> \*T + 3. T -> const T +4. можно расширить тип (например к инт): + 1. unsigned char + 2. unsigned short + 3. short and etc + 4. float -> double (нет лонг дабл) +5. стандартные преобразования + - Любой числовой приводится к любому числовому типу + - Любой указатель приводится к указателю на void + - 0 к любому указателю или любому числовому +6. пользовательсткие преобразования + +--- + +```cpp +const int ci = 1; +void f(int y) {...} + +f(ci); // всё ок +``` + +--- + +алгоритм (фактически): + +- отбрасываем неподходящие +- по каждому параметру берём множество подходящих функций +- смотрим персечение + +```cpp +struct A { + operator int() { return 1; } + void f(double d, char c); // 1 + void f(double d, int j); // 2 + void f(A a, const char *p); // 3 + void f(int i, const char *p); // 4 +}; + +int main() { + A a; + + f(a, 0); // 3 & 2 => 0 + f(a, 'a'); // 12 & 1 => 1 + f('a', 0); // 4 & 2 => 0 +} +``` + +## Статические члены класса + +```cpp +class A { + int a; + static int b; +public: + A(int x) : a(x) { } + static void f() { + cout << b; + } +}; + +int main() { + int A::b = 77; + A::f(); + return 0; +} +``` + +требования: + +- работа только с статик полями +- вызывать только статик функции +- нельзя как const или virtual объявить (void f const { } // может менять статик и mutable поля) + +```cpp +class A { + static int x; + int y; +public: + int f(int x) const {}; +}; + +int main() { + const A a; + a.x = 3; + cout << a.y << a.x << a.f(1); +} +``` + +--- + +```cpp +struct A { + int n; + int k; + A (A &a) { n = a.n; } + int f() { return k; } + A (int a) { n = a; } +}; + +int main() { + A a = A(1), b; + cout << A::f() << " " << a.k << a.n << endl; // 5 53 +} +``` + +```cpp +struct A { + int n; + static int k; + A (const A &a) { n = a.n; } + static int f() { return k; } + A (int a = 3) { n = a; } +}; + +int A::k = 5; + +int main() { + A a = A(1), b; + cout << A::f() << " " << a.k << b.n << endl; // 5 53 +} +``` diff --git a/seminars/3.md b/seminars/3.md new file mode 100644 index 0000000..c96935d --- /dev/null +++ b/seminars/3.md @@ -0,0 +1,259 @@ +# Третий семинар + +## Шаблоны + +```cpp +// template +template +void swap(T& a, T& b) { + T tmp; + tmp = a; + a = b; + b = tmp; +} +``` + +Можно применять и от нескольких неизвестных параметров + +```cpp +template +void transfer(T fromAccount, T toAccount, K code, int sum) +{ + std::cout << "From: " << fromAccount << "\nTo: " << toAccount + << "\nSum: " << sum << "\nCode: " << code << std::endl; +} +``` + +Пример кода для абсолютного значения: + +```cpp +template T abs(const T& x) { +// template T abs(T x) { + return x >= 0 ? x : -x; +} +``` + +Суммирование элементов массива + +```cpp +template T sum(T* mas, int N) { + T res = 0; + + for (int i = 0; i < N; ++i) { + res += mas[i]; + } + + return res; +} + +int main() { + double mas[5] = {...}; + std::cout << sum(mas, 5); + + return 0; +} +``` + +```cpp +template T sum(T* mas, int N) { + T res = 0; + + for (int i = 0; i < N; ++i) { + res += mas[i]; + } + + return res; +} + + +int main() { + double mas[5] = {...}; + std::cout << sum(mas); + + return 0; +} +``` + +## Что-то про стэк + +Вторая задача: + Суть была реализовывать динамически расширяемый массив + +```cpp +template +class st { + T st[SIZE]; + int top = 0; +public: + void push(T a) { + if (top == SIZE) { + // error + } else { + st[top++] = a; + } + } + T pop(); +} + +template +T st::pop() { + + return st[--top]; +} + +``` + +Если указать стандартное значение для каких-то параметров, вызов обычный + +## Библиотеки + +### Контейнеры + +#### Последовательности + +- list - двунаправленный список +- vector +- deque - очередь + +На их основе создаются: + +- stack +- queue + +#### Ассоциативные массивы + +- map - отображения +- multimap - ключ может несколько раз встречаться +- set - уникальные упорядоченные ключи +- multiset - совпадающие ключи + +### Итераторы + +`#include ` - подключение библиотеки + +- value_type - тип значений в контейнере +- size_type - аналог size_t +- reference/ const reference - ссылки на элемент +- pointer/const pointer - указатели + +Исполняют роль указателей + +Для каждого контейнера определён: + +- iterator - идёт от начала +- reverse_iterator - идёт с конца +- const_iterator - не меняет значений +- const_reverse_iterator - не меняет значений, ревёрс + +```cpp +begin(), end(); +rbegin(), rend(); + +cbegin(), cend(); // для константных +``` + +Виды итераторов: + +- input +- output +- forward +- bidirectional - list, map, set +- random_access - для vector deque, можно индексировать, += n + +```cpp +#include + +int main() { + vector v1; // длина 0 + vector v2(5); // длина 5, занулены + vector v3(10, '*'); + int m[] = {1, 2, 3, 4}; + vector v4(m, m + 4); + // vector v4(m.begin(), m.end()); +} +``` + +```cpp +for (int i = 0; i < v.size(); ++i) + cout << v[i] << " "; // только для random_access контейнера + +v[i] == v.at(i) // выдаёт out_of_range, если нет элемента +``` + +Печать элементов в прямом и обратном при помощи итераторов + +```cpp +#include +#include + +// прямой с помощью прямого +void f1(std::vector mas) { + std::vector::std::iterator iter = mas.begin(); + while (iter != mas.end()) { + std::cout << *iter << " "; + iter++; + } +} + +// обратный с помощью реверсивного +void f2(std::vector mas) { + std::vector::std::reverse_iterator iter = mas.rbegin(); + while (iter != mas.rend()) { + std::cout << *iter << " "; + iter++; + } +} + +// обратный с помощью прямого +void f3(std::vector mas) { + std::vector::std::iterator iter = mas.end(); + while (iter != mas.begin()) { + --iter; + std::cout << *iter << " "; + } +} +``` + +Или же код нормального человека: + +```cpp +for (auto x : v) cout << x << " "; +``` + +### Алгоритмы + +Некоторые методы контейнеров: + +- `size_type size()` - количество элементов в контейнере +- `bool empty()` - пустой ли контейнер +- `void clear()` - очищает контейнер +- `void push_back()` - добавляет в конец value_type<> +- `void pop_back()` - удаляет последний элемент +- `reference back()` - возвращает ссылку на последний элемент +- `reference front()` - возвращает ссылку на первый элемент +- `iterator insert(iterator p, value_type<>)` - вставка перед позицией p, возвращает на новый элемент +- `iterator erase(iterator p)` - удаляет, куда указывает, возвращает итератор на некст элемент +- `iterator erase(iterator p1, iterator p2)` - c первого до последнего (не включительно) + +для list, deque + +- `void push_front(value_type<>)` +- `void pop_front(value_type<>)` + +Для bidirectional итераторов можно использовать + +- `advance(p1, 3)` для плюса +- `n = distance(p1, p2)` для вычитания + +```cpp +void f(vactor& mas) { + auto iter = mas.begin(); + + while (iter < mas.end()) { + ++iter; + + if (iter != mas.end()) + iter = mas.erase(iter); + } +} +``` diff --git a/seminars/4.md b/seminars/4.md new file mode 100644 index 0000000..e965967 --- /dev/null +++ b/seminars/4.md @@ -0,0 +1,180 @@ +# Шаблонные функции с контейнером на вход + + -> написать шаблонную функцию, которая ищет макс значение в константном или неконстантном контейнере + +```cpp +#include +#include +#include + +using namespace std; + +template +typename T::value_type Max(const T& c) { + // используем константные итераторы cbegin + typename T::value_type max = *c.cbegin(); + + for (const auto& it : c) { + if (*it > max) { + max = *it; + } + max = *it > max ? *it : max + } + + return max; +} + + +int main() { + list l = { 1, 2, 3, 4, 5 }; + cout << Max>(l) << endl; + + vector v = { 1, 2, 3, 4, 5 }; + cout << Max>(v) << endl; + + return 0; +} +``` + +Шаблонная функция, которая удваивает все элементы в контейнере +Из [1, 2, 3] делает [1, 1, 2, 2, 3, 3] + +```cpp +// работает, но херня, много памяти жрёт +template +void dbl(T& c) { + T res; + auto it = c.begin(); + while (it != c.end()) { + res.push_back(*it); + res.push_back(*it); + ++it; + } + + c = res; + + return; +} + +// работает, всё правильно +template +void dbl(T& c) { + auto it = c.begin(); + // typename T::iterator it = c.begin(); - порой могут вот так просить на коллоквиуме + + while (it != c.end()) { + it = c.insert(++it, *it); + ++it; + } + + return; +} + +``` + +вход функции: 2 итератора, реверсирующая данную коллекцию +Было [1, 2, 3] Стало [3, 2, 1] + +```cpp +template +void rever(T b, T e) { + if (b == e) return; // для проверки на пустой контейнер + + --e; + + while (b != e) { // просто сравнивать нельзя у листов + swap(*b++, *e); // нативный свап + + if (b == e) break; + + --e; + } + + return; +} +``` + +функции подаётся 2 итератора, предикат и стандартное значение +Предикат - объект с перегруженными круглыми скобками + +```cpp +template // T - указатель P - предикат +void f(T b, T, e, P pred, typename T::value_type val) { + +} + +// пример предиката +struct Pred { + bool operation()(int v) { + return v % 3; + } +} + +int main () { + vector v = {...}; + + f(v.begin(), v.end(), Pred(), 9); + + return 0; +} +``` + +## Лямба-функции + +Неименованные функции, которые можно просто вставить в выражение + +```cpp +int x = 5; +auto ef = [x]() { cout << x; } // тут не обойтись без auto +ef(); +auto ef = [](int a) { cout << a; } +ef(x); +``` + +В квадратных скобках - привязка к внешним элементам + +- [] привязки нет +- [=] привязываются все внешние +- [&] по ссылке привязываются все внешние + +В круглых - к тем, что передаются + +## Алгоритм remove_if + +```cpp +vector v = {2, 4, 5, 7, 9, 10}; +auto end = remove_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; }) +``` + +remove_if перемещает в хвост все значения, для которых предикат (лямбда-функция) верна. Возвращает указатель на начало хвоста +Вывод: [5, 7, 9, 2, 4, 10]. end указывать будет на '2' + +## 2 задание 3го контеста + +> есть уже complex, complex stack. Добавление в стек через операцию << + +посчитать польско-инвер запись для комплексных чисел. Если попадается z - значение по умолчанию + +> map - словарик. Содержит элементы 'ключ' - 'значение' + +```cpp +complex eval(const vector& args, const complex& z) { + complex stack st; + map> mp; { + {"z", [&st, &z]() { st = st << z; }}, // если попалось z, добавили в стек + {";", [&st]() { st = ~st; }}, + ... // все прочие +/-/... операции + } + + for (const auto& iter : args) { + if (s[0] != '(') { // если строка не (re,im) + mp[s](); // просто вызвали нужное + } else { + st = st << complex(s); + } + } + + // ответ на верхушке стека + return +st; +} +``` diff --git a/seminars/4.pdf b/seminars/4.pdf new file mode 100644 index 0000000..f726671 Binary files /dev/null and b/seminars/4.pdf differ diff --git a/seminars/5.md b/seminars/5.md new file mode 100644 index 0000000..f4f653c --- /dev/null +++ b/seminars/5.md @@ -0,0 +1,61 @@ +# Наследования + +```cpp +class A { + int a; +public: + A(int x = 0) : a(x) {} + void f() { cout << a; } +}; + +class B : public/private/protected A/*, C*/ { // private by default + int b; +public: + B(int x = 0, int y = 0) : A(x), b(y) {} + void f() { + cout << a << b; // error. A is private + } +}; +``` + +```cpp +int main() { + A obj_a, *pa; + B obj_b, *pb; + pa = &obj_a; + pb = &obj_b; + + // при открытом наследовании + pa = pb; + pb = (B*)pa; + + // при закрытом наследовании + pa = (A*)pb; + // pb = (B*)pa; - невозможно + + *pa = &obj_a; + pa->f(); // вызов из a + *pa = &obj_b; + pa->f(); // вызов тоже из a, т.к. не виртуальная функция +} +``` + +в ситуации любого наложения функций, происходит перекрытие имён + +```cpp +class A { + void f(); +} + +class B : A { + void f(int) { f(); } // error +} +``` + +конструкторы не наследуются + +## консруктор копирования + +```cpp +B (const B &a) : A(a) {} +``` diff --git a/seminars/6.md b/seminars/6.md new file mode 100644 index 0000000..33f3b9c --- /dev/null +++ b/seminars/6.md @@ -0,0 +1,187 @@ +# Семинар 6 + +## RTTI - Run Time Type Identification + +- typeid +- dynamic_cast + +### typeid + +> `typeid` возвращает тип объекта/указателя. Если указатель на класс с виртуальными функциями, вернёт именно тип объекта. Иначе - указателя. + +Для `type_info` переопределённые операции и методы: + +- == +- !- +- .name + +```cpp +class A { +public: + virtual void f() {} +}; + +class B : public A {}; + +int main () { + A *pa = new B; + B *pb; + std::cout << typeid(*pa).name; // 1B (1 символ в имени) + if (typeid(*pa) == typeid(B)) { + pb = (B*)pa; // небезопасное приведение + } +} +``` + +## Dynamic cast + +```cpp +class A { +public: + virtual void f() {} +}; + +class B : public A {}; + +int main () { + A *pa, a; + B *pb, b; + pa = &b; + // безопасно приводит, вернёт не NULL в случае успеха + pb = dynamic_cast(pa); +} +``` + +```cpp +class A { +public: + virtual void f() {} +}; + +class B : public A {}; + +int main () { + A *pa, a; + B *pb, b; + A &pr = a; + // B &rb = dynamic_cast(pa); // выкинет bad_cast +} +``` + +## Исключения + +`try - throw - catch` + +`terminate()` - в случае, если ничего не обработалось + +приводится в `catch` указатели к константным могут + +```cpp +int f() { + try { + ... + throw 10; + ... + throw "abc"; + ... + throw A(); + ... + } catch (int a) { + ... + throw ...; // тогда обработается функцией выше + ... + } catch (const char* s) { + ... + } catch (A &x) { + ... + } catch (...) { // все остальные исключения + + } +} +``` + +В случае возвращение класса, который наследуется от базового, "ловить" надо сначала производный, после - базовый +Деструктор для создаваемого класса вызывается только после фулл обработки исключения (если catch сам вызвал throw) + +```cpp +int f() throw(int, char) { + try { + ... + throw 1.2; + ... + } catch (double) { + ... + } +} +``` + +`unexpected()` - вызывается, если мы на внешнюю функцию передаём исключение типа, который не указан + +```cpp +// никакие не передавать вовне +int f() throw(); + +after c++17 only: +int f() noexcept; +``` + +### Алгоритм обработки исключений + +- создание временного объекта типа возвращаемого исключения +- уничтожение объектов в `try` блоке +- выход из `try` +- подбор нужного обработчика +- если больше исключений нет - деструктор временного объекта +- если не обработано - выход к внешнему обработчику + +```cpp +5.14. Что напечатает следующая программа? +struct S { + S ( int a) { + try { + if (a > 0) throw *this ; + else if (a < 0) throw 0; + } + catch ( S & ) { + cout << “SCatch_S&” << endl; + } catch (int ) { throw ; } + cout << “SConstr” << endl; + } + S (const S & a) { cout << “Copy” << endl; } + ~S ( ) { cout << “Destr” << endl; } +}; +int main ( ) { + try { + S s1( 0 ), s2 ( 5 ); + cout << “Main” << endl; + } + catch (S &) { cout << “MainCatch_S&” << endl; } + catch ( ... ) { cout << “MainCatch_...” << endl; } + + return 0; +} +``` + +Результат отработки программы: + +```text +Sconstr +Copy +Scatch_s& +Destr +Sconstr +Main +Destr +Destr +``` + +1 +14 +15 +CatchB +bad_cast +63 +63 +3 +... +End diff --git a/seminars/codes/1.cpp b/seminars/codes/1.cpp new file mode 100644 index 0000000..63896ff --- /dev/null +++ b/seminars/codes/1.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +class string +{ + int len; // количество памяти + char* str; + +public: + string(const char* s = "") { + len = strlen(s) + 1; + str = new char[len]; + strcpy(str, s); + } + + char& + operator[](int n) { + return str[n]; + } + + string + operator+(string s) { + string tmp; + tmp.len = s.len + len - 1; + tmp.str = new char[tmp.len]; + + strcpy(tmp.str, str); + strcpy(tmp.str + len - 1, s.str); + + return tmp; + } + + // string + // operator=(string s) { + // if (s.str == str) { + // return s; + // } + + // delete[] str; + // len = s.len; + // str = new char[len]; + // strcpy(str, s.str); + + // return *this; + // } + + // ~string() { delete[] str; } почему-то с ним не работает (?) + + void + print() { + std::cout << str << " " << len << std::endl; + } +}; + + +int +main() { + string s1("abcd"), s2("qw"), s3; + s2[1] = 'A'; + s2.print(); + s3 = s1 + s2; + + s3.print(); +} diff --git a/seminars/codes/4.cpp b/seminars/codes/4.cpp new file mode 100644 index 0000000..95a0cad --- /dev/null +++ b/seminars/codes/4.cpp @@ -0,0 +1,96 @@ +// -> написать шаблонную функцию, которая ищет макс значение в константном или неконстантном контейнере +#include +#include +#include + +using namespace std; + +template +typename Container::value_type Max(const Container& c) { + typename Container::value_type max = *c.cbegin(); + + for (auto it = c.cbegin(); it != c.cend(); ++it) { + if (*it > max) { + max = *it; + } + } + + return max; +} + +template +void dbl(T& c) { + auto it = c.begin(); + + while (it != c.end()) { + it = c.insert(++it, *it); + ++it; + } + + return; +} + +template +void rever(T b, T e) { + if (b == e) return; + + --e; + + while (b != e) { + swap(*b++, *e); + + if (b == e) break; + + --e; + } + + return; +} + +struct Pred { + bool operator()(int x) { + return x % 3; + } +}; + +template // T - указатель P - предикат +void f(T b, T e, P pred, typename T::value_type val = {}) { + while (b != e) { + if (pred(*b)) { + *b = val; + } + ++b; + } + + return; +} + +int main() { + list l = { 1, 2, 3, 4, 5 }; + cout << Max>(l) << endl; + + f(l.begin(), l.end(), Pred()); + for (const auto& elem : l) { + cout << elem << " "; + } + cout << endl; + + // dbl(l); + // rever(l.begin(), l.end()); + // for (const auto& elem : l) { + // cout << elem << " "; + // } + // cout << endl; + + vector v = { 1, 3, 3, 4, 5 }; + cout << Max>(v) << endl; + + // dbl(v); + rever(v.begin(), v.end()); + for (const auto& elem : v) { + cout << elem << " "; + } + cout << endl; + + return 0; +} \ No newline at end of file diff --git a/seminars/markdown-cheat-sheet.md b/seminars/markdown-cheat-sheet.md new file mode 100644 index 0000000..c94cb27 --- /dev/null +++ b/seminars/markdown-cheat-sheet.md @@ -0,0 +1,119 @@ +# Markdown Cheat Sheet + +Thanks for visiting [The Markdown Guide](https://www.markdownguide.org)! + +This Markdown cheat sheet provides a quick overview of all the Markdown syntax elements. It can’t cover every edge case, so if you need more information about any of these elements, refer to the reference guides for [basic syntax](https://www.markdownguide.org/basic-syntax/) and [extended syntax](https://www.markdownguide.org/extended-syntax/). + +## Basic Syntax + +These are the elements outlined in John Gruber’s original design document. All Markdown applications support these elements. + +### Heading + +# H1 +## H2 +### H3 + +### Bold + +**bold text** + +### Italic + +*italicized text* + +### Blockquote + +> blockquote + +### Ordered List + +1. First item +2. Second item +3. Third item + +### Unordered List + +- First item +- Second item +- Third item + +### Code + +`code` + +### Horizontal Rule + +--- + +### Link + +[Markdown Guide](https://www.markdownguide.org) + +### Image + +![alt text](https://www.markdownguide.org/assets/images/tux.png) + +## Extended Syntax + +These elements extend the basic syntax by adding additional features. Not all Markdown applications support these elements. + +### Table + +| Syntax | Description | +| ----------- | ----------- | +| Header | Title | +| Paragraph | Text | + +### Fenced Code Block + +``` +{ + "firstName": "John", + "lastName": "Smith", + "age": 25 +} +``` + +### Footnote + +Here's a sentence with a footnote. [^1] + +[^1]: This is the footnote. + +### Heading ID + +### My Great Heading {#custom-id} + +### Definition List + +term +: definition + +### Strikethrough + +~~The world is flat.~~ + +### Task List + +- [x] Write the press release +- [ ] Update the website +- [ ] Contact the media + +### Emoji + +That is so funny! :joy: + +(See also [Copying and Pasting Emoji](https://www.markdownguide.org/extended-syntax/#copying-and-pasting-emoji)) + +### Highlight + +I need to highlight these ==very important words==. + +### Subscript + +H~2~O + +### Superscript + +X^2^ \ No newline at end of file