Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DKR #396

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions dk82_krapovnytskyi/dkr/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.PHONY: clean

build:
gcc -o main.o main.c utils.c -lm
clean:
rm *.o
55 changes: 55 additions & 0 deletions dk82_krapovnytskyi/dkr/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
=========================
Домашня контрольна робота
=========================

Варіант 3
---------
Программа выводит количество байт, различающихся в двух файлах. Если указан флаг --trim, больший по размеру файл принимается обрезанным до размера меньшего, а в противном случае – принимается различающимся также на разницу в размере файлов
Додоткові вимоги:
----------------

* Принимает аргументы командной строки. Для парсинга использовать Argp (`argp <https://www.gnu.org/software/libc/manual/html_node/Argp.html>`_)
* Собирается с помощью Make. Makefile содержит дополнительные цели build и clean, где build является целью-ссылкой на основную, а clean – PHONY-целью, очищающей все артефакты сборки
* Выводит результат в stdout, а ошибки – в stderr
* Содержит часть служебных функций, вынесенных в отдельный модуль utils (utils.c и utils.h)
* Использует флаг `--verbose (-v)`, заставляющий программу выводить выполняемые действия детально. В противном случае полагается, что ее вывод будет использоваться другой прогаммой.

Пример с verbose:

::

Parsed arguments: ...
...
Value: [val] Error: [err] ([errp] %)
Пример без verbose:
[val]
[err] [errp]

- Возвращает *exit code 0* в случае успешного завершения, соответствующий код ошибки в противном случае. Для определения ошибок использовать enum
- Использует объектный стиль кода для внутренних конструкций, реализующих основной функционал.

Building
--------
.. code-block::

make build

Parameters
----------

Use the `-v` parameter to get more information

Example Usage
~~~~~~~~~~~~~~
::

$ ./main.o --trim -v file1.txt file2.txt

Result
~~~~~~~~~~~~~~

.. code-block:: bash

[file1.txt] size is 26 bytes and [file2.txt] size is 33 bytes
After trimming [file1.txt] size is 26 bytes and [file2.txt] size is 26 bytes
Difference in bytes between files is : 8
1 change: 1 addition & 0 deletions dk82_krapovnytskyi/dkr/file1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, my name is thodned
1 change: 1 addition & 0 deletions dk82_krapovnytskyi/dkr/file2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, my name is Ykrapovn
58 changes: 58 additions & 0 deletions dk82_krapovnytskyi/dkr/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "utils.h"

static char doc[] = "Calculate difference between files in bytes";

static char args_doc[] = "Input two file names to compare each of them byte by byte";

static struct argp_option options[] = {
{"verbose", 'v', "VERBOSITY", OPTION_ARG_OPTIONAL, "Produce verbose output"},
{"trim", 't', "TRIMMED", OPTION_ARG_OPTIONAL, "Trim a larger file to the size of a smaller one"},
{0, 0, "FILE", 0, "File for reading"},
{0}
};

static struct argp argp = { options, parse_opt, args_doc, doc };

int main (int argc, char **argv)
{
//declare and intitialize structure to store parsed args
struct arguments arguments;

arguments.trim = 0;
arguments.verbose = 0;
arguments.index = 0;

argp_parse (&argp, argc, argv, 0, 0, &arguments);

unsigned long file1_size = calculate_file_size(arguments.input_file_names[0]);
unsigned long file2_size = calculate_file_size(arguments.input_file_names[1]);

unsigned char is_first_bigger = (file1_size > file2_size) ? 1 : 0;

if (arguments.verbose) {
fprintf(stdout, "\n[%s] size is %u bytes and [%s] size is %u bytes\n",
arguments.input_file_names[0], file1_size,
arguments.input_file_names[1], file2_size);
}

if (arguments.trim) {
if (is_first_bigger) {
trim_file(arguments.input_file_names[0], file2_size);
file1_size = file2_size;
}
else {
trim_file(arguments.input_file_names[1], file1_size);
file2_size = file1_size;
}
if (arguments.verbose) {
fprintf(stdout, "After trimming [%s] size is %u bytes and [%s] size is %u bytes\n",
arguments.input_file_names[0], file1_size,
arguments.input_file_names[1], file2_size);
}
}

fprintf(stdout, "Difference in bytes between files is : %u\n",
compare_files(arguments.input_file_names[0], arguments.input_file_names[1]));

exit(0);
}
Binary file added dk82_krapovnytskyi/dkr/main.o
Binary file not shown.
95 changes: 95 additions & 0 deletions dk82_krapovnytskyi/dkr/utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include "utils.h"


error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct arguments *arguments = state->input;

switch (key) {
case 'v':
arguments->verbose = 1;
break;
case 't':
arguments->trim = 1;
break;
case ARGP_KEY_ARG:
if (state->arg_num > 1) {
argp_failure (state, 1, 0, "Too many arguments\n");
argp_usage (state);
}
strcpy(arguments->input_file_names[arguments->index], arg);
(arguments->index)++;
break;
case ARGP_KEY_END:
if (state->arg_num < 2) {
argp_failure (state, 1, 0, "Too few arguments\n");
argp_usage (state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}


unsigned long calculate_file_size(char* file_name)
{
FILE* file = fopen(file_name, "r+");

if (file == NULL) {
fprintf(stderr, "Incorrect file name or it doesn't exit\n");
exit(EXIT_FAILURE);
}

fseek(file, 0L, SEEK_END);
unsigned long file_size = ftell(file);

fclose(file);

return file_size;
}

enum TRIM_STATUS trim_file(char* file_name, unsigned long desired_size)
{
enum TRIM_STATUS trim_status = __TRIM_OK__;

FILE* file = fopen(file_name, "r+");

if (file == NULL) {
fprintf(stderr, "Incorrect file name or it doesn't exit\n");
exit(EXIT_FAILURE);
}

trim_status = ftruncate(fileno(file), desired_size);

fclose(file);

return trim_status;
}

unsigned long compare_files(char* file_name1, char* file_name2)
{

char temp1, temp2;

unsigned long different_bytes = 0;

unsigned long file1_size = calculate_file_size(file_name1);
unsigned long file2_size = calculate_file_size(file_name2);

FILE* file1 = fopen(file_name1, "r+");
FILE* file2 = fopen(file_name2, "r+");

for (size_t i = 0; i < MIN(file1_size, file2_size); i++) {
fread(&temp1, 1, 1, file1);
fread(&temp2, 1, 1, file2);
if (temp1 != temp2) different_bytes++;
}

fclose(file1);
fclose(file2);

if (file1_size == file2_size) return different_bytes;
else return (different_bytes + abs((long) file1_size - (long) file2_size));
}
29 changes: 29 additions & 0 deletions dk82_krapovnytskyi/dkr/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <argp.h>
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))

enum TRIM_STATUS {
__TRIM_OK__ = 0,
__TRIM_FAIL__ = -1
};



struct arguments
{
char input_file_names[2][20];
unsigned long trim;
unsigned long verbose;
unsigned long index;
};

error_t parse_opt(int key, char *arg, struct argp_state *state);

unsigned long calculate_file_size(char* file_name);

enum TRIM_STATUS trim_file(char* file_name, unsigned long desired_size);

unsigned long compare_files(char* file_name1, char* file_name2);