До сих пор ни одна из наших программ не содержала како-го-либо описания типа функции. Дело в том, что по умолчаниюфункция неявно описывается своим появлением в выражении илиоператоре, как, например, в 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; 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 100MAIN() /* 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(...) являются плавающие числа двойной точности. Если функция 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' и пока-затель экспоненты, возможно со знаком.