Прототип функции в программе на языке си.

      Комментарии к записи Прототип функции в программе на языке си. отключены

В языке Си необходимо до первого вызова обращения к функции сообщить программе тип возвращаемого функцией значения, а также количество и типы ее аргументов. Подобное сообщение называется прототипом функции.

Прототип функции имеет следующий вид

тип(список параметров)

Использование прототипа называют еще объявлением функции или просто ее declaration. Прототип может полностью совпадать с заголовком функции, хотя при объявлении функции компилятору необходимо знать только имя функции, количество аргументов и их типы и тип возвращаемого функцией значения. Поэтому имена аргументов как имена формальных параметров не имеют никакого значения и игнорируются компилятором.

Поэтому прототип функции может иметь один из следующих видов:

int fun1(int x, int y, char* c); или int fun1(int, int, char*);

Вызов функции это выражение, которое передает управление и действительные аргументы, если они есть, функции. В вызове функции выражение вычисляется для получения адреса функции, а список-выражений это список разделенных запятыми выражений. Значения этих выражений являются действительными аргументами, передаваемыми в функцию. Если у функции нет аргументов, то список выражений может быть пустым.

Вопрос 33

Массивы — это группа элементов одинакового типа (double, float, int и т.п.). Из объявления массива компилятор должен получить информацию о типе элементов массива и их количестве. Объявление массива имеет два формата:

спецификатор-типа описатель [константное — выражение];

спецификатор-типа описатель [ ];

Описатель — это идентификатор массива .

Спецификатор-типа задает тип элементов объявляемого массива. Элементами массива не могут быть функции и элементы типа void.

Константное-выражение в квадратных скобках задает количество элементов массива. Константное-выражение при объявлении массива может быть опущено в следующих случаях:

— при объявлении массив инициализируется,

— массив объявлен как формальный параметр функции,

— массив объявлен как ссылка на массив, явно определенный в другом файле.

В языке СИ определены только одномерные массивы, но поскольку элементом массива может быть массив, можно определить и многомерные массивы. Они формализуются списком константных-выражений следующих за идентификатором массива, причем каждое константное-выражение заключается в свои квадратные скобки.

Каждое константное-выражение в квадратных скобках определяет число элементов по данному измерению массива, так что объявление двухмерного массива содержит два константных-выражения, трехмерного — три и т.д. Отметим, что в языке СИ первый элемент массива имеет индекс равный 0.

Вопрос 34

Массивы символов — это группа элементов одинакового типа (char)

Синтаксис объявления имеет вид:

char ID [N];

где ID – идентификатор массива, N – длина массива, при этом в памяти для хранения строки выделяется N байт.

Например, для переменной char ST[10] в памяти выделяется 10 байт, что дает возможность сформировать строку из 9 символов. Для таких строк действуют все правила представления и обработки массивов.

Идентификатор массива – константа типа указатель, значение которой равно адресу первого элемента массива.

Инициализация возможна двумя способами:

  • посимвольная инициализация char st[10]={‘y’,’e’,’s’,’\0′};

при этом оставшиеся 6 позиций не будут заполнены;

  • инициализация на основе строковой константы char st [10]=Yes;

при этом в выделенную для строки память будут помещены 3 символа и добавлен четвертый – символ ‘\0’.

Инициализация и объявление возможны без указания длины массива char st[]={‘y’,’e’,’s’,’\0′};

в этом случае будет создан массив из четырех элементов.

Вопрос 35

В языке СИ определены только одномерные массивы, но поскольку элементом массива может быть массив, можно определить и многомерные массивы. Они формализуются списком константных-выражений следующих за идентификатором массива, причем каждое константное-выражение заключается в свои квадратные скобки.

Каждое константное-выражение в квадратных скобках определяет число элементов по данному измерению массива, так что объявление двухмерного массива содержит два константных-выражения, трехмерного — три и т.д. Отметим, что в языке СИ первый элемент массива имеет индекс равный 0.

Примеры:

int a[2][3]; /* представлено в виде матрицы

a[0][0] a[0][1] a[0][2]

a[1][0] a[1][1] a[1][2] */

double b[10]; /* вектор из 10 элементов имеющих тип double */

int w[3][3] = { { 2, 3, 4 },

{ 3, 4, 8 },

{ 1, 0, 9 } };

В последнем примере объявлен массив w[3][3]. Списки, выделенные в фигурные скобки, соответствуют строкам массива, в случае отсутствия скобок инициализация будет выполнена неправильно.

Вопрос 36

Указатель — это переменная, содержащая адрес переменной.

двумерный массив — это индексированная переменная, которая определяется двумя индексами. Первый ее индекс- показывает порядковый номер строки, а второй индекс показывает номер столбца. Ниже в таблице Вы видите обозначение каждого элемента двумерного массива (матрицы).

a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]

Количество байт памяти, которое необходимо для хранения массива, вычисляется по формуле:
Количество байт =**
Например, если массив содержит натуральные числа от 1 до 255, каждое из которых, как известно, занимает по 1 байту памяти, то массив, состоящий из трех строк и четырех столбцов, занимает 12 байт ( 1 байт * 3 строки * 4 столбца ) памяти. В таблице слева вы видите, что под массив размером: 3 строки на 4 столбца отведено 12 клеточек. Каждая клеточка условно изображает один байт. Обратите внимание на обозначение элементов массива. Здесь: a — это имя массива, и далее первый индекс в квадратных скобках — номер строки, второй индекс в квадратных скобках — номер столбца.
Напомним, что в Си многомерный массив обозначается следующим образом: тип[размер1][размер2]…[размерN].
Поэтому одномерный массив будет иметь следующее описание: тип[размер]. Например: int a[100]. Данный массив содержит 100 целых чисел. В Си индексы нумеруются от нуля. Таким образом, здесь элементы имеют коды: a[0], a[2], …, a[99].
В памяти компьютера массив располагается непрерывно по строкам: так упомянутый выше двумерный массив представляет собой вытянутый в линию непрерывную строку: a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], a[1][1], a[1][2], a[1][3], a[2][0], a[2][1], a[2][2], a[2][3].

Вопрос 36

Указатели в языке программирования Си. Операции с указателями, адресная арифметика. Взаимосвязь массивов и указателей.

Унарный операторвыдает адрес объекта, так что инструкция

p = c;

присваивает переменной p адрес ячейки c (говорят, что p указывает на c). Операторприменяется только к объектам, расположенным в памяти: к переменным и элементам массивов. Его операндом не может быть ни выражение, ни константа, ни регистровая переменная.

Унарный оператор * есть оператор косвенного доступа. Примененный к указателю он выдает объект, на который данный указатель указывает. Предположим, что x и y имеют тип int, а ip – укаэатель на int. Следующие несколько строк придуманы специально для того, чтобы показать, каким образом объявляются указатели и как используются операторыи *.

int х = 1, у = 2, z[10];

int *ip; /* ip — указатель на int */

ip = x; /* теперь ip указывает на x */

y = *ip; /* y теперь равен 1 */

*ip = 0; /* x теперь равен 0 */

ip = z[0]; /* ip теперь указывает на z[0] */

Объявления x, y и z нам уже знакомы. Объявление указателя ip

int *ip;

Если p есть указатель на некоторый элемент массива, то p++ увеличивает p так, чтобы он указывал на следующий элемент, а p+=i увеличивает его, чтобы он указывал на i-й элемент после того, на который указывал ранее. Эти и подобные конструкции — самые простые примеры арифметики над указателями, называемой также адресной арифметикой.

В Си существует связь между указателями и массивами, и связь эта настолько тесная, что эти средства лучше рассматривать вместе. Любой доступ к элементу массива, осуществляемый операцией индексирования, может быть выполнен с помощью указателя. Вариант с указателями в общем случае работает быстрее, но разобраться в нем, особенно непосвященному, довольно трудно.

Объявление

int a[10];

Определяет массив a размера 10, т. е. блок из 10 последовательных объектов с именами a[0], a[1], …, a[9].

Запись a[i] отсылает нас к i-му элементу массива. Если pa есть указатель на int, т. е. объявлен как

int *pa;

то в результате присваивания

pa = a[0];

pa будет указывать на нулевой элемент a, иначе говоря, pa будет содержать адрес элемента a[0].

Теперь присваивание

x = *pa;

будет копировать содержимое a[0] в x.

Если pa указывает на некоторый элемент массива, то pa+1 по определению указывает на следующий элемент, pa+i — на i-й элемент после pa, a pa-i — на i-й элемент перед pa. Таким образом, если pa указывает на a[0], то

*(pa+1)

есть содержимое a[1], a+i — адрес a[i], a *(pa+i) — содержимое a[i].

Вопрос 37

Варианты описания массивов в языке программирования Си. Аргументы функции main.

Примеры:

int a[2][3]; /* представлено в виде матрицы

a[0][0] a[0][1] a[0][2]

a[1][0] a[1][1] a[1][2] */

float b[10]; /* вектор из 10 элементов имеющих тип double */

int w[3][3] = { { 2, 3, 4 },

{ 3, 4, 8 },

{ 1, 0, 9 } };

В последнем примере объявлен массив w[3][3]. Списки, выделенные в фигурные скобки, соответствуют строкам массива, в случае отсутствия скобок инициализация будет выполнена неправильно.

В языке C заданы два встроенных аргумента функции main: argc и argv.

Выглядит это так:

int main(int argc, char *argv[])

Аргумент argc типа integer содержит в себе количество аргументов командной строки.

Аргумент argv типа char — указатель на массив строк. Каждый элемент массива указывает на аргументы командной строки. Один параметр отделяется от другого пробелами.

argv[0] — полное имя запущенной программы

argv[1] — первая строка записаная после имени программы

argv[2] — вторая строка записаная после имени программы

argv[argc-1] — последняя строка записаная после имени программы

argv[argc] — NULL

Вопрос 38

Основные спецификации форматного ввода/вывода (для функций printf и scanf) в библиотеке stdio языка программирования Си.

Символ Вводимые данные; тип аргумента
d десятичное целое: int *
i целое: int *. Целое может быть восьмеричным(с 0 слева) или шестнадцатеричным (с 0x или 0X слева)
o восьмеричное целое (с нулем слева или без него); int*
u беззнаковое десятичное целое; unsigned int *
x шестнадцатеричное целое (с 0x или 0X слева или безних); int *
c символы; char *. Следующие символы ввода (поумолчанию один) размещаются в указанном месте. Обычный пропуск символов-разделителей подавляется; чтобы прочесть очередной символ, отличный отсимвола-разделителя, используйте %1s
s Строка символов(без обрамляющих кавычек); char *,указывающая на массив символов, достаточный для строки и завершающего символа’\0′, который будет добавлен
e, f, g число с плавающей точкой, возможно, со знаком;обязательно присутствие либо десятичной точки, либо экспоненциальной части, авозможно, и обеих вместе; float *
% сам знак %, никакое присваивание не выполняется
Символ Тип аргумента; вид печати
d, i int; десятичное целое
o unsigned int; беззнаковое восьмеричное (octal) целое (безнуля слева)
x, X unsigned int; беззнаковое шестнадцатеричное целое (без 0x или 0Xслева), для 10…15 используются abcdef или ABCDEF
u unsigned int; беззнаковое десятичное целое
c int; одиночный символ
s char *; печатает символы, расположенные до знака \0, или вколичестве, заданном точностью
f double; [-]m.dddddd, где количество цифр dзадается точностью (по умолчанию равно 6)
e, E double; [-]m.dddddde±xx или [-]m.ddddddE±xx,где количество цифр d задается точностью (по умолчанию равно 6)
g, G double; использует %e или %E, если порядокменьше, чем -4, или больше или равен точности; в противном случае использует %f.Завершающие нули и завершающая десятичная точка не печатаются
p void *; указатель (представление зависит от реализации)
% Аргумент не преобразуется; печатается знак %

Вопрос 39

Основные функции, используемые при работе с текстовыми файлами (открытие, закрытие, чтение, запись и пр.) в библиотеке stdio языка программирования Си.

Обращение к fopen в программе может выглядеть следующим образом:

fp = fopen(name, mode);

Первый аргумент — строка, содержащая имя файла. Второй аргумент несет информацию о режиме. Это тоже строка: в ней указывается, каким образом пользователь намерен применять файл. Возможны следующие режимы: чтение (read — r), запись (write — w) и добавление (append — a), т. е. запись информации в конец уже существующего файла. В некоторых системах различаются текстовые и бинарные файлы; в случае последних в строку режима необходимо добавить букву b (binary — бинарный).

Следующее, что нам необходимо знать, — это как читать из файла или писать в файл, коль скоро он открыт. Существует несколько способов сделать это, из которых самый простой состоит в том, чтобы воспользоваться функциями getc и putc. Функция getc возвращает следующий символ из файла; ей необходимо сообщить указатель файла, чтобы она знала откуда брать символ.

int getc(FILE *fp);

Функция getc возвращает следующий символ из потока, на который указывает *fp; в случае исчерпания файла или ошибки она возвращает EOF.

Функция putc пишет символ c в файл fp

int putc(int с, FILE *fp);

и возвращает записанный символ или EOF в случае ошибки

При запуске Си-программы операционная система всегда открывает три файла и обеспечивает три файловые ссылки на них. Этими файлами являются: стандартный ввод, стандартный вывод и стандартный файл ошибок; соответствующие им указатели называются stdin, stdout и stderr; они описаны в . Обычно stdin соотнесен с клавиатурой, а stdout и stderr — с экраном. С помощью getc, putc, stdin и stdout функции getchar и putchar теперь можно определить следующим образом:

#define getchar() getc(stdin)

#define putchar(c) putc((c), stdout)

Форматный ввод-вывод файлов можно построить на функциях fscanf и fprintf. Они идентичны scanf и printf с той лишь разницей, что первым их аргументом является указатель на файл, для которого осуществляется ввод-вывод, формат же указывается вторым аргументом.

int fscanf(FILE *fp, char *format, …)

int fprintf(FILE *fp, char *format, …)

Вопрос 40

Основные функции, используемые при работе со строками в библиотеке string,stdio,stlib языка программирования Си.

В стандартной библиотеке stdio имеется программа ввода fgets, аналогичная программе getline, которой мы пользовались в предыдущих главах.

char *fgets(char *line, int maxline, FILE *fp)

Функция fgets читает следующую строку ввода (включая и символ новой строки) из файла fp в массив символов line, причем она может прочитать не более MAXLINE-1 символов. Переписанная строка дополняется символом ‘\0’. Обычно fgets возвращает line, а по исчерпании файла или в случае ошибки — NULL. (Наша getline возвращала длину строки, которой мы потом пользовались, и нуль в случае конца файла.)

Функция вывода fputs пишет строку (которая может и не заканчиваться символом новой строки) в файл.

int fputs(char *line, FILE *fp)

Эта функция возвращает EOF, если возникла ошибка, и неотрицательное значение в противном случае.

Библиотечные функции gets и puts подобны функциям fgets и fputs. Отличаются они тем, что оперируют только стандартными файлами stdin и stdout, и кроме того, gets выбрасывает последний символ ‘\n’, a puts его добавляет.

char *strcpy(s,ct) копирует строку ct в строку s, включая’\0′; возвращает s
char *strncpy(s,ct,n) копирует не более n символов строки ctв s; возвращает s. Дополняет результат символами ‘\0’, еслисимволов в ct меньше n
char *strcat(s,ct) приписывает ct к s; возвращает s
char *strncat(s,ct,n) приписывает не более n символов ct к s,завершая s символом ‘\0’; возвращает s
char strcmp(cs,st) сравнивает cs и ct; возвращает ct (I.B.: вообще-то,функция возвращает int)
char strncmp(cs,ct) сравнивает не более n символов cs и ct;возвращает ct (I.B.:тоже int должна возвращать)
char *strchr(cs,c) возвращает указатель на первое вхождение c в csили, если такового не оказалось, NULL
char *strrchr(cs,c) возвращает указатель на последнее вхождение cв cs или, если такового не оказалось, NULL
size_t strspn(cs,ct) возвращает длину начального сегмента cs,состоящего из символов, входящих в строку ct
size_t strcspn(cs,ct) возвращает длину начального сегмента cs,состоящего из символов, не входящих в строку ct
char *strpbrk(cs,ct) возвращает указатель в cs на первый символ,который совпал с одним из символов, входящих в ct, или, если таковогоне оказалось, NULL
char *strstr(cs, ct) возвращает указатель на первое вхождение ct вcs или, если такового не оказалось, NULL
size_t strlen(cs) возвращает длину cs
char * strerror(n) возвращает указатель на зависящую от реализациистроку, соответствующую номеру ошибки n
char * strtok(s, ct) strtok ищет в s лексему, ограниченную символами из ct;более подробное описание этой функции см. ниже

Функции mem… предназначены для манипулирования с объектами как с массивами символов; их назначение — получить интерфейсы к эффективным программам. В приведенной ниже таблице s и t принадлежат типу void *; cs и ct — типу const void *; n — типу size_t; а c имеет значение типа int, приведенное к типу char.

void *memcpy(s,ct,n) копирует n символов из ct в s ивозвращает s
void *memmove(s,ct,n) делает то же самое, что и memcpy, но работаети в случае перекрывающихся объектов.
int memcmp(cs,ct, n) сравнивает первые n символов cs и ct;выдает тот же результат, что и функция strcmp
void *memchr(cs,c, n) возвращает указатель на первое вхождение символа cв cs или, если среди первых n символов c не встретилось,NULL
void *memset(s,c, n) размещает символ c в первых n позицияхстроки s и возвращает s

double strtod(const char *s, char **endp)

strtod преобразует первые символы строки s в double, игнорируя начальные символы-разделители; запоминает указатель на непреобразованный конец в *endp (если endp не NULL), при переполнении она выдает HUGE_VAL с соответствующим знаком, в случае, если результат оказывается меньше, чем возможно представить данным типом, возвращается 0; в обоих случаях в errno устанавливается ERANGE.

long strtol(const char *s, char **endp, int base)

strtol преобразует первые символы строки s в long, игнорируя начальные символы-разделители; запоминает указатель на непреобразованный конец в *endp (если endp не NULL). Если base находится в диапазоне от 2 до 36, то преобразование делается в предположении, что на входе — запись числа по основанию base. Если base равно нулю, то основанием числа считается 8, 10 или 16; число, начинающееся с цифры 0, считается восьмеричным, а с 0x или 0X — шестнадцатеричным. Цифры от 10 до base-1 записываются начальными буквами латинского алфавита в любом регистре. При основании, равном 16, в начале числа разрешается помещать 0x или 0X. В случае переполнения функция возвращает LONG_MAX или LONG_MIN (в зависимости от знака), a в errno устанавливается ERANGE.

unsigned long strtoul(const char *s, char **endp, int base)

strtoul работает так же, как и strtol, с той лишь разницей, что возвращает результат типа unsigned long, а в случае переполнения — ULONG_MAX.

Спс Грише за последние 4 вопроса

Статьи к прочтению:

Программирование на Си урок 22: Функции, прототипы функций


Похожие статьи: