Справочник от Автор24
Поделись лекцией за скидку на Автор24

Структуры: шаблон структуры; структурные переменные

  • 👀 307 просмотров
  • 📌 242 загрузки
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Структуры: шаблон структуры; структурные переменные» pdf
Лекция 3. СТРУКТУРЫ Успех программы часто зависит от удачного выбора способа представления данных. С помощью структур возможно моделировать сложные объекты, возникающие при решении задач. Структуры представляют средство для доступа к записям, которые содержат поля одного или нескольких типов. Для использования структуры необходимо: 1. установить шаблон для структуры 2. объявить переменную, соответствующую этому шаблону 3. осуществить доступ к компонентам структуры. Шаблон структуры Шаблон - это схема, описывающая содержание структуры. Установка структурного шаблона телефонный справочник: struct sprav { char fio[20]; long num; }; Данный шаблон описывает структуру с именем типа структуры sprav, состоящую из двух компонентов: строки fio и целой переменной num типа long. Имя типа структуры sprav необязательно и используется для ссылки на эту структуру. Компоненты структуры - данные любого типа, включая и другие структуры. Имя внутри структуры может быть таким же, как имя объекта вне структуры. Если шаблон описан внутри функции - он доступен только этой функции, если шаблон описан вне функции - он доступен любой функции программы. Установка шаблона не вызывает никаких действий в программе. Структурные переменные Объявление структурных переменных приводит к выделению памяти для компонент структуры, куда можно записать данные или откуда можно прочитать их. Для объявления структурных переменных имеются несколько способов. 1. Установить структурный шаблон: struct sprav { char fio[20]; long num; }; Объявить простую переменную, массив структур, указатель на структуру: struct sprav tel1, tel2[5], *tel3; 2. Установить структурный шаблон с помощью макроопределения: #define SPRAV struct sprav SPRAV { char fio[20]; long num; }; Объявить переменные: SPRAV sp1, sp2[6], *sp3; 3. Объявить переменные одновременно с установкой шаблона (если на данную структуру вы больше не ссылаетесь): struct { char fio[20]; long num; } tel1, tel2[3], *tel3; 4. Ввести новый тип данных (TEL) - структура определенного вида: typedef struct { char fio[20]; long num; } TEL; Объявить переменные нового типа: TEL tel1, tel2[6], *tel3; Если программа достаточно объемна, представляется более удобным четвертый способ. Инициализация структуры Инициализировать можно только внешние или статические структуры. static struct { char fio[20]; long num; } tel[2]= { "Иванов Ф.А.", 456756, "Петров В.П.", 632345 }; ДОСТУП К КОМПОНЕНТАМ СТРУКТУРЫ Доступ к компонентам структуры продемонстрируем с помощью примеров. Пример 1. Обращение к элементам структуры через имя переменной #include #include void main(void) { struct { char fio[20]; /* фамилия */ long num; /* телефон */ } tel1, tel2; clrscr(); puts("введите фио абонента-"); gets(tel1.fio); puts("введите его номер-"); scanf("%ld",&tel1.num); tel2=tel1; /* нельзя так же сравнивать структуры */ puts("Введено:"); printf("Фамилия :%s номер: %ld\n",tel2.fio,tel2.num); } Пример 2. Динамическое выделение памяти для структуры Обращение к элементам структуры через указатель #include #include struct sprav { char fio[20]; long num; }; 2 void main(void) { struct sprav *tel1, *tel2; tel1=(struct sprav *)malloc(sizeof(struct sprav)); // Выделение памяти для структуры tel2=(struct sprav *)malloc(sizeof(struct sprav)); puts("введите фио абонента-"); gets(tel1->fio); puts("введите его номер-"); scanf("%ld",&tel1->num); *tel2= *tel1; puts("Введено:"); printf("Фамилия :%s номер: %ld\n",(*tel2).fio,(*tel2).num); } Массив структур Пример 3. Массив структур. Обращение к элементам структуры через имя элемента массива #include #include #include #define SPRAV struct sprav void main(void) { SPRAV { char fio[20]; long num; }; SPRAV tel[5]; char fio_tek[20]; int i; // массив структур - 5 элементов for(i=0; i<5; i++) // ввод данных в массив структур { puts("введите фио абонента-"); gets(tel[i].fio); puts("введите его номер-"); scanf("%ld",&tel[i].num); getchar(); } puts("Выбор телефона по фамилии"); gets(fio_tek); for(i=0; i<5; i++) // поиск структуры по фамилии абонента if(!strcmp(fio_tek,tel[i].fio)) break; if(i!=5) printf("номер абонента %s равен %ld\n",fio_tek, tel[i].num); else puts("Абонент не найден"); } Пример 4. Массив структур. Память выделяется динамически. Обращение к элементам структуры через указатель #include #include #include 3 #include typedef struct { char fio[20]; long num; } TEL; void main(void) { TEL *tel; char fio_tek[20]; int i; tel=(TEL *)malloc(sizeof(TEL)*3); // Выделение памяти для массива - 3 элемента for(i=0; i<3; i++) { puts("введите фио абонента-"); gets((tel+i)->fio); puts("введите его номер-"); scanf("%ld",&(tel+i)->num); getchar(); } puts("Выбор телефона по фамилии"); gets(fio_tek); for(i=0; i<5; i++,tel++) if(!strcmp(fio_tek,tel->fio)) break; if(i!=5) printf("номер абонента %s равен %ld\n",fio_tek, tel->num); else puts("Абонент не найден"); } Передача структуры в функцию Непосредственный доступ к компонентам структуры - плохой стиль программирования. Все операции, которые разрешены применительно к структуре, должны быть при этом реализованы в виде отдельных функций. Не все компиляторы языка Си позволяют передавать структуры в функцию по значению, поэтому в примерах передача структуры идет через указатель. Для этого объявляем соответствующий тип typedef struct { float a; /* действительная часть */ float b; /* мнимая часть */ } COMPLEX; void out(COMPLEX *); void out( COMPLEX *p) { printf("(%.2f,%.2f)\n", (*p).a,(*p).b); return; } ВЛОЖЕННЫЕ СТРУКТУРЫ Структура, являющаяся компонентом другой структуры, называется вложенной. Пример 5. 4 Даны четыре точки - центры четырех окружностей. Заполнить структуру окружность, если все окружности проходят через начало координат. #include #include #include #include struct POINT { float x; float y; }; struct CIRCLE { struct POINT point; /* вложенная структура */ double r; circle[2], } *p; void main (void) { int i,j; float a,b,c,d; clrscr(); gotoxy(17,1); cputs("ВВЕДИТЕ КООРДИНАТЫ ТОЧЕК :\r\n"); for(i=0;i<2;i++) { cprintf ("\n\n ВВЕДИТЕ X: "); cprintf ("X[%d]= ",i+1); cscanf("%f",&circle[i].point.x); cprintf ("\n ВВЕДИТЕ Y: "); cprintf ("Y[%d]= ",i+1); cscanf ("%f",&circle[i].point.y); } p=circle; gotoxy(17,12); cputs("РЕЗУЛЬТАТ:\r\n\n"); for(i=0;i<2;i++) { a=p->point.x; b=p->point.y; c=sqrt(a*a+b*b); p->r=c; cprintf("\nРАДИУС : %lf , ЦЕНТР (%f,%f)\r\n",p->r,a,b); p++; } } 5 Работа с двоичными файлами Двоичный (типизированный) файл представляет собой набор компонент фиксированной длины. В качестве компонент двоичного файла могут выступать данные различных типов (целые и вещественные числа, структуры и пр.). При записи информации в двоичный файл и чтении информации из двоичного файла явно указываются размер в байтах одной компоненты и количество считываемых (записываемых) компонент. Поскольку размер компонент двоичного файла является строго постоянным, это дает возможность организовать прямой доступ к информации в двоичном файле. Данные, записываемые в двоичный файл, сохраняются в файле в виде набора символов. Поэтому, можно сказать, что двоичные файлы – это последовательность значений типа char. Использование двоичных файлов делает программы немобильными при переносе из одной среды в другую, поскольку, несмотря на то, что любой набор данных может быть представлен как набор символов, это представление может изменяться при переходе от одной реализации Си к другой. Кроме того, двоичные файлы нельзя создать и прочесть с помощью текстового редактора. Они создаются только в процессе работы программы. В силу вышеуказанных причин достаточно часто информацию хранят в текстовых файлах, на базе которых в процессе выполнения программы создают двоичные файлы и работают с ними, поскольку обработка двоичных файлов также проста, как и обработка массивов. Однако, способ хранения числовой информации в двоичных файлах имеет то преимущество, что позволяет экономить память. Открытие двоичного файла производится также как и открытие текстового файла - с помощью функции fopen(). Однако требуется обязательно явно указать, что файл открывается в бинарном режиме, для чего в конец строки, задающей режим открытия файла, добавляется символ ‘b’. Чтение двоичного файла и запись в двоичный файл можно производить только в бинарном режиме (“rb”, “wb” и т.п.). Например, f1=fopen ("test.dat", "wb"); - открытие двоичного файла test.dat в текущем каталоге в режиме записи Закрытие двоичного файла осуществляет функция fclose(). Для чтения информации из двоичного файла и записи информации в двоичный файл используются функции прямого ввода-вывода fread() и fwrite(). Данные, записанные в файл с помощью функции fwrite(), можно читать только с помощью функции fread() и наоборот. int fread(void *bufer, int size, int count, FILE *stream) Функция читает count элементов длины size из входного потока stream и помещает в bufer. int fwrite(char *bufer, int size, int count, FILE *stream) Функция дописывает count элементов длины size из области bufer в поток stream. Можно считать структуру из файла целиком с помощью функции fread, а записать – с помощью функции fwrite: fread ( адрес структурной переменной, размер структуры, количество структур, читаемых за 1 раз, указатель на файл); fwrite ( адрес структуры в памяти, размер структуры, количество структур, записываемых за 1 раз, указатель на файл); FILE *in; //Объявление файлового указателя char file_name[50]="c:\\user\\prim2.dat"; float a, // Буферная переменная in=fopen(file_name,"w+b"); // Открытие двоичного файла одновременно для чтения/записи fwrite(&a,sizeof(a),1,in); // Запись одного числа в файл fread(&a,sizeof(a),1,in); // Чтение первого числа из файла 6 В двух текстовых файлах содержится информация о студентах Информация о каждом студенте хранится в отдельной строке Структура записей в первом файле следующая: фамилия (15 символов, дополняется пробелами), имя (12 символов, дополняется пробелами), курс и три оценки - по физике, математике и программированию (номер курса и каждая оценка отделены друг от друга пробелами) Структура записей во втором файле следующая: фамилия (15 символов, дополняется пробелами), имя (12 символов, дополняется пробелами), пол (буква "ж" или "м") и год рождения через пробел Сформировать на основе каждого текстового файла соответствующий ему по информационному содержанию двоичный файл. Отсортировать записи в двоичных файлах, расположив фамилии по алфавиту. Определить, кто лучше сдал математику - юноши или девушки,#include #include #include #include //Шаблон структуры для хранения записей из первого файла struct stud1{ char fam[16]; char name[13]; int kurs; int oc[3]; }; //Шаблон структуры для хранения записей из второго файла struct stud2{ char fam[16]; char name[13]; char pol; int god; }; void main() { int i, fl, kolm, kolw; float srm, srw; long ft; FILE *ft1, *ft2, *fd1, //Флаг для сортировки //Кол-во девушек //Кол-во юношей //Средний балл юношей по математике //Средний балл девушек по математике //Указатель первого текстового файла //Указатель второго текстового файла //Указатель первого двоичного файла 7 *fd2; //Указатель второго двоичного файла //Буферные структуры stud1 so1, so2; stud2 sx1, sx2; char fnamet1[30]="c:\\user\\oc.txt", fnamet2[30]="c:\\user\\xarakt.txt", fnamed1[30]="c:\\user\\oc.dat", fnamed2[30]="c:\\user\\xarakt.dat"; clrscr(); //Открытие текстовых файлов для чтения if((ft1=fopen(fnamet1,"r"))==NULL) { printf("file %s ne syshestvyet",fnamet1); getch();exit(-1); } if((ft2=fopen(fnamet2,"r"))==NULL) { printf("file %s ne syshestvyet",fnamet1); getch();exit(-1); } //Открытие двоичных файлов одновременно для записи и чтения fd1=fopen(fnamed1,"w+b"); fd2=fopen(fnamed2,"w+b"); //Цикл считывания информации из текстовых файлов в буферные структуры //и записи этих структур в двоичные файлы while(fgets(so1.fam,16,ft1)!=NULL) //Считывается фамилия из 1-го текст. файла {fgets(so1.name,13,ft1); //Считывается имя из 1-го текст. файла fscanf(ft1,"%d",&so1.kurs); //Цикл чтения оценок for(i=0;i<3;i++) fscanf(ft1,"%d",&so1.oc[i]); fscanf(ft1,"\n"); fwrite(&so1,sizeof(so1),1,fd1); fgets(sx1.fam,16,ft2); fgets(sx1.name,13,ft2); sx1.pol=fgetc(ft2); fscanf(ft2, " %d",&sx1.god); fscanf(ft2,"\n"); fwrite(&sx1,sizeof(sx1),1,fd2); } //Считывается номер курса //Переход на новую стоку в 1-м файле //Запись структуры в 1-й двоичн. файл //Считывается фамилия из 2-го текст. файла //Считывается имя из 1-го текст. файла //Считывается пол //Считывается год рождения //Переход на новую стоку во 2-м файле //Запись структуры во 2-й двоичн. файл //Цикл вывода информации о студентах из обоих двоичных файлов //Позиционирование указателей на начало каждого двоичного файла rewind(fd1); rewind(fd2); printf("\nИнформация о студентах до сортировки\n"); fread(&so1,sizeof(so1),1,fd1); //Чтение структуры из 1-го двоичн. файла 8 fread(&sx1,sizeof(sx1),1,fd2); //Чтение структуры из 2-го двоичн. файла while(!feof(fd1)) { printf("\n%s %s %d ",so1.fam,so1.name,so1.kurs); for(i=0;i<3;i++) printf("%d ",so1.oc[i]); printf("%c %d",sx1.pol,sx1.god); fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); } //Сортировка информации в двоичных файлах методом "пузырька" do { fl=0; //Устанавливаем флаг в 0 //Позиционирование указателей на начало каждого двоичного файла rewind(fd1); rewind(fd2); //Читаем по одной структуре из 1-го и 2-го двоичных файлов fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); //Цикл однократного прохода по файлам //Попарно сравниваем и, при необходимости, обмениваем местами структуры while(!feof(fd1)) { //Читаем еще по одной структуре из каждого файла fread(&so2,sizeof(so2),1,fd1); if(feof(fd1)) break; fread(&sx2,sizeof(sx2),1,fd2); //Сравниваем фамилии if(strcmp(so1.fam,so2.fam)>0) { //Обмен местами двух структур в 1-м файле ft=ftell(fd1)-2*sizeof(so1); fseek(fd1,ft,SEEK_SET); fwrite(&so2,sizeof(so2),1,fd1); fwrite(&so1,sizeof(so1),1,fd1); //Обмен местами двух структур в 1-м файле ft=ftell(fd2)-2*sizeof(sx1); fseek(fd2,ft,SEEK_SET); fwrite(&sx2,sizeof(sx2),1,fd2); fwrite(&sx1,sizeof(sx1),1,fd2); fl++; //Увеличение флага в случае перестановки } //Возвращаем указатель на одну структуру назад в 1-м файле ft=ftell(fd1)-sizeof(so1); fseek(fd1,ft,SEEK_SET); //Чтение очередной структуры из 1-го файла fread(&so1,sizeof(so1),1,fd1); 9 //Возвращаем указатель на одну структуру назад во 2-м файле ft=ftell(fd2)-sizeof(sx1); fseek(fd2,ft,SEEK_SET); //Чтение очередной структуры из 2-го файла fread(&sx1,sizeof(sx1),1,fd2); } }while(fl>0); //Цикл вывода информации о студентах из обоих двоичных файлов //Выход на начало каждого файла rewind(fd1); rewind(fd2); printf("\n\nИнформация о студентах после сортировки\n"); //Читаем по одной структуре из 1-го и 2-го двоичных файлов fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); while(!feof(fd1)) { printf("\n%s %s %d ",so1.fam,so1.name,so1.kurs); for(i=0;i<3;i++) printf("%d ",so1.oc[i]); printf("%c %d",sx1.pol,sx1.god); fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); } //Подсчет среднего балла по математике для юношей и девушек rewind(fd1); rewind(fd2); //Обнуляем кол-ва и суммы kolm=0; kolw=0; srm=0; srw=0; fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); while(!feof(fd1)&&!feof(fd2)) { if(sx1.pol=='м') { kolm++; srm+=so1.oc[1]; } if(sx1.pol=='ж') { kolw++; srw+=so1.oc[1]; } fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); } 10 if(kolm) srm/=kolm; if(kolw) srw/=kolw; if(srm>srw) printf("\n\nМатематику лучше сдали юноши"); else if(srm #include #include #include //Шаблон структуры для хранения записей из первого файла struct stud1 { char fam[16]; char name[13]; int kurs; int oc[3]; }; //Шаблон структуры для хранения записей из второго файла struct stud2 { char fam[16]; char name[13]; char pol; int god; }; void main() { int i, fl, kolm, kolw; //Флаг для сортировки //Кол-во девушек //Кол-во юношей 11 float srm, srw; long ft; FILE *ft1, *ft2, *fd1, *fd2; //Средний балл юношей по математике //Средний балл девушек по математике //Указатель первого текстового файла //Указатель второго текстового файла //Указатель первого двоичного файла //Указатель второго двоичного файла //Буферные структуры stud1 so1, so2; stud2 sx1, sx2; char fnamet1[30]="c:\\user\\oc.txt", fnamet2[30]="c:\\user\\xarakt.txt", fnamed1[30]="c:\\user\\oc.dat", fnamed2[30]="c:\\user\\xarakt.dat"; clrscr(); //Открытие текстовых файлов для чтения if((ft1=fopen(fnamet1,"r"))==NULL) { printf("file %s ne syshestvyet",fnamet1); getch();exit(-1); } if((ft2=fopen(fnamet2,"r"))==NULL) { printf("file %s ne syshestvyet",fnamet1); getch();exit(-1); } //Открытие двоичных файлов одновременно для записи и чтения fd1=fopen(fnamed1,"w+b"); fd2=fopen(fnamed2,"w+b"); //Цикл считывания информации из текстовых файлов в буферные структуры //и записи этих структур в двоичные файлы while(fgets(so1.fam,16,ft1)!=NULL) // Считывается фамилия из 1-го текст. файла { fgets(so1.name,13,ft1); // Считывается имя из 1-го текст. файла fscanf(ft1,"%d",&so1.kurs); // Считывается номер курса for(i=0;i<3;i++) fscanf(ft1,"%d",&so1.oc[i]); // Цикл чтения оценок fscanf(ft1,"\n"); fwrite(&so1,sizeof(so1),1,fd1); // Переход на новую стоку в 1-м файле // Запись структуры в 1-й двоичн. файл fgets(sx1.fam,16,ft2); fgets(sx1.name,13,ft2); sx1.pol=fgetc(ft2); fscanf(ft2, " %d",&sx1.god); fscanf(ft2,"\n"); fwrite(&sx1,sizeof(sx1),1,fd2); } // Считывается фамилия из 2-го текст. файла // Считывается имя из 1-го текст. файла // Считывается пол // Считывается год рождения // Переход на новую стоку во 2-м файле // Запись структуры во 2-й двоичн. файл //Цикл вывода информации о студентах из обоих двоичных файлов //Позиционирование указателей на начало каждого двоичного файла rewind(fd1); 12 rewind(fd2); printf("\nИнформация о студентах до сортировки\n"); fread(&so1,sizeof(so1),1,fd1); //Чтение структуры из 1-го двоичн. файла fread(&sx1,sizeof(sx1),1,fd2); //Чтение структуры из 2-го двоичн. файла while(!feof(fd1)) { printf("\n%s %s %d ",so1.fam,so1.name,so1.kurs); for(i=0;i<3;i++) printf("%d ",so1.oc[i]); printf("%c %d",sx1.pol,sx1.god); fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); } //Сортировка информации в двоичных файлах методом "пузырька" do { fl=0; //Устанавливаем флаг в 0 //Позиционирование указателей на начало каждого двоичного файла rewind(fd1); rewind(fd2); //Читаем по одной структуре из 1-го и 2-го двоичных файлов fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); //Цикл однократного прохода по файлам //Попарно сравниваем и, при необходимости, обмениваем местами структуры while(!feof(fd1)) { //Читаем еще по одной структуре из каждого файла fread(&so2,sizeof(so2),1,fd1); if(feof(fd1)) break; fread(&sx2,sizeof(sx2),1,fd2); if(strcmp(so1.fam,so2.fam)>0) //Сравниваем фамилии { //Обмен местами двух структур в 1-м файле ft=ftell(fd1)-2*sizeof(so1); fseek(fd1,ft,SEEK_SET); fwrite(&so2,sizeof(so2),1,fd1); fwrite(&so1,sizeof(so1),1,fd1); //Обмен местами двух структур в 2-м файле ft=ftell(fd2)-2*sizeof(sx1); fseek(fd2,ft,SEEK_SET); fwrite(&sx2,sizeof(sx2),1,fd2); fwrite(&sx1,sizeof(sx1),1,fd2); fl++; //Увеличение флага в случае перестановки } //Возвращаем указатель на одну структуру назад в 1-м файле ft=ftell(fd1)-sizeof(so1); 13 fseek(fd1,ft,SEEK_SET); //Чтение очередной структуры из 1-го файла fread(&so1,sizeof(so1),1,fd1); //Возвращаем указатель на одну структуру назад во 2-м файле ft=ftell(fd2)-sizeof(sx1); fseek(fd2,ft,SEEK_SET); //Чтение очередной структуры из 2-го файла fread(&sx1,sizeof(sx1),1,fd2); } }while(fl>0); //Цикл вывода информации о студентах из обоих двоичных файлов //Выход на начало каждого файла rewind(fd1); rewind(fd2); printf("\n\nИнформация о студентах после сортировки\n"); //Читаем по одной структуре из 1-го и 2-го двоичных файлов fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); while(!feof(fd1)) { printf("\n%s %s %d ",so1.fam,so1.name,so1.kurs); for(i=0;i<3;i++) printf("%d ",so1.oc[i]); printf("%c %d",sx1.pol,sx1.god); fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); } //Подсчет среднего балла по математике для юношей и девушек rewind(fd1); rewind(fd2); //Обнуляем кол-ва и суммы kolm=0; kolw=0; srm=0; srw=0; fread(&so1,sizeof(so1),1,fd1); fread(&sx1,sizeof(sx1),1,fd2); while(!feof(fd1)&&!feof(fd2)) { if(sx1.pol=='м') { kolm++; srm+=so1.oc[1]; } if(sx1.pol=='ж') { kolw++; srw+=so1.oc[1]; } fread(&so1,sizeof(so1),1,fd1); 14 fread(&sx1,sizeof(sx1),1,fd2); } if(kolm) srm/=kolm; if(kolw) srw/=kolw; if(srm>srw) printf("\n\nМатематику лучше сдали юноши"); else if(srm
«Структуры: шаблон структуры; структурные переменные» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot