Аргументы - вызов по значению

Язык С
Строк программы, исключая математическое обеспечение Является учебным введением в центральную часть языка “C” Hачинаем. Единственный способ освоить новый язык Оператор FOR Набор полезных программ Подсчет символов Подсчет слов Функции Аргументы - вызов по значению Область действия: внешние переменные Резюме Константы Описания Преобразование типов До 9 и буквы от а до F Операции и выражения присваивания Старшинство и порядок вычисления Операторы и блоки Переключатель Цикл DO - WHILE Оператор CONTINUE Основные сведения Функции, возвращающие нецелые значения Еще об аргументах функций Правила, определяющие область действия Статические переменные Блочная структура Рекурсия Указатели и адреса Указатели и массивы Адресная арифметика Указатели символов и функции Указатели - не целые До 12, а не от 0 до 11. Так как за экономию памяти у нас пока не награждают, такой способ проще, чем подгонка индек-сов Инициализация массивов указателей Указатели на функции Структуры Структуры и функции Указатели на структуры Мы продемонстрируем, как правильно выполнить эту задачу Поля Определение типа Обращение к стандартной библиотеке Форматный вывод - функция PRINTF Форматный ввод - функция SCANF Форматное преобразование в памяти Обработка ошибок - STDERR и EXIT Обращение к системе Низкоуровневый ввод/вывод - операторы READ и WRITE Произвольный доступ - SEEK и LSEEK Пример - распечатка справочников Пример - распределитель памяти Константы Синтаксическая нотация Преобразования Первичные выражения Унарные операции Аддитивные операции Операция присваивания Спецификаторы типа Описание структур и объединений Инициализация TYPEDEF Оператор SWITCH Внешнее определение функции Область действия внешних идентификаторов Неявные описания Явные преобразования указателей Анахронизмы Операторы
439386
знаков
0
таблиц
0
изображений

1.8. Аргументы - вызов по значению.

 

Один аспект в “C” может оказаться непривычным для прог-

раммистов, которые использовали другие языки, в частности,

фортран и PL/1. в языке “C” все аргументы функций передаются

“по значению”. это означает, что вызванная функция получает

значения своих аргументов с помощью временных переменных

/фактически через стек/, а не их адреса. Это приводит к не-

которым особенностям, отличным от тех, с которыми мы сталки-

вались в языках типа фортрана и PL/1, использующих “вызов по

ссылке “, где вызванная процедура работает с адресом аргу-

мента, а не с его значением.

Главное отличие состоит в том, что в “C” вызванная функ-

ция не может изменить переменную из вызывающей функции; она

может менять только свою собственную временную копию.

Вызов по значению, однако, не помеха, а весьма ценное

качество. Оно обычно приводит к более компактным программам,

содержащим меньше не относящихся к делу переменных, потому

что с аргументами можно обращаться как с удобно инициализи-

рованными локальными перемнными вызванной процедуры. Вот,

например, вариант функции POWER использующей это обстоятель-

ство

 

POWER(X,N) /* RAISE X N-TH POWER; N > 0;

VERSION 2 */

INT X,N;

{

INT P;

FOR (P = 1; N > 0; --N)

P = P * X;

RETURN (P);

}

 

 

Аргумент N используется как временная переменная; из не-

го вычитается единица до тех пор, пока он не станет нулем.

Переменная I здесь больше не нужна. чтобы ни происходило с N

внутри POWER это никак не влияет на аргумент, с которым пер-

воначально обратились к функции POWER.

При необходимости все же можно добиться, чтобы функция

изменила переменную из вызывающей программы. Эта программа

должна обеспечить установление адреса переменной /техничес-

ки, через указатель на переменную/, а в вызываемой функции

надо описать соответствующий аргумент как указатель и ссы-

латься к фактической переменной косвенно через него. Мы рас-

смотрим это подробно в главе 5.

Когда в качестве аргумента выступает имя массива, то

фактическим значением, передаваемым функции, является адрес

начала массива. /Здесь нет никакого копирования элементов

массива/. С помощью индексации и адреса начала функция может

найти и изменить любой элемент массива. Это - тема следующе-

го раздела.


·     32 -

 

1.9. Массивы символов.

 

По-видимому самым общим типом массива в “C” является

массив символов. Чтобы проиллюстрировать использование мас-

сивов символов и обрабатывающих их функций, давайте напишем

программу, которая читает набор строк и печатает самую длин-

ную из них. Основная схема программы достаточно проста:

 

WHILE (имеется еще строка)

IF (эта строка длиннее самой длинной из

предыдущих)

запомнить эту строку и ее длину

напечатать самую длинную строку

По этой схеме ясно, что программа естественным образом

распадается на несколько частей. Одна часть читает новую

строку, другая проверяет ее, третья запоминает, а остальные

части программы управляют этим процессом.

Поскольку все так прекрасно делится, было бы хорошо и

написать программу соответсвующим образом. Давайте сначала

напишем отдельную функцию GETLINE, которая будет извлекать

следующую строку из файла ввода; это - обобщение функции

GETCHAR. мы попытаемся сделать эту функцию по возможности

более гибкой, чтобы она была полезной и в других ситуациях.

Как минимум GETLINE должна передавать сигнал о возможном по-

явлении конца файла; более общий полезный вариант мог бы пе-

редавать длину строки или нуль, если встретится конец файла.

нуль не может быть длиной строки, так как каждая строка со-

держит по крайней мере один символ; даже строка, содержащая

только символ новой строки, имеет длину 1.

Когда мы находим строку, которая длиннее самой длинной

из предыдущих, то ее надо где-то запомнить. Это наводит на

мысль о другой функции, COPY , которая будет копировать но-

вую строку в место хранения.

Наконец, нам нужна основная программа для управления

функциями GETLINE и COPY . Вот результат :

#DEFINE MAXLINE 1000 /* MAXIMUM INPUT

LINE SIZE */

MAIN() /* FIND LONGEST LINE */

{

INT LEN; /* CURRENT LINE LENGTH */

INT MAX; /* MAXIMUM LENGTH SEEN SO FAR */

CHAR LINE[MAXLINE]; /* CURRENT INPUT LINE */

CHAR SAVE[MAXLINE]; /* LONGEST LINE, SAVED */

 

MAX = 0;

WHILE ((LEN = GETLINE(LINE, MAXLINE)) > 0)

IF (LEN > MAX) {

MAX = LEN;

COPY(LINE, SAVE);

}

IF (MAX > 0) /* THERE WAS A LINE */

PRINTF(“%S”, SAVE);

}


·     33 -

GETLINE(S,LIM) /* GET LINE INTO S,RETURN LENGTH */

CHAR S[];

INT LIM;

{

INT C, I;

FOR(I=0;I<LIM-1 && (C=GETCHAR())!=EOF && C!='\N';++I)

S[I] = C;

IF (C == '\N') {

S[I] = C;

++I;

}

S[I] = '\0';

RETURN(I);

}

 

COPY(S1, S2) /* COPY S1 TO S2;

ASSUME S2 BIG ENOUGH */

CHAR S1[], S2[];

{

INT I;

I = 0;

WHILE ((S2[I] = S1[I] != '\0')

++I;

}

Функция MAIN и GETLINE общаются как через пару аргумен-

тов, так и через возвращаемое значение. аргументы GETLINE

описаны в строках

 

CHAR S[];

INT LIM;

которые указывают, что первый аргумент является массивом, а

второй - целым.

Длина массива S не указана, так как она определена в

MAIN . функция GETLINE использует оператор RETURN для пере-

дачи значения назад в вызывающую программу точно так же, как

это делала функция POWER. Одни функции возвращают некоторое

нужное значение; другие, подобно COPY, используются из-за их

действия и не возвращают никакого значения.

Чтобы пометить конец строки символов, функция GETLINE

помещает в конец создаваемого ей массива символ \0 /нулевой

символ, значение которого равно нулю/. Это соглашение ис-

пользуется также компилятором с языка “C”: когда в “C” -

программе встречается строчная константа типа

 

“HELLO\N”

·      
34 -

 

то компилятор создает массив символов, содержащий символы

этой строки, и заканчивает его символом \0, с тем чтобы фун-

кции, подобные PRINTF, могли зафиксировать конец массива:

 

! H ! E ! L ! L ! O ! \N ! \0 !

 

Спецификация формата %S указывает, что PRINTF ожидает стро-

ку, представленную в такой форме. Проанализировав функцию

COPY, вы обнаружите, что и она опирается на тот факт, что ее

входной аргумент оканчивается символом \0, и копирует этот

символ в выходной аргумент S2. /Все это подразумевает, что

символ \0 не является частью нормального текста/.

Между прочим, стоит отметить, что даже в такой маленькой

программе, как эта, возникает несколько неприятных организа-

ционных проблем. Например, что должна делать MAIN, если она

встретит строку, превышающую ее максимально возможный раз-

мер? Функция GETLINE поступает разумно: при заполнении мас-

сива она прекращает дальнейшее извлечение символов, даже ес-

ли не встречает символа новой строки. Проверив полученную

длину и последний символ, функция MAIN может установить, не

была ли эта строка слишком длинной, и поступить затем, как

она сочтет нужным. Ради краткости мы опустили эту проблему.

Пользователь функции GETLINE никак не может заранее уз-

нать, насколько длинной окажется вводимая строка. Поэтому в

GETLINE включен контроль переполнения. в то же время пользо-

ватель функции COPY уже знает /или может узнать/, каков раз-

мер строк, так что мы предпочли не включать в эту функцию

дополнительный контроль.

Упражнение 1-14.

Переделайте ведущую часть программы поиска самой длинной

строки таким образом, чтобы она правильно печатала длины

сколь угодно длинных вводимых строк и возможно больший

текст.

Упржнение 1-15.

Напишите программу печати всех строк длиннее 80 симво-

лов.

Упражнение 1-16.

Напишите программу, которая будет удалять из каждой

строки стоящие в конце пробелы и табуляции, а также строки,

целиком состоящие из пробелов.

Упражнение 1-17.

Напишите функцию REVERSE(S), которая распологает сим-

вольную строку S в обратном порядке. С ее помощью напишите

программу, которая обратит каждую строку из файла ввода.

·      
35 -


Информация о работе «Язык С»
Раздел: Информатика, программирование
Количество знаков с пробелами: 439386
Количество таблиц: 0
Количество изображений: 0

Похожие работы

Скачать
48443
0
0

... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...

Скачать
43709
0
0

... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...

Скачать
39778
0
1

... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...

Скачать
64931
0
0

... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...

0 комментариев


Наверх