Краткий конспект семинарских занятий по языку C - Н.Д. Васюкова_ И.В. Машечкин_ В.В.Тюляева_ Е.М.Шляховая, страница 3
Описание файла
Документ из архива "Краткий конспект семинарских занятий по языку C - Н.Д. Васюкова_ И.В. Машечкин_ В.В.Тюляева_ Е.М.Шляховая", который расположен в категории "". Всё это находится в предмете "операционные системы" из 3 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Краткий конспект семинарских занятий по языку C - Н.Д. Васюкова_ И.В. Машечкин_ В.В.Тюляева_ Е.М.Шляховая"
Текст 3 страницы из документа "Краткий конспект семинарских занятий по языку C - Н.Д. Васюкова_ И.В. Машечкин_ В.В.Тюляева_ Е.М.Шляховая"
p1=s; p2=t;
while( *p2++=*p1++);
Задачи.
-
Конкатенировать строки (аналог функции strcat).
-
Сравнить строки (аналог функции strcmp).
-
Присвоить переменной единицу, если одна строка содержится в конце другой, и ноль в противном случае.
-
Поменять местами первый отрицательный элемент вещественного массива m1 с последним положительным элементом вещественного массива m2.
-
Изменить знак у всех отрицательных элементов вещественного массива X.
-
Определить, у скольких элементов целочисленного массива X равные соседи(предыдущий и последующий элементы). Записать ответ в переменную n.
-
Проверить на равенство строки s1 и s2 при условии, что пробелы не учитываются.
-
Описаны 2 строки:
char s[255], t[10];
Подсчитать количество вхождений строки t в строку s, ответ записать в переменную count, а переменной last присвоить индекс начала последнего вхождения.
-
Описаны 2 строки:
char s[200], t[200];
Все цифры строки s записать в начало строки t, а остальные символы – в конец (в любом порядке).
-
Упорядочить вещественный массив х по неубыванию, используя метод сортировки выбором (найти максимальный элемент массива и переставить его с последним элементом; затем применить этот же метод ко всем элементам, кроме последнего).
-
Упорядочить вещественный массив х по неубыванию, используя метод сортировки обменом ("метод пузырька") (последовательно сравнивать пары соседних элементов: x1 с x2, х2 с х3 и т.д., и если первый элемент пары больше второго, то переставлять их – наибольший элемент окажется в конце массива; затем применить этот же метод ко всем элементам, кроме последнего).
-
Упорядочить вещественный массив х по неубыванию, используя метод сортировки вставками (пусть первые k элементов уже упорядочены по неубыванию; взять (k+1)-ый элемент и разместить его между первыми k, не нарушая порядок).
ТЕМА 4. Понятие функции. Оператор return. Понятие прототипа функции. Механизм передачи параметров.
В стандарте ANSI C представлено два способа описания и определения функций, так называемые «новая» (введенная стандартом) и «старая» (используемая до принятия стандарта) нотации.
Согласно новой нотации определение любой функции имеет следующий вид:
[<тип результата>]<имя функции>([список параметров])
{ [декларации]
[операторы]
}
Согласно старой нотации функция определяется следующим образом:
[<тип результата>]<имя функции>([список имен парам.])
[описание параметров]
{ [декларации]
[операторы]
}
В этом случае в круглых скобках после имени функции перечисляются имена параметров, а их типы задаются перед первой открывающей фигурной скобкой. Функция может возвращать одно значение, тип которого указывается в заголовке, а само значение задается выражением в операторе return:
return <выражение>;
Оператор return возвращает управление вызвавшей функции.
Если возвращаемое значение имеет тип int, то тип результата можно не указывать. Функция может и не возвращать значение, тогда вместо типа результата следует писать void.
В стандарт Си было добавлено средство контроля за соответствием фактических параметров в вызове функции ее формальным параметрам. В начале программного файла, как правило, для всех функций, кроме main, задаются прототипы. Синтаксически прототип повторяет заголовок функции. При отсутствии прототипа функции, если в выражении встретилось имя, нигде ранее не описанное, за которым следует открывающая скобка, такое имя считается именем функции, возвращающей значение типа int. При несоответствии типов формальных и фактических параметров автоматическое приведение типов не осуществляется, что приводит к ошибочному результату. А при наличии прототипа функции все приведения типов осуществляются автоматически. Согласованность имен параметров в прототипе и в определении функции не требуется, могут быть указаны только типы параметров без имен.
В случае старой нотации в прототипе функции параметры не указываются, и компилятор не может обнаружить ошибок при несоответствии количества формальных и фактических параметров или их типов. Пример описания и определения функции в новой и в старой нотациях:
Аргументы функции передаются по “значению”. Если аргументом является имя массива, то функции передается копия адреса начала этого массива, а сам массив не копируется. Нельзя передать целиком сам массив функции и таким образом:
int arr[10];
...
f(*arr);
В этом случае функция f получит в качестве фактического значения аргумента значение нулевого элемента массива.
Задача1. Написать функцию, суммирующую два вещественных значения в двух вариантах: сумма – возвращаемое значение функции и сумма – параметр функции.
. . .
double sum1(double,double);/* прототип
функции sum1*/
void sum2(double,double,double*); /* прототип
функции sum2*/
main()
{ double a1=2.5, u;
int a2=3;
u=sum1(a1,a2);
printf(“u=%f\n”,u); /* u=5.5 */
sum2(a1,a2,&u);
printf(“u=%f\n”,u); /* u=5.5 */
}
double sum1(double x,double y)
{ return x+y; }
void sum2(double x,double y,double *z)
{ *z=x+y; }
Задача 2. Написать функцию суммирования двух целочисленных векторов.
. . .
void sum_vec(int*,int*,int*,int);
main()
{ int m1[20],m2[20],m3[20],i;
. . .
sum_vec(m1,m2,m3,20);
for(i=0;i<20;i++)
printf(“m3[%d]=%d\n”,i,m3[i]);
}
void sum_vec(int x[],int *y,int z[],int k)
{ int i;
for(i=0;i<k;i++)
*z++=x[i]+y[i]; /*z[i]=x[i]+y[i];*/
}
Список формальных параметров функции может быть переменной длины – в этом случае он заканчивается “, …” и должен содержать хотя бы один именованный параметр. Примером такой функции является функция печати printf, описанная в stdio.h:
int printf(const char *format, …);
Для работы с параметрами, количество и тип которых заранее не известны, используется механизм макросов из файла стандартной библиотеки <stdarg.h>. В теле функции заводится переменная типа va_list – указатель на очередной неименованный аргумент. Доступ к неименованным параметрам через переменную типа va_list возможен только после обращения к макросу va_start. Макрос va_start получает два параметра - переменную типа va_list и последний именованный параметр функции и инициализирует переменную типа va_list так, чтобы она указывала на первый неименованный параметр:
int f(p1, p2, ...)
{
va_list parg;
va_start(parg, p2);/* p2 – последний
именованный параметр функции f */
int i = va_arg(parg, int);
...
va_end(parg);
}
Далее, каждое обращение к макросу va_arg выдает очередной параметр и передвигает указатель (переменную типа va_list) на следующий параметр. К макросу va_arg обращаются с двумя параметрами – переменной типа va_list, проинициализированной с помощью va_start, и именем типа возвращаемого параметра. Макрос va_end нужен для корректного завершения работы с переменной типа va_list.
Поскольку функции не известны ни типы передаваемых неименованных параметров, ни их количество, то для корректной работы с такими параметрами может использоваться различная дополнительная информация. Например, как в случае функции printf, параметр format полностью определяет типы и число последующих параметров. Другой способ – передавать через фиксированный параметр количество неименованных параметров.
Пример: Написать функцию, возвращающую максимальный из полученных ею фактических параметров (типа unsigned int).
#include <stdio.h>
#include <stdarg.h>
unsigned int unsgn_max(unsigned int count, ...);
/* Число неименованных параметров передается через параметр count и не учитывается при поиске максимума. */
main()
{
printf(“max = %d\n”,
unsgn_max (3, 10, 20, 30));
}
unsigned int unsgn_max(unsigned int count, ...)
{
va_list ap;
unsigned int res = 0, cur;
int i;
va_start(ap, count);
for(i=1; i<=count; i++)
if(res < (cur = va_arg(ap,uinsigend int)))
res = cur;
va_end(ap);
return res;
}
Задачи.
-
Дан массив, содержащий заданное количество вещественных чисел. Написать функцию, возвращающую максимальное значение этого массива.
-
Даны целочисленные массивы X и Y , содержащие по 20 элементов. Написать функцию, которая возвращает значение u.
-
Написать аналог функции strstr , которая возвращает указатель на первое вхождение одной строки в другую и нулевой указатель в противном случае. Используя функцию strstr, найти последнее вхождение строки “end” во введенной строке. Распечатать символы, которые следуют за этим вхождением.
-
Написать функцию, упорядочивающую вещественный массив. Число элементов массива и сам массив передать в качестве параметров.
-
Написать функцию getletter(), читающую одну литеру из стандартного ввода с помощью getchar() и возвращающую введенную литеру, если это большая или малая латинская буква, и –1 в противном случае.
-
Описать функцию, определяющую, сколько элементов вещественного массива X из n элементов равны числу у.
-
Написать функцию, которой передаются 2 100-элементных вещественных массива, определяющую, составлены ли эти 2 массива из одних и тех же чисел без учета порядка их следования, но с учетом повторяющихся чисел(функция возвращает 1 в случае положительного ответа).
-
Написать функцию, которая за 1 просмотр циклически сдвигает полученный вещественный массив на 20 позиций влево (функция для работы должна использовать вспомогательный массив).
-
Написать функцию, вычисляющую n-ое число Фибоначчи (n>=0) по правилу:
ТЕМА 5. Общая структура программного файла. Области видимости и существования переменных. Препроцессор.
Программа может размещаться как в одном, так и в нескольких файлах, содержать одну или несколько функций, одна из которых считается головной (main), с нее начинается выполнение программы. Определение каждой функции размещается полностью в одном файле, но файл может содержать несколько определений различных функций.
В соответствии со структурой программы переменные могут обладать следующими качествами:
-
видимость переменной (область видимости);
-
существование переменной (область существования).
Область видимости переменной определяет текстовое пространство программы (оно не обязательно непрерывно), из любой точки которого доступна данная переменная с данным именем. С точки зрения видимости можно выделить следующие группы переменных:
-
видимые в пределах блоков,
-
видимые в пределах файла,
-
видимые в пределах программы.
Для переменных, определенных внутри функции в начале любого блока, областью видимости является весь этот блок. В случае вложенных блоков переменные, определенные внутри вложенного блока, “перекрывают” переменные с такими же именами, определенные в объемлющем блоке (и так для любой степени вложенности). Например:
main()
{ int x = 1;
if(x>0)
{ int x = 2;
printf(“x = %d\n”, ++x); /*выводит: x = 3 */
}
printf(“x = %d\n”, x); /*выводит: x = 1 */
}
Переменные, определенные внутри функции, “перекрывают” формальные параметры с теми же именами4:
int f(int f)
{
int f = 1;
…
}
Переменные, определенные вне блоков, доступны с точки определения до конца файла. Если на такую переменную нужно сослаться до того, как она определена, должно быть ее описание со спецификатором extern, например:
int x;