mirror of https://github.com/t1meshift/os_labs.git
				
				
				
			Compare commits
	
		
			2 Commits 
		
	
	
		
			38b6a593e6
			...
			fca8d3a057
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | fca8d3a057 | |
|  | b18451fef0 | 
|  | @ -16,3 +16,4 @@ endfunction() | |||
| define_lab(lab2) | ||||
| define_lab(lab3) | ||||
| define_lab(lab4) | ||||
| define_lab(lab7) | ||||
|  | @ -4,6 +4,8 @@ | |||
| 
 | ||||
| - [Лабораторная работа 2](lab2/README.md) | ||||
| - [Лабораторная работа 3](lab3/README.md) | ||||
| - [Лабораторная работа 4](lab4/README.md) | ||||
| - [Лабораторная работа 7](lab7/README.md) | ||||
| 
 | ||||
| ## Запуск | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,17 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -euo pipefail | ||||
| IFS=$'\n\t' | ||||
| 
 | ||||
| LAB_FILE="$1/lab7_switch_case.c_run" | ||||
| 
 | ||||
| function test_string() { | ||||
|   local str=$1 | ||||
|   echo "Testing on string \`" $str "\`..." | ||||
|   echo -e $str | $LAB_FILE | ||||
| } | ||||
| 
 | ||||
| test_string "Hello :)" | ||||
| test_string "24 character long string" | ||||
| test_string "Hello World! Not 8-even-sized string" | ||||
| test_string "The test string, even with NUMBERS!\n1234 and 5678." | ||||
|  | @ -0,0 +1,34 @@ | |||
| cmake_minimum_required(VERSION 3.16) | ||||
| set(CMAKE_C_STANDARD 11) | ||||
| 
 | ||||
| # Lab name | ||||
| set(LAB_NAME "lab7") | ||||
| 
 | ||||
| # Lab tasks | ||||
| list(APPEND SOURCE_FILES | ||||
|         switch_case.c | ||||
|         ) | ||||
| list(APPEND NON_COMPILABLE_SRC | ||||
|         .execme | ||||
|         ) | ||||
| 
 | ||||
| ### Here goes the template | ||||
| 
 | ||||
| project("${LAB_NAME}" C) | ||||
| 
 | ||||
| add_custom_target("${LAB_NAME}") | ||||
| 
 | ||||
| foreach (file IN LISTS SOURCE_FILES) | ||||
|     add_executable("${LAB_NAME}_${file}_run" "${file}") | ||||
|     add_dependencies("${LAB_NAME}" "${LAB_NAME}_${file}_run") | ||||
| endforeach () | ||||
| 
 | ||||
| foreach (file IN LISTS NON_COMPILABLE_SRC) | ||||
|     add_custom_command( | ||||
|             TARGET "${LAB_NAME}" POST_BUILD | ||||
|             DEPENDS "${file}" | ||||
|             COMMAND ${CMAKE_COMMAND} -E copy | ||||
|             "${CMAKE_CURRENT_SOURCE_DIR}/${file}" | ||||
|             "${CMAKE_CURRENT_BINARY_DIR}/${file}" | ||||
|     ) | ||||
| endforeach () | ||||
|  | @ -0,0 +1,17 @@ | |||
| # Лабораторная работа №7 | ||||
| 
 | ||||
| Была поставлена задача разработать функцию, которая принимает строку и меняет  | ||||
| регистр через модификацию 6-ого бита. Для ускорения предлагается читать строку  | ||||
| из 32/64 бит, а не символ за один раз, если длина строки кратна 4/8 байт.  | ||||
| 
 | ||||
| В результате работы была разработана программа, использующая искомую функцию. В  | ||||
| целях оптимизации по памяти она считывает не строку целиком, а работает со вводом | ||||
| по частям по 8 байт каждая.  | ||||
| 
 | ||||
| Поскольку при вводе из tty могут возникнуть проблемы с EOF (если длина ввода кратна  | ||||
| восьми, то нужно дважды подавать сигнал Ctrl-D), программа считывает символы по одному,  | ||||
| если обнаруживает, что `stdin` принадлежит tty. Также в tty программа останавливает чтение | ||||
| строки на символе `\n` для удобства. | ||||
| 
 | ||||
| Применение битовой маски для всего блока в памяти затрудняется тем, что ввод может состоять | ||||
| не только из букв. | ||||
|  | @ -0,0 +1,71 @@ | |||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #define IS_ALPHA(x) (((x) >= 'A' && (x) <= 'Z') || ((x) >= 'a' && (x) <= 'z')) | ||||
| 
 | ||||
| typedef union { | ||||
|   uint64_t i64; | ||||
|   char     chr[8]; | ||||
| } str_block; | ||||
| 
 | ||||
| #define CHUNK_SIZE (sizeof(str_block)) | ||||
| 
 | ||||
| int chunk_switch_case(str_block *chunk) { | ||||
|   size_t i = 0; | ||||
|   for (; i < CHUNK_SIZE; ++i) { | ||||
|     if (!chunk->chr[i]) { | ||||
|       break; | ||||
|     } | ||||
|     if (IS_ALPHA(chunk->chr[i])) { | ||||
|       chunk->chr[i] ^= 0x20; | ||||
|     } | ||||
|   } | ||||
|   return i; | ||||
| } | ||||
| 
 | ||||
| char *str_switch_case(const char *str) { | ||||
|   size_t str_size = strlen(str); | ||||
|   size_t chunked_read_border = str_size - (str_size%CHUNK_SIZE); | ||||
|   char *result = malloc(str_size); | ||||
|   str_block chunk = {0}; | ||||
| 
 | ||||
|   for (size_t i = 0; i < chunked_read_border; i += CHUNK_SIZE) { | ||||
|     memcpy(chunk.chr,str + i, CHUNK_SIZE); | ||||
|     chunk_switch_case(&chunk); | ||||
|     memcpy(result + i, chunk.chr, CHUNK_SIZE); | ||||
|   } | ||||
|   for (size_t i = chunked_read_border; i < str_size; ++i) { | ||||
|     result[i] = str[i]; | ||||
|     if (IS_ALPHA(result[i])) { | ||||
|       result[i] ^= 0x20; | ||||
|     } | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| int main(){ | ||||
|   str_block chunk = {0}; | ||||
|   char stop_reading = 0; | ||||
| 
 | ||||
|   do { | ||||
|     if (isatty(STDIN_FILENO)) { | ||||
|       for (size_t i = 0; i < CHUNK_SIZE; ++i) { | ||||
|         fread(&chunk.chr[i], 1, 1, stdin); | ||||
|         if (chunk.chr[i] == '\n') { | ||||
|           chunk.chr[i] = 0; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       fread(&chunk.i64, 1, CHUNK_SIZE, stdin); | ||||
|     } | ||||
|     stop_reading = (chunk_switch_case(&chunk) != CHUNK_SIZE); | ||||
|     fwrite(&chunk.chr, 1, CHUNK_SIZE, stdout); | ||||
|     chunk.i64 = 0; | ||||
|   } while (!stop_reading); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue