progr_su_4.ppt
- Количество слайдов: 68
Управление памятью программы Области памяти программы: Сегмент кода Статическая память (сегмент данных) Стек Динамическая память (куча)
Динамическое распределение памяти в С malloc void* malloc(size_t size); calloc void* calloc(size_t num, size_t size); realloc void* realloc(void* ptr, size_t size); free void free(void* ptr);
Пример создания динамической переменной int num, *i. Ptr ; i. Ptr = malloc(4); /* malloc(sizeof(num)) */ scanf("%d", i. Ptr); printf("Number: %dn", *i. Ptr); free(i. Ptr); i. Ptr = NULL;
Проверка выделения памяти double* ptr; int max = 4; ptr = (double*) malloc(max * sizeof (double)); if (ptr == NULL) printf('' Ошибка выделения памяти!''); else { /* вычисления */ free (ptr); }
Еще вариант контроля #include <stdlib. h> int main (void) { double* ptr; int max = 4; if ((ptr = (double*) malloc(max * sizeof (double))) == NULL) { printf('' Ошибка выделения памяти!''); exit (EXIT_FAILURE); /* stdlib. h EXIT_SUCCESS*/ } // вычисления free (ptr); }
Пример создания строки в динамической памяти char buffer[200], *st. Ptr; scanf("%s", buffer); int len = strlen(buffer); st. Ptr = malloc(len+1); strcpy(st. Ptr, buffer); printf("String: %sn", st. Ptr); free(st. Ptr); st. Ptr = NULL;
Создание динамических переменных в C++ Операторы С++: 1. new — выделение динамической памяти для одной переменной 2. new[ ] — выделение динамической памяти для массива 3. delete — освобождение динамической памяти из-под переменной (кроме массива) 4. delete[ ] - освобождение динамической памяти из-под массива
Пример программы с динамической переменной #include <iostream> using namespace std; int main() { float *iptr; // объявление переменной-указателя iptr = new float; // выделение динамической памяти cout << "enter one number->"; cin >> *iptr; // ввод числа в динамич. переменную cout << *iptr; // вывод из динамич. переменной delete iptr; // освобождение памяти iptr=NULL; return 0; }
Массив в динамической памяти #include <iostream> using namespace std; int main() { float *mptr; int n = 3, i; // выделение памяти mptr = new float[n]; // заполнение массива for(i=0; i<n; i++) { cout << "enter number->"; cin >> *(mptr+i); } // вывод массива for(i=0; i<n; i++) cout << *(mptr+i); // освобождение памяти delete[ ] mptr; mptr = NULL; return 0; }
Проверка выделения памяти int max = 4; double* ptr = new double[max]; if (ptr == NULL) cout <<'' Ошибка выделения памяти!''; else { /* вычисления */ delete[ ] ptr; }
Задача Создать тип структуры из трех полей: Наименование товара, цена единицы товара, количество. Создать массив структур в динамической памяти, ввести в него данные с клавиатуры. Вычислить общую стоимость товара. Введенный массив и результат вычислений вывести на экран. Ввод, вывод и обработку массива выполнить с помощью функций.
Классы хранения переменных Переменные отличаются временем жизни и областью видимости 1. auto — автоматические (стек) 2. static — статические (сегмент данных данного модуля) static double a; 3. register — регистровые (регистр процессора) register int b = 45; 4. extern — внешние (сегмент данных другого модуля) extern float c;
Статическая переменная #include <stdio. h> void counter(); int main() { for(i=0; i<5; i++) counter(); return 0; } На экране: Текущее значение статич. переменной 1 Текущее значение статич. переменной 2 Текущее значение статич. переменной 3 Текущее значение статич. переменной 4 Текущее значение статич. переменной 5 void counter() { static int count=0; count++; printf(''Текущее значение статич. переменной %dn', count'); }
Регистровая переменная /* main. c*/ #include <stdio. h> int main() { register int reg = 45; scanf("%d", ®); /* ошибка! */ printf("REG: %d %pn", reg, ®); /* ошибка! */ return 0; }
Внешние переменные int a=10; int b = 15; extern int a; extern int b; int c = a + b; Модуль 1 Модуль 2
Пример использования внешней /* modul. h */ переменной #ifndef MODUL_H_INCLUDED #define MODUL_H_INCLUDED int summa(int c, int d); #endif // MODUL_H_INCLUDED /*modul. c*/ #include "modul. h" int a = 10; int b = 15; /*main. c*/ #include <stdio. h> #include "modul. h" extern int a; int main() { extern int b; a+=2; b+=3; printf("%dn", summa(a, b)); return 0; int summa(int c, int d) { return c+d; } }
Задача: найдите ошибки в программе //main. cpp int main() { extern int a; extern int d; printf("%d %d %dn", f(a), b(a), a+d); return 0; } //modul. cpp int a = 10; int b(int c){ static int d=9; d+=c; return d; } int f(int c){ int g = 1; g*= c; return g; }
Файловый ввод/вывод 1. Файл — именованный раздел для сохранения информации. 2. Файлы в программе представлены переменными. 3. Файл — последовательность байтов. 4. Файлы двоичные и текстовые. 5. Стандартные файлы: stdin — стандартный поток ввода stdout — стандартный поток вывода stderr — стандартный поток ошибок
Структура типа FILE Объявление файловой переменной: FILE * file ; Информация, хранимая структурой типа FILE: указатель текущей позиции в файле признак конца файла ( EOF) индикаторы ошибок сведения о буферизации
Функции для работы с файлами fopen ( ) - открытие файла FILE* fopen(const char *filename, const char *mode); fseek ( ) - перемещение по файлу int fseek(FILE* file, long int offset, int whence); ftell ( ) - определение текущего положения в файле long int ftell (FILE* file); fclose ( ) - закрытие файла (0 — файл закрыт) int fclose (FILE* file); feof ( ) - возвращает состояние индикатора конца файла (<>0 — конец файла достигнут) int feof (FILE* file);
Режимы открытия файлов ''w'' — создание нового файла ''r'' — открытие файла для чтения ''a'' — открытие файла для записи в конец ''t'' — открытие текстового файла ''b'' — открытие двоичного файла ''+'' - открытие файла на чтение и запись FILE* fl = open(''My. txt'', ''r''); FILE* fl = open(''My. txt'', ''r+''); FILE* fl = open(''My. txt'', ''wb+''); FILE* fl = open(''My. txt'', ''a+'');
Функции чтения и записи 1. getc ( ) - чтение символа из файла putc ( ) - запись символа в файл 2. fgets ( ) - чтение строки из файла fputs ( ) - запись строки в файл 3. fscanf ( ) - форматированный ввод из файла fprintf ( ) - форматированный вывод в файл 4. fread ( ) - блоковый (двоичный) ввод fwrite ( ) - блоковый (двоичный) вывод
Функции getc ( ) и putc ( ) int getc (FILE* file); int putc (int c, FILE* file); char ch; FILE* file; file = fopen (''my. txt'', ''r''); ch = getc (file); while (ch != EOF) { putchar (ch); ch = getc (file); } Возвращают код прочитанного или записанного в файл символа или EOF
Посимвольное копирование строки FILE *in, *out; int ch; if ((in = fopen(''in. txt'', ''r'')) == NULL) { printf (''Входной файл не открытn''); exit(1); } if ((out = fopen(''out. txt'', ''w'')) == NULL) { printf (''Файл на запись не открытn''); exit(2); } while ((ch = getc (in)) != EOF) putc (ch, out); if (fclose (in) != 0 || fclose (out) != 0) printf (''Ошибка при закрытии файлов''); return 0;
Функции fgets ( ) и fputs ( ) #include <stdio. h> char* fgets (char* s, int n, FILE* file); #define MAXLINE 10 возвращает указатель на прочитанную строку или NULL int main ( ) int fputs (const char* st, FILE* file); { возвращает код последнего записанного char line [MAXLINE]; символа или EOF FILE *in, *out; if ((in = fopen (''mystr. txt'', ''r'')) ==NULL) { printf(''Входной файл не открытn''); exit (1); } while (fgets(line, MAXLINE, in) != NULL) { puts(line); fputs(line, out); } fclose (in); fclose (out); return 0; }
Функции fscanf ( ) и fprintf ( ) int fscanf (FILE* file, const char* format, . . . ); int fprintf (FILE* file, const char* format, . . . ); fscanf возвращает количество заполненных переменных fprintf возвращает количество записанных в файл байтов int num=15; double f=2. 6; char st[20]=''numbers: ''; FILE* out = fopen(''my. txt'', ''w''); fprintf(in, ''%20 s%6 d%6. 2 lf'', st, num, f); fclose(out);
Чтение массива из файла #include <stdio. h> #include <stdlib. h> #define N 5 int main() { int mas[N], i=0; FILE* in; if((in=fopen("num. txt", "r"))==NULL) { printf("File not foundn"); exit(1); } while(!feof(in)) { fscanf(in, "%d", mas+i); printf("%d %dn", i, mas[i]); i++; } fclose(in); return 0; }
Проверка чтения из файла FILE* file; char st[100]; double num; if ((file = fopen(''text. txt'', ''r''))==NULL) { fprintf(stderr, ''Ошибкаn''); exit(1); } while (fscanf (file, ''%s%lf'', st, &num) == 2) printf (''%s %lfn'', st, num); fclose (file);
Функции fread ( ) и fwrite ( ) size_t fread (void* ptr, size_t size, size_t number, FILE* file); size_t fwrite (void* ptr, size_t size, size_t number, FILE* file); Возвращают количество прочитанных/записанных элементов (<=number) или EOF double mas[4] = {0. 5, 0. 9, 1. 8, 3. 7}; FILE* file; file = fopen (''num'', ''w''); fwrite(mas, sizeof(double), 4, file); fclose(file);
Задача В текстовом файле записаны несколько чисел. Написать программу, которая читает файл в массив, увеличивает значения чисел на 10 и сохраняет в текстовый файл, потом увеличивает числа еще на 10 и сохраняет в двоичный файл.
Текст программы (1) #include <stdio. h> #define N 100 int main() { FILE *fin, *bfout, *tfout; int mas[N]; int i, n; fin=fopen("in. txt", "r");
Текст программы (2) if(fin!=NULL) { i=0; while(!feof(fin)) { fscanf(fin, "%d", mas+i); i++; if (i>=N) break; } fclose(fin);
Текст программы (3) n=i; //printf("N=%d i=%dn", N, n); for(i=0; i<n; i++) printf("%8 d", *(mas+i)); printf("n"); tfout=fopen("t. txt", "w"); bfout=fopen("b. txt", "wb");
Текст программы (4) for(i=0; i<n; i++) { *(mas+i)+=10; fprintf(tfout, "%6 d", *(mas+i)); *(mas+i)+=10; } fwrite(mas, sizeof(int), n, bfout); fclose(tfout); }
Текст программы (5) else printf("File not foundn"); return 0; }
Работа с файлом в режиме чтения и записи (1) #include <stdio. h> #include <stdlib. h> #define N 100 int main(void) { FILE *fin=fopen("b. txt", "rb+"); int mas[N]; int* ptr=mas; int i, n;
Работа с файлом в режиме чтения и записи (2) if(fin!=NULL) { i=0; while(!feof(fin)&&i<N) { if(fread((void*)ptr, sizeof(int), 1, fin)) { i++; ptr++; } } n=i; printf("%8 dn", n);
Работа с файлом в режиме чтения и записи (3) for(i=0; i<n; i++) printf("%8 dn", *(mas+i)); printf("!!!!n"); fseek(fin, 2*sizeof(int), SEEK_SET); int num; scanf("%d", &num); int tmp; fwrite(&num, sizeof(int), 1, fin); // fflush(fin);
Работа с файлом в режиме чтения и записи (4) fseek(fin, 2*sizeof(int), SEEK_SET); fread(&tmp, sizeof(int), 1, fin); printf("Position: %ld Number: %dn", ftell(fin), tmp); fclose(fin);
Работа с файлом в режиме чтения и записи (5) FILE *fin 2=fopen("b. txt", "rb"); int mas 2[N]; if(fin 2!=NULL) { fread((void*)mas 2, sizeof(int), n, fin 2); for(i=0; i<n; i++) printf("%8 d", *(mas+i)); printf("n"); fclose(fin 2); } }
Работа с файлом в режиме чтения и записи (6) else printf("File not found!n"); return 0; }
Рекурсия Прямая рекурсия int A( ) { … A ( ); . . . } Косвенная рекурсия int B( ); int A( ) { … B ( ); . . . } int B( ) { … A ( ); . . . }
Рекурсивная функция А( ) { если (условие выполнено) { любые действия вызов А( ) } иначе действия }
Вычисление факториала double fact(int n); int main(void) { int num = 5; printf(''%d ! = %lfn'', num, fact(num)); return 0; } double fact(int n) { double res; printf(''Вычисляю %d!n'', n); if (n > 1) res = n * fact (n-1); else res = 1; printf(''%lfn'', res); return res; } Рекурсивная формула: n! = n * (n-1)! Сообщения на экране: Вычисляю 5! Вычисляю 4! Вычисляю 3! Вычисляю 2! Вычисляю 1! 1 2 6 24 120 5! = 120
Вычисление суммы цифр целого #include <stdio. h> числа int sum_rec(int); int main(void) { int number; scanf("%d", &number); printf("sum = %dn", sum_rec(number)); return 0; } int sum_rec(int n) { int sum; if (n>9) sum = n%10+sum_rec(n/10); else sum = n; return sum; }
Функция с переменным числом аргументов Прототип функции: return_type fn_name(type arg 1, . . . ); Примеры стандартных функций: int scanf (const char* format, . . . ); int printf (const char* format, . . . );
Функция пользователя с переменным числом аргументов #include <stdio. h> void example(int, . . . ); int main() { int var 1=5, var 2=6, var 3=7, var 4=8; example(1, var 1); example(3, var 1, var 2); example(5, var 1, var 2, var 3, var 4); return 0; }
Функция пользователя с переменным числом аргументов (2) void example(int arg 1, . . . ) { int* ptr=&arg 1; printf("Number of arguments: %dn", arg 1); for(; arg 1 --) { printf("%6 d", *ptr); ptr++; } printf("n---------n"); }
Задача Написать функцию с переменным числом аргументов, вычисляющую сумму аргументов. Написать программу для вычисления суммы нескольких чисел с помощью этой функции.
Функции преобразования типов данных atoi — преобразование строки в целое число типа integer atol - преобразование строки в целое число типа long strtol — преобразование строки в число типа long strtof — преобразование строки в число типа float (С 99) strtod — преобразование строки в число типа double sprintf - запись в строку данных любых типов (чисел, символов, строк)
Функции atoi, atol и atof int atoi (const char* st); long int atol (const char* st); double atof (const char* st); На экране: 1994 199 0 0 char str 1[20] = ''1994''; int year 1 = atoi(str 1); char str 2[20] = ''199 rty''; int year 2 = atoi(str 2); char str 3[20] = ''ert''; int year 3 = atoi(str 3); char str 4[20] = ''0''; int year 4 = atoi(str 4); printf(''%d %dn'', year 1, year 2, year 3, year 4);
Функции strtol, strtof, strtod long int strtol(const char* st, char** error, int base); float strtof(const char* st, char** error); double strtod(const char* st, char** error); Ввод: 12. 78 На экране: 12. 78 double num; char str[20]; Ввод ty 1. 7 char* error; На экране: gets(str); Ввод 1. 7 ty num = strtod(str, &error); На экране: if (*error == NULL) printf (''%lf'', num); else printf (''%s'', error); ty 1. 7 ty
Функция sprintf ( ) int sprintf(char* new_string, char* format, …); char name[20] = ''Nick''; int year = 1994; float weight = 65. 5; char str[20+5+5]; sprintf(str, ''%s : %d %4. 1 f'', name, year, weight); puts (str);
Операторы языка С
Инкремент и декремент Префиксный инкремент ++A Префиксный декремент --A Постфиксный инкремент A++ Постфиксный декремент A- - int A = 10, B=12; int C = A++; int D = ++B; printf(''A=%d B=%d C=%d D=%dn'', A, B, C, D); /* A=11 B=13 C=10 D=13 */
Префиксный и постфиксный декременты в арифметическом выражении int a=7, b=7; a--; /* постфиксный декремент */ --b; /* префиксный декремент */ printf(''a=%d b=%d summa=%d'', a, b, a+b); Ответ: a=6 b=6 summa=12 int a=7, b=7; int c=--a+b; int d=a+b--; printf(''a=%d b=%d c=%d d=%d'', a, b, c, d); Ответ: a=6 b=6 c=13 d=13
Поразрядные операции unsigned int A, B; ~A — НЕ (инверсия) A&B — И (умножение) A|B — ИЛИ (сложение) A^B — исключающее ИЛИ (сложение по модулю 2)
Поразрядное НЕ unsigned short A = 46, C = ~A;
Поразрядное И unsigned short A = 46, B = 29, D = A & B;
Поразрядное ИЛИ unsigned short A = 46, B = 29, E = A | B;
Поразрядное исключающее ИЛИ unsigned short A = 46, B = 29, F = A ^ B;
Задача Число хранится в переменной A типа unsigned short. Она используется в выражении вида C=A op B, которое позволяет изменить значение 3 -5 битов: 1. на значение 0, 2. на значение 1, 3. на противоположные значения. Определить, какой оператор op должен быть использован в каждом случае и какое значение должна иметь переменная B.
Операции сдвига unsigned short A = 46, G; G = A << 2; unsigned short A = 46, H; H = A >> 3;
Условная (тернарная) операция int A = 12, B = 10; int C = A < B ? B : A; printf(''%d'', C); Ответ: 12 Задача Даны 3 переменные, содержащие целые числа. Определить максимальное число. НЕ использовать инструкцию if.
progr_su_4.ppt