4.2. Функции, возвращающие нецелые значения.
До сих пор ни одна из наших программ не содержала како-
го-либо описания типа функции. Дело в том, что по умолчанию
функция неявно описывается своим появлением в выражении или
операторе, как, например, в
WHILE (GETLINE(LINE, MAXLINE) > 0)
Если некоторое имя, которое не было описано ранее, появ-
ляется в выражении и за ним следует левая круглая скобка, то
оно по контексту считается именем некоторой функции. Кроме
того, по умолчанию предполагается, что эта функция возвраща-
ет значение типа INT. Так как в выражениях CHAR преобразует-
ся в INT, то нет необходимости описывать функции, возвращаю-
щие CHAR. Эти предположения покрывают большинство случаев,
включая все приведенные до сих пор примеры.
Но что происходит, если функция должна возвратить значе-
ние какого-то другого типа ? Многие численные функции, такие
как SQRT, SIN и COS возвращают DOUBLE; другие специальные
функции возвращают значения других типов. Чтобы показать,
как поступать в этом случае, давайте напишем и используем
функцию ATоF(S), которая преобразует строку S в эквивалент-
ное ей плавающее число двойной точности. Функция ATоF явля-
ется расширением атоI, варианты которой мы написали в главах
2 и 3; она обрабатывает необязательно знак и десятичную точ-
ку, а также целую и дробную часть, каждая из которых может
как присутствовать, так и отсутствовать./эта процедура пре-
образования ввода не очень высокого качества; иначе она бы
заняла больше места, чем нам хотелось бы/.
Во-первых, сама ATоF должна описывать тип возвращаемого
ею значения, поскольку он отличен от INT. Так как в выраже-
ниях тип FLOAT преобразуется в DOUBLE, то нет никакого смыс-
ла в том, чтобы ATOF возвращала FLOAT; мы можем с равным ус-
пехом воспользоваться дополнительной точностью, так что мы
полагаем, что возвращаемое значение типа DOUBLE. Имя типа
должно стоять перед именем функции, как показывается ниже:
DOUBLE ATOF(S) /* CONVERT STRING S TO DOUBLE */
CHAR S[];
{
DOUBLE VAL, POWER;
INT I, SIGN;
·
78 -
FOR(I=0; S[I]==' ' \!\! S[I]=='\N' \!\! S[I]=='\T'; I++)
; /* SKIP WHITE SPACE */
SIGN = 1;
IF (S[I] == '+' \!\! S[I] == '-') /* SIGN */
SIGN = (S[I++] == '+') ? 1 : -1;
FOR (VAL = 0; S[I] >= '0' && S[I] <= '9'; I++)
VAL = 10 * VAL + S[I] - '0';
IF (S[I] == '.')
I++;
FOR (POWER = 1; S[I] >= '0' && S[I] <= '9'; I++) {
VAL = 10 * VAL + S[I] - '0';
POWER *= 10;
}
RETURN(SIGN * VAL / POWER);
}
Вторым, но столь же важным, является то, что вызывающая
функция должна объявить о том, что ATOF возвращает значение,
отличное от INT типа. Такое объявление демонстрируется на
примере следующего примитивного настольного калькулятора
/едва пригодного для подведения баланса в чековой книжке/,
который считывает по одному числу на строку, причем это чис-
ло может иметь знак, и складывает все числа, печатая сумму
после каждого ввода.
#DEFINE MAXLINE 100
MAIN() /* RUDIMENTARY DESK CALKULATOR */
{
DOUBLE SUM, ATOF();
CHAR LINE[MAXLINE];
SUM = 0;
WHILE (GETLINE(LINE, MAXLINE) > 0)
PRINTF(“\T%.2F\N”,SUM+=ATOF(LINE));
Оисание
DOUBLE SUM, ATOF();
говорит, что SUM является переменной типа DOUBLE , и что
ATOF является функцией, возвращающей значение типа DOUBLE .
Эта мнемоника означает, что значениями как SUM, так и
ATOF(...) являются плавающие числа двойной точности.
· 79 -
Если функция ATOF не будет описана явно в обоих местах,
то в “C” предполагается, что она возвращает целое значение,
и вы получите бессмысленный ответ. Если сама ATOF и обраще-
ние к ней в MAIN имеют несовместимые типы и находятся в од-
ном и том же файле, то это будет обнаружено компилятором. Но
если ATOF была скомпилирована отдельно /что более вероятно/,
то это несоответствие не будет зафиксировано, так что ATOF
будет возвращать значения типа DOUBLE, с которым MAIN будет
обращаться, как с INT , что приведет к бессмысленным резуль-
татам. /Программа LINT вылавливает эту ошибку/.
Имея ATOF, мы, в принципе, могли бы с ее помощью напи-
сать ATOI (преобразование строки в INT):
ATOI(S) /* CONVERT STRING S TO INTEGER */
CHAR S[];
{
DOUBLE ATOF();
RETURN(ATOF(S));
}
Обратите внимание на структуру описаний и оператор RETURN.
Значение выражения в
RETURN (выражение)
всегда преобразуется к типу функции перед выполнением самого
возвращения. Поэтому при появлении в операторе RETURN значе-
ние функции атоF, имеющее тип DOUBLE, автоматически преобра-
зуется в INT, поскольку функция ATOI возвращает INT. (Как
обсуждалось в главе 2, преобразование значения с плавающей
точкой к типу INT осуществляется посредством отбрасывания
дробной части).
Упражнение 4-2.
Расширьте ATOF таким образом, чтобы она могла работать с
числами вида
123.45е-6
где за числом с плавающей точкой может следовать 'E' и пока-
затель экспоненты, возможно со знаком.
... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...
... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...
... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...
... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...
0 комментариев