Чтение онлайн

ЖАНРЫ

Программирование на Objective-C 2.0
Шрифт:

После присваивания значений соответствующий вызов NSLog выводит зна-чения, содержащиеся в этой структуре. Вычисляется остаток отделения today.year на 100, поэтому функция NSLog выводит для года только две цифры. Символы формата %.2i в обращении к NSLog указывают вывод не менее двух символов, в результате чего для года выводится ведущий нуль.

При вычислении выражений компоненты структуры подчиняются таким же правилам, что и обычные переменные в языке Objective-C. Деление целого ком-понента структуры на другое целое значение выполняется как деление целых, например century = today.year /100+ 1;

Напишем несложную программу, которая принимает на входе текущую дату и выводит завтрашнюю

дату (tomorrow). На первый взгляд это кажется совсем простой задачей. Нужно запросить у пользователя ввод текущей даты и затем вычислить завтрашнюю дату с помощью следующего набора операторов. tomorrow.month = today.month; tomorrow.day = today.day + 1; tomorrow.year - today.year;

Конечно, для большинства дат это подходит, но два случая будут реализованы неверно.

Текущая дата приходится на конец месяца.

Текущая дата приходится на конец года (то есть на 3 1 декабря). Чтобы определить, приходится ли текущая дата на конец месяца, нужно задать массив целых значений, соответствующих числу дней каждого месяца.

Поиск в этом массиве даст число дней месяца (см. программу 13.7). // Программа определения завтрашней даты #import <Foundation/Foundation.h> struct date { int month; int day; int year; }; // Функция для вычисления завтрашней даты struct date dateUpdate (struct date today) { struct date tomorrow; int numberOfDays (struct date d); if (today.day != numberOfDays (today)) { tomorrow.day = today.day + 1; tomorrow.month = today.month; tomorrow.year = today.year; } else if (today.month == 12) // end of year { tomorrow.day = 1; tomorrow.month = 1; tomorrow.year = today.year + 1; } else { // конец месяца tomorrow.day = 1; tomorrow.month = today.month + 1; tomorrow.year = today.year; } return (tomorrow); } // Функция для поиска числа дней в месяце int numberOfDays (struct date d) { int answer; BOOL isLeapYear (struct date d); int daysPerMonth[12] = { 31,28, 31, 30, 31, 30, 31, 31,30, 31,30, 31 }; if (isLeapYear (d) == YES && d.month == 2) answer = 29; else answer = daysPerMonth[d. month - 1]; return (answer); } // Функция, определяющая, является ли год високосным BOOL isleapYear (struct date d) { if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0 ) return YES; else return NO; } int main (int argc, char *argv[]) { NSAutoreleasePool * poo! = [[NSAutoreleasePool alloc] init]; struct date datellpdate (struct date today); struct date thisDay, nextDay; NSLog (@nEnter today’s date (mm dd yyyy):"); scanf ("%i%i%i", SthisDay.month, SthisDay.day, &thisDay.year); nextDay = dateUpdate (thisDay); NSLog (@"Tomorrow’s date is %i/%i/%.2i.",nextDay.month, nextDay .day, nextDay.year % 100); [pool drain]; return 0; }

Вывод программы 13.7 Enter today’s date (mm dd yyyy): (Введите текущую дату (мм дд rrrr) 2 28 2012 Tomorrow’s date is 2/29/12. (Завтрашняя дата)

Вывод программы 13.7 (повторный запуск) Enter today’s date (mm dd yyyy): 10 2 2009 Tomorrow’s date is 10/3/09.

Вывод программы 13.7 (повторный запуск) Enter today’s date (mm dd yyyy): 12 31 2010 Tomorrow’s date is 1/1/10.

Хотя мы не работаем в этой программе с классами, здесь был импортирован файл Foundation.!!, поскольку нам нужен тип B00L и определенные имена YES и N0. Они определены в этом файле.

Отметим, что определение структуры данных представлено в первую очередь и вне какой-либо функции. Определения структур данных действуют аналогично переменным. Если структура определена внутри какой-либо функции, только эта функция «знает» о ее существовании, и тогда это локальное определение структуры. Если структура определена вне любой функции, это определение является глобальным. Глобальное определение структуры позволяет объявлять любые

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

Внутри процедуры main объявление struct date dateUpdate (struct date today);

указывает компилятору, что функция dateUpdate принимает в качестве аргумента структуру типа date и возвращает структуру такого же типа. Это объявление не обязательно, поскольку компилятор уже «видел» конкретное объявление функции в этом файле, но принято в практике надежного программирования. Если вы в дальнейшем разделите определение этой функции и main на отдельные исходные файлы, объявление будет необходимо.

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

После ввода даты и ее сохранения в структурной переменной thisDay типа date происходит вызов функции dateUpdate. nextDay = dateUpdate (thisDay);

Здесь происходит вызов функции dateUpdate с передачей этой функции струк-туры даты thisDay.

Внутри функции dateUpdate объявление прототипа int numberOfDays (struct date d);

информирует компилятор Objective-C, что функция numberOfDays возвращает целое значение и принимает один аргумент типа struct date.

Оператор if (today.day != numberOfDays (today))

указывает, что структура today должна передаваться как аргумент функции numberOTOays. Внутри этой функции должно быть соответствующее объявление, информирующее систему, что аргументом должна быть структура, как в следующей строке. int numberOfDays (struct date d)

Сначала в функции numberOfDays нужно выполнить проверку на високосный год и определить, не является ли месяц февралем. Для первой проверки вызы-вается другая функция с именем isLeapYear.

Функция isLeapYear вполне понятна; она проверяет год, содержащийся в структуре типа date, которая передается как аргумент, и возвращает значение YES в случае високосного года или N0 в противном случае.

Вы должны понять иерархию вызовов функций в программе 13.7. функция main вызывает dateUpdate, которая вызывает numberOfDays, которая, в свою очередь, вызывает функцию isLeapYear. Инициализация структур

Инициализация структур аналогична инициализации массивов: значения ком-понентов просто перечисляются в фигурных скобках с применением запятой в качестве разделителя.

Чтобы инициализировать переменную today структуры типа date, задав зна-чение Июль, 2 число, 20П год, можно использовать оператор struct date today = { 7, 2, 2011 };

Как и при инициализации массива, можно указывать значения не для всех компонентов структуры. Например, в операторе struct date today = {7 };

задается значение 7 для компонента today.month, но не задаются начальные зна-чения для today.day и today.year. В таких случаях начальные значения по умолча-нию не определены.

Для конкретных компонентов можно выполнять инициализацию в любом порядке, используя в списке инициализации форму записи .компонент = значение

например, struct date today = {.month = 7, .day = 2, .year = 2011 };

и struct date today = {.year = 2011 };

В последнем примере этой структуры задается только значение года, равное 2011. Остальные два компонента не определены. Массивы структур

Работа с массивами структур не представляет особых сложностей. Например, в struct date birthdays[15];

Поделиться с друзьями: