Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






ЗаданиеПриоритеты операций и "хитрые" выражения




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

Это увлекательные упражнения, но, на наш взгляд, к реальному программированию они имеют мало отношения. Программы, в которых дети специально "наворачивают" выражения для повышения "крутизны" и уменьшения читабельности текста, автор просто отказывается проверять и советует коллегам придерживаться того же принципа. Поэтому здесь не будут приводиться примеры таких выражений и разбираться "а почему же все-таки оно имеет такое значение". На это можно потратить огромное количество времени безо всякой пользы. А вот приоритеты операций? другое дело. Знать их полезно, хотя в сомнительных случаях гораздо разумнее использовать скобки для явного указания

порядка разбора выражения. Таблица приоритетов операций будет приведена в приложении (это объясняется тем, что еще не все операции были нами рассмотрены). Здесь же мы уделим внимание ряду "тонких" вопросов, которые иногда заставляют изрядно помучиться и детей, и учителя. Си, подобно большинству языков, не фиксирует порядок вычисления операндов операций. На практике это означает, что при вычислении такого, например, выражения: a=fl() +f2();, мы не можем быть уверены, какая из функций? fl или f2 будет вызвана раньше. Порядок вычисления аргументов функций также не стандартизован. Нельзя быть уверенным, что выдаст на печать оператор: printf("%d

%d",++n,f(n));. Чтобы не ломать голову, надо просто вынести операцию инкремента "наверх":

++n;

printf("%d%d",n,f (n));

(Или, наоборот, "вниз", если вы рассчитываете на другой порядок вычислений аргументов функции.)

Выражение вида а [ i ] =i++; также может пониматься различными компиляторами по-разному.

. Перечислимый тип

Перечислимый тип enum используется для улучшения читабельности программ. Константы перечислимого типа на самом деле являются целыми (int), фактически при определении перечислимого типа мы определяем символические имена целых констант. Приведем пример: пусть нам нужно закодировать дни недели. Можно, конечно, просто использовать числа от 0 до б, но разумнее определить соответствующий перечислимый тип и далее вместо чисел использовать в программе названия, соответствующие дням недели. Вот так:

enum (mо,tu,we,th,fr,st,su};

В результате такого описания мы получаем возможность использовать константы mo, tu, we, th, fr, st, su со значениями от 0 до б (по умолчанию константы перечислимого типа получают значения начиная с 0). Если мы хотим нумеровать дни недели начиная с 1, достаточно сопоставить значение 1 с константой то (компилятор продолжит нашу нумерацию).

enum {mo=l,tu,we,th,fr,st,su};

Если нам надо просто определить ряд целых констант с произвольными значениями, то это также

можно сделать с использованием перечислимого типа:

enum {msk=95,stpt=812};

Если перечислимому типу дать имя, появляется возможность использовать это имя в описаниях:

enum days {то, tu,we, th, fr, st, su};

enum days dl,d2,d3;



Структуры

Структуры (struct) в Си являются аналогом записей (record) в Паскале. Типичный пример описания структуры:

struct point {int x,y;} /* точка на плоскости с целочисленными координатами; х и у являются полями структуры point*/

Приведенный пример является именно описанием самой структуры, описание соответствующей переменной выглядит следующим образом:

struct point a;

Обратите внимание, что переменная описывается не как просто point а, а именно как struct point а.

Переменные можно описывать и при описании самой структуры:

struct point {int x,y;} a,b,c; /* описание структуры point и трех переменных a, b и с*/

Доступ к элементам структуры производится так же, как и в Паскале, с указанием имени переменной и имени поля. Пример: а.х, поле х

переменной а.

При описании указателя на структуру (такие указатели часто используются для организации списков, деревьев и других динамических структур данных, о которых будет рассказано далее) доступ к полю можно осуществлять посредством операции?>. Приведем соответствующий пример. Пусть у нас уже имеется описание структуры point (см, выше), и мы описываем указатель на эту структуру: struct point *р. Для доступа к полю х в этом случае необходимо использовать запись (*р).х,но то же самое можно записать и короче: р?>х.

Структуры могут "вкладываться" друг в друга, это обычно делается для более точного описания объекта. Так, можно описать окружность посредством одной структуры struct circl {int x,y,r; }, но запись struct circl {struct point centre; int r; } изящнее. Хотя за это придется "платить" усложнением доступа к полям структуры. В первом случае при описании переменной struct circl о для доступа к полю х достаточно написать просто о.х, а во втором требуется запись о.centre.х. Впрочем, в случае более сложных примеров (а мы приводим совсем простые) такие "усложнения" описания типов обычно оправданны, ибо улучшают читабельность программы. В заключение этого раздела приведем пример описания массива структур. Ничего особенного и нового в этом описании нет, но массивы структур приходится использовать часто, и мы хотим, чтобы соответствующий пример был у вас перед глазами. Итак, если у нас уже имеется описание структуры point, то описание массива из десяти точек выглядит следующим образом: struct point m[10]. Доступ к элементам массива и их полям производится следующим образом: m [ i ].х.

 

# include <stdio.h>

main()

{

int i;

struct tel {char s[10];int num;} t;

FILE *f;

f=fopen("1.txt", "wb");

for (i=0;i<3;i++)

{

scanf("%s",&t.s);

scanf("%d",&t.num);

fwrite(&t, sizeof(t),1,f);

}

fclose(f);

}

 

Бинарные файлы. Структуры.

1. Дан файл f, компоненты которого являются действительными числами. Найти: а) сумму компонент

файла f; б) последнюю компоненту файла.

2. Дан файл f, компоненты которого являются действительными числами. Найти: а) наибольшее из

значений компонент; б) наименьшее из значений компонент с четными номерами; в) наибольшее из

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

файла.

3. Дан файл f, компоненты которого являются целыми числами. Найти количество квадратов простых чисел среди компонент.

4. Дано натуральное n. Записать в файл g целые числа При i=1,2,...,n значение равно: а) i; б) i!;

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

6. Описать, используя структуру данных запись, таблицу дат и событий русской истории. Составить программу, выдающую список событий 19 века.

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

8. Описать, используя структуру данных запись, выборы (фамилия кандидата и количество

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

 

 

.


Объединения

 

В Паскале нет аналогов объединениям (union), да и в Си объединения используются не слишком часто (как написано в одной из популярных книг по Си, объединения чаще всего используются для "сомнительного преобразования типов"). Мы не будем много заниматься

объединениями, но кратко поясним, что это такое.

Описание объединения похоже на описание структуры: union point { int х, у;}, но само объединение принципиально отличается от структуры тем, что все элементы объединения располагаются в памяти, начиная с одного и того же адреса. То есть переменные описанного нами объединения point будут занимать два байта памяти (элементы структуры point занимали четыре байта), и поля х и у данного объединения практически неразличимы. Приведем пример короткой программы, демонстрирующий сказанное:

#include <stdio.h>

void main(void)

{ union point { int x,y;} a;

a.x=10;

printf("\nРазмер объединения:%d a.x=%d a.y=%d",sizeof(a), a.x, a.y);

}

На печать будет выведено 2 10 10.

. Описания типов (typedef)

Выше мы фактически уже продемонстрировали описание типов (перечислимого типа, структур и объединений). В этом разделе речь пойдет о

специальном операторе typedef, который предназначен для объявления типов, но сначала приведем пример еще одного способа

"псевдоописания" типа посредством директивы #define. Для "псевдоописания" типа можно использовать следующую конструкцию:

/* Описание "типа" POINT */ #define POINT struct point

POINT { int x,y;};

/* Описание переменных типа POINT */

POINT a,b,c;

В приведенном примере тип point, конечно, не определяется, все построено на контекстных заменах. Но такой прием иногда используют, часто он встречается и в различных пособиях по языку Си,

Теперь о том, как в Си описываются именно типы. Рассмотрим сначала совсем простые примеры.

Вот описание обычной вещественной переменной с именем real: float real;. А вот описание типа real: typedef float real. После описания типа real можно описывать переменные данного типа: real а,Ь, с;

Вот описание целочисленного массива из десяти элементов: int array[10];..A вот описание типа array: typedef int array [10]. После описания типа array можно описывать переменные array ml,m2,m3;?все это описания "целочисленных массивов ml, m2, mЗ из 10 элементов.

 

 






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных