Фундаментальные объекты данных, с которыми работает программа, – это переменные и константы [2.1]. Используемые в программе переменные перечисляются в объявлениях или декларациях, в которых указывается их тип, а также иногда их начальные значения.
С именами переменных связывается тип данных, который контролируется компилятором и для которого выделяется определенное количество байтов памяти [2.1]. Имена переменных должны начинаться с буквы (латинского алфавита) или символа подчеркивания (например, _aza ), за которым могут следовать любые комбинации букв в любом регистре (заглавные или строчные), символы подчеркивания или цифры 0–9. В языке С имеется различие между заглавными и строчными буквами. Поэтому переменная World будет отличаться от переменной world и т.п. При этом в определении переменной не разрешается символ пробела (пробелов) и некоторые другие символы, например, $... .
Стандарт С89 определяет пять базовых типов данных [2.4]:
int – целочисленный тип, целое число;
float – вещественное число одинарной точности с плавающей точкой;
double – вещественное число двойной точности с плавающей точкой;
char – символьный тип для определения одного символа;
void – тип без значения.
Кроме того, существуют модификаторы, которые могут применяться к этим базовым типам [2.1]. Ряд компиляторов может поддерживать еще и логический тип _Bool. Тип void служит для объявления функции, не возвращающей значения, или для создания универсального указателя (pointer).
Объект типа char всегда занимает 1 байт памяти [2.4]. Размеры объектов других типов, как правило, зависят от среды программирования и операционной системы.
Приведем модификаторы базовых типов данных. К ним относятся следующие спецификаторы, предшествующие им в тексте программы [2.4]:
signed, unsigned, long, short
Базовый тип int может быть модифицирован каждым из перечисленных спецификаторов. Тип char модифицируется с помощью unsigned и signed, тип double – с помощью long.
В табл. 2.1 приведены допустимые комбинации типов данных языка С с их минимальным диапазоном значений и типичным размером [13].
| Типы данных языка С | ||
|---|---|---|
| Тип данных | Типичный размер в битах | Минимально допустимый диапазон значений |
| char | 8 (или 1 байт) | от –128 до 127 |
| unsigned char | 8 | от 0 до 255 |
| signed char | 8 | от –128 до 127 |
| int | 16 или 32 | от –32768 до 32767 |
| unsigned int | 16 или 32 | от 0 до 65535 |
| signed int | 16 или 32 | от –32767 до 32767 |
| short int | 16 | от –32767 до 32767 |
| unsigned short int | 16 | от 0 до 65535 |
| signed short int | 16 | от –32767 до 32767 |
| long int | 32 | от –2147483648 до 2147483647 |
| long long int | 64 | от –(263–1 ) до (263–1) для С99 |
| signed long int | 32 | от –2147483647 до 2147483647 |
| unsigned long int | 32 | от 0 до 4294967295 |
| unsigned long long int | 64 | от 0 до (264–1) для С99 |
| float | 32 | от 1Е–37 до 1Е+37 (с точностью не менее 6 значащих десятичных цифр) |
| double | 64 | от 1Е–37 до 1Е+37 (с точностью не менее 10 значащих десятичных цифр) |
| long double | 80 | от 1Е–37 до 1Е+37 (с точностью не менее 10 значащих десятичных цифр) |
Для базового типа int возможны следующие записи с модификатором:
signed или signed int unsigned или unsigned int long или long int short или short int
Для данных вещественного типа максимальные значения абсолютных величин представлены в табл. 2.2 [2.4].
| Вещественные типы данных языка С | ||
|---|---|---|
| Тип данных | Типичный размер в битах | Диапазон абсолютных величин |
| float | 32 | от 3.4Е–38 до 3.4Е+37 |
| double | 64 | от 1.7Е–308 до 1.7Е+308 |
| long double | 80 | от 3.4Е–4932 до 1.1Е+4932 |
В языке С предусматривается преобразование типов в выражениях и приведение типов. Если в выражении смешаны различные типы литералов и переменных, то компилятор преобразует их в один тип. Во-первых, все char и short int значения автоматически преобразуются (с расширением "типоразмера") в тип int. Этот процесс называется целочисленным расширением (integral promotion). Во-вторых, все операнды преобразуются (также с расширением "типоразмера") в тип самого большого операнда. Этот процесс называется расширением типа (type promotion), причем он выполняется пооперационно. Например, если один операнд имеет тип int, а другой– long int, то тип int расширяется в тип long int. Или если хотя бы один из операндов имеет тип double, то любой другой операнд приводится к типу double. Это означает, что такие преобразования, как тип char в тип double, вполне допустимы (если предусматривать, к чему это приведет). После преобразования оба операнда будут иметь один и тот же тип, а результат операции – тип, совпадающий с типом операндов. Приведем последовательность преобразования типов в выражениях по старшинству [2.4]:
ЕСЛИ операнд имеет тип long double ТО второй операнд преобразуется в long double ИНАЧЕ ЕСЛИ операнд имеет тип double ТО второй операнд преобразуется в double ИНАЧЕ ЕСЛИ операнд имеет тип float ТО второй операнд преобразуется в float ИНАЧЕ ЕСЛИ операнд имеет тип unsigned long ТО второй операнд преобразуется в unsigned long ИНАЧЕ ЕСЛИ операнд имеет тип long ТО второй операнд преобразуется в long ИНАЧЕ ЕСЛИ операнд имеет тип unsigned int ТО второй операнд преобразуется в unsigned int
Кроме того, действует правило: если один из операндов имеет тип long, а второй– unsigned int, притом значение unsigned int не может быть представлено типом long, то оба операнда преобразуются в значение типа unsigned long.
В языке С предусматривается явное преобразование (приведение) типов. Общая форма оператора явного приведения типа: (тип) выражение.
В приведенной форме тип – это любой поддерживаемый тип данных. Явное преобразование типа – это операция. Оператор приведения типа является унарным и имеет тот же приоритет, что и остальные
В приводимых ниже программах используются такие средства ввода-вывода, как printf(), getchar(), gets(), scanf().
Приведем характеристику данных функций [2.4].
Прототип функции printf() имеет вид:
int printf(const char *format, ?);
Функция printf() записывает в стандартный поток stdout (стандартный выходной поток данных) значения аргументов из заданного списка аргументов в соответствии со строкой форматирования, адресуемой параметром format. Строка форматирования состоит из элементов двух типов. К элементам первого типа относятся символы, которые выводятся на экран. Элементы второго типа содержат %05d дополнит нулями выводимое целое число, в котором менее пяти цифр, чтобы общая длина равнялась пяти символам. Действие модификатора точности зависит от кода формата, к которому он применяется. Чтобы добавить модификатор точности, следует поставить за спецификатором ширины поля десятичную точку, а после нее – требуемое значение точности (число знаков после десятичной точки). Применительно к целым числам модификатор точности задает минимальное количество выводимых цифр. При необходимости перед целым числом будут добавлены нули. Если модификатор точности применяется к строкам, то число, следующее за точкой, задает максимальную длину поля. Например, спецификация %5.7s выведет строку длиной не менее пяти, но не более семи символов. Если выводимая строка окажется длиннее максимальной длины поля, конечные символы будут отсечены. По умолчанию все выводимые значения выравниваются по правому краю: если ширина поля больше выводимого значения, то оно будет выровнено по правому %–10.4f обеспечит выравнивание вещественного числа с четырьмя десятичными знаками по левому краю в 10-символьном поле. Существуют два модификатора формата, позволяющие функции printf() отображать короткие и длинные целые числа. Это модификатор l (латинская буква эль) уведомляет функцию printf() о длинном типе значения. Модификатор h сообщает функции printf(), что нужно вывести число короткого целого типа. Кроме того, модификатор l можно поставить перед командами форматирования
вещественных чисел. В этом случае он уведомит о выводе значения типа long double.
Спецификаторы формата для функции printf() перечислены в табл. 2.3, взятой из [2.3].
| Спецификаторы формата функции printf() | |
|---|---|
| Код | Формат |
| %c | Символ |
| %d | Десятичное целое число со знаком |
| %i | Десятичное целое число со знаком |
| %e | Экспоненциальное представление числа (в виде мантиссы и порядка, е — на нижнем регистре) |
| %E | Экспоненциальное представление числа (в виде мантиссы и порядка, Е — на верхнем регистре) |
| %f | Десятичное число с плавающей точкой |
| %F | Десятичное число с плавающей точкой (только стандарт С99; если применяется к бесконечности или нечисловому значению, то выдает надписи INF, |
| %g | Использует более короткий из форматов %e или %f |
| %G | Использует более короткий из форматов %E или %F |
| %o | Восьмеричное число без знака |
| %s | Символьная строка |
| %x | Шестнадцатеричное без знака (строчные буквы) |
| %X | Шестнадцатеричное без знака (прописные буквы) |
| %p | Выводит указатель |
| %n | Соответствующий аргумент должен быть указателем на целое число. (Этот спецификатор указывает, что в целочисленной переменной, на которую указывает ассоциированный с данным спецификатором указатель, будет храниться число символов, выведенных к моменту обработки спецификации %n) |
| %% | Выводит знак процента |
Прототип функции getchar() имеет следующий вид:
int getchar(void);
Функция getchar() возвращает из стандартного потока stdin (входного потока данных) следующий символ. При чтении символа предполагается, что символ имеет тип unsigned char, который потом преобразуется в целый. При достижении конца файла, как и при обнаружении ошибки, функция getchar() возвращает значение EOF (End Of File – конец файла).
Прототип функции gets имеет следующий вид:
char *gets(char *str);
Функция gets() читает символы (включая пробелы) из стандартного потока stdin и помещает их в *str (далее это EOF. Для реализации EOF на клавиатуре следует набрать одновременно Ctrl+Z. Вместо разделителя строк в конец строки вставляется нулевой символ, свидетельствующий о ее завершении. Следует учесть, что нет способа ограничить количество символов, которое прочитает функция gets(). Поэтому массив, адресуемый указателем *str, может переполниться, и тогда программа выдаст непредсказуемые результаты.
Прототип функции scanf() имеет следующий вид:
int scanf(const char *format, ?);
Функция scanf() представляет собой функцию для ввода данных общего назначения, которая читает поток stdin и сохраняет информацию в переменных, перечисленных в списке аргументов. Если в строке форматирования встретится разделитель, то функция scanf() пропустит один или несколько разделителей во входном потоке. Под разделителем, или пробельным символом, подразумевают пробел, символ табуляции \t или разделитель строк \n. Все переменные должны передаваться посредством своих адресов, например, с помощью символа . Управляющая строка, задаваемая параметром format, состоит из символов трех категорий: спецификаторов формата, пробельных символов, символов, отличных от пробельных [2.4].
scanf() тип данного, которое будет прочитано. scanf() приведены в табл.2.4.
| Спецификаторы формата функции scanf() | |
|---|---|
| Код | Формат |
| %c | Читает один символ |
| %d | Читает десятичное целое число |
| %i | Читает целое число в любом формате (десятичное, восьмеричное или шестнадцатеричное) |
| %u | Читает десятичное целое число типа short int |
| %e | Читает число с плавающей точкой (и в экспоненциальной форме) |
| %E | Аналогично коду %e |
| %f | Читает число с плавающей точкой |
| %lf | Читает десятичное число с плавающей точкой типа double |
| %F | Аналогично коду %f (для стандарта С99) |
| %g | Читает число с плавающей точкой. |
| %G | Аналогично коду %g |
| %o | Читает восьмеричное число |
| %x | Читает шестнадцатеричное число |
| %X | Аналогично коду %x |
| %s | Читает строку |
| %p | Читает указатель |
| %n | Принимает целое значение, равное количеству прочитанных до сих пор символов |
| %[ ] | Просматривает набор символов |
| %% | Читает знак процента |
Строка форматирования читается слева направо, и *, стоящий после знака % и перед кодом формата, прочитает данные заданного типа, но запретит их присваивание. Команды форматирования могут содержать модификатор максимальной длины поля. Он представляет собой целое число, располагаемое между знаком % и кодом формата, которое ограничивает количество читаемых для всех полей символов. Если входной поток содержит больше заданного количества символов, то при последующем обращении к операции ввода чтение начнется с того места, в котором "остановился" предыдущий вызов функции scanf() [2.3]. Если разделитель (например, пробел) встретится раньше, чем достигнута максимальная ширина поля, то ввод данных завершится. В этом случае функция scanf() переходит к чтению следующего поля. При чтении
одиночных символов символы табуляции и разделители строк читаются подобно любому другому символу.
В программах бывает необходимость определять константы. В языке С типы констант можно задавать явно при использовании суффиксов. Например:
long int j = –12345678L; /* суффикс L */ unsigned int a = 678U; /* суффикс U */ float x = 123.45F; /* суффикс F */ long double z = 12345678.99L; /* суффикс L* /
По умолчанию спецификации f, e, g заставляют функцию scanf() присваивать переменным типа float. Если перед одной из этих спецификаций поставить модификатор l, то функция scanf() присвоит прочитанные данные переменной типа double.
Функция scanf() поддерживает спецификатор формата общего назначения, называемый набором сканируемых символов. В этом случае определяется набор символов, которые могут быть прочитаны функцией scanf() и присвоены соответствующему массиву символов. Для определения такого набора символы, подлежащие сканированию, необходимо заключить в квадратные скобки. Открывающая квадратная скобка должна следовать сразу за знаком процента. При использовании набора сканируемых символов функция scanf() продолжает читать символы и помещать их в соответствующий scanf() читать только те символы, которые отсутствуют в наборе сканируемых символов. Если в строке форматирования встретился символ, отличный от разделителя, то функция scanf() прочитает и отбросит его. Если заданный символ не найден, то функция scanf() завершает работу.
В таких средах разработки как MS Visual Studio 2008 и 2010 рекомендуется для безопасной работы применять функции gets_s() и scanf_s(). Для этих функций при чтении символа или строки следует указать размер в байтах, соответственно для символа или строки. Например, scanf_s("%c", ch, 1). В Visual Studio 2010 тип данных char занимает 1 байт.
Для приводимых примеров будем приводить только текст программы и результат ее выполнения. Программы должны быть написаны в Visual Studio (см. тему 1).
Пример 1. Напишите программу ввода символа, строки, действительных и целых чисел. Действительные числа сложите, целые числа перемножьте. Для действительных чисел использовать типы float и double.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
int main (void) {
// Объявления
char ch, str[79+1];// С учетом одного места для символа '\0'
int x, y, z;
float a, b, c;
double A, B, C;
// Выполнение программы
printf("\n\t Enter a symbol: ");
ch = getchar();
printf("\t The symbol is: %c\n", ch);
_flushall();
printf("\n\t Enter a string: ");
gets_s(str, 79);
printf("\t The string is: %s\n", str);
a = 2.42F; b = 3.58F;
c = a + b;
printf("\n\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c);
A = 12.1234567796602;
B = 2.7182818284509;
C = A + B;
printf("\n\t The sum %1.13f and %1.13f \n\t is equal (as double): %1.13f\n", A, B,C);
x = 2; y = 7;
z = x*y;
printf("\n\t Multiplication %d on %i (as an integer) is equal: %d\n", x, y, z);
printf("\n\n Press any key: ");
_getch();
return 0;
}
В объявлении символьного массива str[79+1] в методических целях сделано напоминание, что для строки следует предусмотреть символ ее завершения, т. е. '\0'. В определении переменных типа float добавлены суффиксы F.
(рис 2.1) Результат программы с базовыми типами данныхРезультат выполнения программы показан на рис 2.1.
Добавим считывание данных с помощью функции scanf_s(). В результате получим следующую программу:
#include <stdio.h>
#include <conio.h>
int main (void)
{
// Объявления
char ch, str[79+1];
int x, y, z;
float a, b, c;
double A, B, C;
// 1-я часть
printf("\n\t Enter a symbol: ");
ch = getchar();
printf("\t The symbol is: %c\n", ch);
_flushall();
printf("\n\t Enter any string: ");
gets_s(str, 79);
printf("\t The string is: %s\n", str);
a = 2.42F;
b = 3.58F;
c = a + b;
printf("\n\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c);
A = 12.1234567796602;
B = 2.7182818284509;
C = A + B;
printf("\n\t The sum %1.13f and %1.13f \n\t is equal (as double): %1.13f\n", A, B,C);
x = 2;
y = 7;
z = x*y;
printf("\n\t The multiplication %d on %i (as an integer) is equal: %d\n", x, y, z);
// 2-я часть
printf("\n\t Enter a symbol: ");
scanf_s("%c", ch, 1);
printf("\t The symbol is: %c\n", ch);
printf("\n\t Enter any string: ");
scanf_s("%s", str, 79);
printf("\t The string is: %s\n", str);
_flushall(); // для устранения пустой строки
printf("\t Enter a real number a: ");
scanf_s("%f", a);
printf("\t Enter a real number b: ");
scanf_s("%f", b);
c = a + b;
printf("\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c);
printf("\n\t Enter a real number A: ");
scanf_s("%lf", A);
printf("\t Enter a real number B: ");
scanf_s("%lf", B);
C = A + B;
Результат выполнения видоизмененной программы показан на рис 2.2.
(рис 2.2) Результат программы с различным вводом данныхВ начале функции int main(void) сделано объявление переменных, которые будут использоваться в программе. Каждый тип переменных объявлен через запятую. В частности, char str[81] означает printf() выводят либо только сообщения, либо еще заданные переменные соответствующих типов.
Функция _flushall() используется для того, чтобы устранить пробельную строку, образованную либо после действия функции getchar(), либо после действия функции scanf(). В некоторых компиляторах функция _flushall() используется без префиксного нижнего подчеркивания.
Функция gets() позволяет считывать символы с наличием разделителей, в частности, с пробелами. В Microsoft Visual Studio 2010 рекомендуется использовать gets_s(), чтобы не было предупреждений.
Следует обратить внимание на формат записи функций scanf(). Если сканируются числа, или одиночные символы, то присваивание этих символов переменным, которые были объявлены через соответствующие типы данных, осуществляется с помощью взятия адреса этих переменных, т.е. с помощью символа , например, scanf_s("%c",ch, 1). При сканировании массива символов, т.е. при сканировании строки, символ не используется. Имя массива само по себе является указателем. double в функции scanf_s() используется спецификатор l.
Задание 1
\t. Для вывода строки предусмотрите табулированный вывод с помощью спецификатора формата %xs, где х – требуемое число позиций отступа.gets_s(), превышающую число 1._flushall(). В отчет вставьте полученный результатfloat с десятью знаками после десятичной точки. Выведите и проанализируйте результат сложения. Объясните результат.puts() и примените ее вместо функции printf(), которая использовалась в режиме сообщений. В отчет вставьте полученный результат. Объясните результат.Пример 2. Напишите программу вычисления алгебраических выражений с приведением типов char, int, float, double.
Возможный программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main (void) {
char ch;
int a, b;
float x;
double y, z;
ch = 'C';
a = 2; b = 5;
x = 5.5F;
y = 6.0 ;
z = ch + a + b + x + y;
// Результат приведения типов
printf("\n\t The result of the conversion types: %lf\n", z);
// Явное преобразование типов
z = (double) ch + (double) a + (double) b + (double) x + y;
printf("\n\t The apparent conversion types: %lf\n", z);
z = sqrt((double)a/b);
printf("\n\t z = sqrt(%d/%d) = %lf\n", a, b, z);
printf("\n\t z = lg(%d/%d) = %lf\n", a, b, log10(z));
printf("\n\t z = ln(%d/%d) = %lf\n", a, b, log(z));
printf("\n Press any key: ");
_getch();
return 0;
}
В программу включена библиотека математических функций math.h, в которой sqrt() – функция извлечения квадратного корня, log10() – логарифмическая функция по основанию 10, log() – функция натурального логарифма. Все эти функции возвращают результат типа double и вычисляют от числа (выражения) также типа double.
Результат выполнения программы показан на рис 2.3.
(рис 2.3) Вычисления с приведением типовЗадание 2
у задайте в виде у = 6.U, F, L и произведите с ними арифметические действия.10Х по основанию 2Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Выполните тестовый пример для проверки вычислений, т.е. для заданного основания подберите число, от которого логарифм с заданным основанием даст целое число. Например, log10(100.0) = 2.0000.Пример 3.Напишите программу вычисления площади круга и его длины окружности по заданному радиусу, вводимого пользователем с клавиатуры, а также вывода на консоль максимальных значений чисел типа int, float и double.
Для решения примера следует воспользоваться математической библиотекой компилятора, т. е. включить в программу заголовочный файл <math.h>., а также заголовочные файлы <limits.h>, <float.h>.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
// Для числа пи
#define _USE_MATH_DEFINES
#include <math.h>
#include <limits.h>
#include <float.h>
int main (void)
{
double R;
double Sr, Lr;
printf("\n Enter a real greater than zero: ");
scanf_s("%lf", R);
Sr = M_PI*R*R;
Lr = 2*M_PI*R;
printf("\n Area of a circle of radius R = %g is %g", R, Sr);
printf("\n The length of a circle of radius R = %g is %g",R,Lr);
puts("");
printf("\n Maximum integer: %d\n ", INT_MAX);
printf(" Maximum real number of float: %g\n ", FLT_MAX);
printf("Maximum real number type double: %g\n ", DBL_MAX);
printf("\n Press any key: ");
_getch();
return 0;
}
В программу включена константа _USE_MATH_DEFINES для работы с числом M_PI ( $$\pi$$ ). Остальные константы можно найти в справочной документации компилятора. Например, через меню Help $$\to$$ Index системы MS Visual Studio 2008.
Функция scanf_s() определена в компиляторе языка С системы MS Visual Studio 2008. С этой функцией компилятор не выдает предупреждений.
Результат выполнения программы показан на рис 2.4.
(рис 2.4) Пример использования предопределенных константЗадание 3
char, short int, long int.printf() и puts() при консольном выводе информации?math.h?gets_s() с какими разделителями может происходить считывание информации с консоли?gets_s() при считывании информации?scanf_s()?scanf_s()?printf()?5, 5.0, 5.0F, "5", '5', 5u, 5L, 5.0L?
Фундаментальные объекты данных, с которыми работает программа, – это переменные и константы [2.1]. Используемые в программе переменные перечисляются в объявлениях или декларациях, в которых указывается их тип, а также иногда их начальные значения.
С именами переменных связывается тип данных, который контролируется компилятором и для которого выделяется определенное количество байтов памяти [2.1]. Имена переменных должны начинаться с буквы (латинского алфавита) или символа подчеркивания (например, _aza ), за которым могут следовать любые комбинации букв в любом регистре (заглавные или строчные), символы подчеркивания или цифры 0–9. В языке С имеется различие между заглавными и строчными буквами. Поэтому переменная World будет отличаться от переменной world и т.п. При этом в определении переменной не разрешается символ пробела (пробелов) и некоторые другие символы, например, $... .
Стандарт С89 определяет пять базовых типов данных [2.4]:
int – целочисленный тип, целое число;
float – вещественное число одинарной точности с плавающей точкой;
double – вещественное число двойной точности с плавающей точкой;
char – символьный тип для определения одного символа;
void – тип без значения.
Кроме того, существуют модификаторы, которые могут применяться к этим базовым типам [2.1]. Ряд компиляторов может поддерживать еще и логический тип _Bool. Тип void служит для объявления функции, не возвращающей значения, или для создания универсального указателя (pointer).
Объект типа char всегда занимает 1 байт памяти [2.4]. Размеры объектов других типов, как правило, зависят от среды программирования и операционной системы.
Приведем модификаторы базовых типов данных. К ним относятся следующие спецификаторы, предшествующие им в тексте программы [2.4]:
signed, unsigned, long, short
Базовый тип int может быть модифицирован каждым из перечисленных спецификаторов. Тип char модифицируется с помощью unsigned и signed, тип double – с помощью long.
В табл. 2.1 приведены допустимые комбинации типов данных языка С с их минимальным диапазоном значений и типичным размером [13].
| Типы данных языка С | ||
|---|---|---|
| Тип данных | Типичный размер в битах | Минимально допустимый диапазон значений |
| char | 8 (или 1 байт) | от –128 до 127 |
| unsigned char | 8 | от 0 до 255 |
| signed char | 8 | от –128 до 127 |
| int | 16 или 32 | от –32768 до 32767 |
| unsigned int | 16 или 32 | от 0 до 65535 |
| signed int | 16 или 32 | от –32767 до 32767 |
| short int | 16 | от –32767 до 32767 |
| unsigned short int | 16 | от 0 до 65535 |
| signed short int | 16 | от –32767 до 32767 |
| long int | 32 | от –2147483648 до 2147483647 |
| long long int | 64 | от –(263–1 ) до (263–1) для С99 |
| signed long int | 32 | от –2147483647 до 2147483647 |
| unsigned long int | 32 | от 0 до 4294967295 |
| unsigned long long int | 64 | от 0 до (264–1) для С99 |
| float | 32 | от 1Е–37 до 1Е+37 (с точностью не менее 6 значащих десятичных цифр) |
| double | 64 | от 1Е–37 до 1Е+37 (с точностью не менее 10 значащих десятичных цифр) |
| long double | 80 | от 1Е–37 до 1Е+37 (с точностью не менее 10 значащих десятичных цифр) |
Для базового типа int возможны следующие записи с модификатором:
signed или signed int unsigned или unsigned int long или long int short или short int
Для данных вещественного типа максимальные значения абсолютных величин представлены в табл. 2.2 [2.4].
| Вещественные типы данных языка С | ||
|---|---|---|
| Тип данных | Типичный размер в битах | Диапазон абсолютных величин |
| float | 32 | от 3.4Е–38 до 3.4Е+37 |
| double | 64 | от 1.7Е–308 до 1.7Е+308 |
| long double | 80 | от 3.4Е–4932 до 1.1Е+4932 |
В языке С предусматривается преобразование типов в выражениях и приведение типов. Если в выражении смешаны различные типы литералов и переменных, то компилятор преобразует их в один тип. Во-первых, все char и short int значения автоматически преобразуются (с расширением "типоразмера") в тип int. Этот процесс называется целочисленным расширением (integral promotion). Во-вторых, все операнды преобразуются (также с расширением "типоразмера") в тип самого большого операнда. Этот процесс называется расширением типа (type promotion), причем он выполняется пооперационно. Например, если один операнд имеет тип int, а другой– long int, то тип int расширяется в тип long int. Или если хотя бы один из операндов имеет тип double, то любой другой операнд приводится к типу double. Это означает, что такие преобразования, как тип char в тип double, вполне допустимы (если предусматривать, к чему это приведет). После преобразования оба операнда будут иметь один и тот же тип, а результат операции – тип, совпадающий с типом операндов. Приведем последовательность преобразования типов в выражениях по старшинству [2.4]:
ЕСЛИ операнд имеет тип long double ТО второй операнд преобразуется в long double ИНАЧЕ ЕСЛИ операнд имеет тип double ТО второй операнд преобразуется в double ИНАЧЕ ЕСЛИ операнд имеет тип float ТО второй операнд преобразуется в float ИНАЧЕ ЕСЛИ операнд имеет тип unsigned long ТО второй операнд преобразуется в unsigned long ИНАЧЕ ЕСЛИ операнд имеет тип long ТО второй операнд преобразуется в long ИНАЧЕ ЕСЛИ операнд имеет тип unsigned int ТО второй операнд преобразуется в unsigned int
Кроме того, действует правило: если один из операндов имеет тип long, а второй– unsigned int, притом значение unsigned int не может быть представлено типом long, то оба операнда преобразуются в значение типа unsigned long.
В языке С предусматривается явное преобразование (приведение) типов. Общая форма оператора явного приведения типа: (тип) выражение.
В приведенной форме тип – это любой поддерживаемый тип данных. Явное преобразование типа – это операция. Оператор приведения типа является унарным и имеет тот же приоритет, что и остальные
В приводимых ниже программах используются такие средства ввода-вывода, как printf(), getchar(), gets(), scanf().
Приведем характеристику данных функций [2.4].
Прототип функции printf() имеет вид:
int printf(const char *format, ?);
Функция printf() записывает в стандартный поток stdout (стандартный выходной поток данных) значения аргументов из заданного списка аргументов в соответствии со строкой форматирования, адресуемой параметром format. Строка форматирования состоит из элементов двух типов. К элементам первого типа относятся символы, которые выводятся на экран. Элементы второго типа содержат %05d дополнит нулями выводимое целое число, в котором менее пяти цифр, чтобы общая длина равнялась пяти символам. Действие модификатора точности зависит от кода формата, к которому он применяется. Чтобы добавить модификатор точности, следует поставить за спецификатором ширины поля десятичную точку, а после нее – требуемое значение точности (число знаков после десятичной точки). Применительно к целым числам модификатор точности задает минимальное количество выводимых цифр. При необходимости перед целым числом будут добавлены нули. Если модификатор точности применяется к строкам, то число, следующее за точкой, задает максимальную длину поля. Например, спецификация %5.7s выведет строку длиной не менее пяти, но не более семи символов. Если выводимая строка окажется длиннее максимальной длины поля, конечные символы будут отсечены. По умолчанию все выводимые значения выравниваются по правому краю: если ширина поля больше выводимого значения, то оно будет выровнено по правому %–10.4f обеспечит выравнивание вещественного числа с четырьмя десятичными знаками по левому краю в 10-символьном поле. Существуют два модификатора формата, позволяющие функции printf() отображать короткие и длинные целые числа. Это модификатор l (латинская буква эль) уведомляет функцию printf() о длинном типе значения. Модификатор h сообщает функции printf(), что нужно вывести число короткого целого типа. Кроме того, модификатор l можно поставить перед командами форматирования
вещественных чисел. В этом случае он уведомит о выводе значения типа long double.
Спецификаторы формата для функции printf() перечислены в табл. 2.3, взятой из [2.3].
| Спецификаторы формата функции printf() | |
|---|---|
| Код | Формат |
| %c | Символ |
| %d | Десятичное целое число со знаком |
| %i | Десятичное целое число со знаком |
| %e | Экспоненциальное представление числа (в виде мантиссы и порядка, е — на нижнем регистре) |
| %E | Экспоненциальное представление числа (в виде мантиссы и порядка, Е — на верхнем регистре) |
| %f | Десятичное число с плавающей точкой |
| %F | Десятичное число с плавающей точкой (только стандарт С99; если применяется к бесконечности или нечисловому значению, то выдает надписи INF, |
| %g | Использует более короткий из форматов %e или %f |
| %G | Использует более короткий из форматов %E или %F |
| %o | Восьмеричное число без знака |
| %s | Символьная строка |
| %x | Шестнадцатеричное без знака (строчные буквы) |
| %X | Шестнадцатеричное без знака (прописные буквы) |
| %p | Выводит указатель |
| %n | Соответствующий аргумент должен быть указателем на целое число. (Этот спецификатор указывает, что в целочисленной переменной, на которую указывает ассоциированный с данным спецификатором указатель, будет храниться число символов, выведенных к моменту обработки спецификации %n) |
| %% | Выводит знак процента |
Прототип функции getchar() имеет следующий вид:
int getchar(void);
Функция getchar() возвращает из стандартного потока stdin (входного потока данных) следующий символ. При чтении символа предполагается, что символ имеет тип unsigned char, который потом преобразуется в целый. При достижении конца файла, как и при обнаружении ошибки, функция getchar() возвращает значение EOF (End Of File – конец файла).
Прототип функции gets имеет следующий вид:
char *gets(char *str);
Функция gets() читает символы (включая пробелы) из стандартного потока stdin и помещает их в *str (далее это EOF. Для реализации EOF на клавиатуре следует набрать одновременно Ctrl+Z. Вместо разделителя строк в конец строки вставляется нулевой символ, свидетельствующий о ее завершении. Следует учесть, что нет способа ограничить количество символов, которое прочитает функция gets(). Поэтому массив, адресуемый указателем *str, может переполниться, и тогда программа выдаст непредсказуемые результаты.
Прототип функции scanf() имеет следующий вид:
int scanf(const char *format, ?);
Функция scanf() представляет собой функцию для ввода данных общего назначения, которая читает поток stdin и сохраняет информацию в переменных, перечисленных в списке аргументов. Если в строке форматирования встретится разделитель, то функция scanf() пропустит один или несколько разделителей во входном потоке. Под разделителем, или пробельным символом, подразумевают пробел, символ табуляции \t или разделитель строк \n. Все переменные должны передаваться посредством своих адресов, например, с помощью символа . Управляющая строка, задаваемая параметром format, состоит из символов трех категорий: спецификаторов формата, пробельных символов, символов, отличных от пробельных [2.4].
scanf() тип данного, которое будет прочитано. scanf() приведены в табл.2.4.
| Спецификаторы формата функции scanf() | |
|---|---|
| Код | Формат |
| %c | Читает один символ |
| %d | Читает десятичное целое число |
| %i | Читает целое число в любом формате (десятичное, восьмеричное или шестнадцатеричное) |
| %u | Читает десятичное целое число типа short int |
| %e | Читает число с плавающей точкой (и в экспоненциальной форме) |
| %E | Аналогично коду %e |
| %f | Читает число с плавающей точкой |
| %lf | Читает десятичное число с плавающей точкой типа double |
| %F | Аналогично коду %f (для стандарта С99) |
| %g | Читает число с плавающей точкой. |
| %G | Аналогично коду %g |
| %o | Читает восьмеричное число |
| %x | Читает шестнадцатеричное число |
| %X | Аналогично коду %x |
| %s | Читает строку |
| %p | Читает указатель |
| %n | Принимает целое значение, равное количеству прочитанных до сих пор символов |
| %[ ] | Просматривает набор символов |
| %% | Читает знак процента |
Строка форматирования читается слева направо, и *, стоящий после знака % и перед кодом формата, прочитает данные заданного типа, но запретит их присваивание. Команды форматирования могут содержать модификатор максимальной длины поля. Он представляет собой целое число, располагаемое между знаком % и кодом формата, которое ограничивает количество читаемых для всех полей символов. Если входной поток содержит больше заданного количества символов, то при последующем обращении к операции ввода чтение начнется с того места, в котором "остановился" предыдущий вызов функции scanf() [2.3]. Если разделитель (например, пробел) встретится раньше, чем достигнута максимальная ширина поля, то ввод данных завершится. В этом случае функция scanf() переходит к чтению следующего поля. При чтении
одиночных символов символы табуляции и разделители строк читаются подобно любому другому символу.
В программах бывает необходимость определять константы. В языке С типы констант можно задавать явно при использовании суффиксов. Например:
long int j = –12345678L; /* суффикс L */ unsigned int a = 678U; /* суффикс U */ float x = 123.45F; /* суффикс F */ long double z = 12345678.99L; /* суффикс L* /
По умолчанию спецификации f, e, g заставляют функцию scanf() присваивать переменным типа float. Если перед одной из этих спецификаций поставить модификатор l, то функция scanf() присвоит прочитанные данные переменной типа double.
Функция scanf() поддерживает спецификатор формата общего назначения, называемый набором сканируемых символов. В этом случае определяется набор символов, которые могут быть прочитаны функцией scanf() и присвоены соответствующему массиву символов. Для определения такого набора символы, подлежащие сканированию, необходимо заключить в квадратные скобки. Открывающая квадратная скобка должна следовать сразу за знаком процента. При использовании набора сканируемых символов функция scanf() продолжает читать символы и помещать их в соответствующий scanf() читать только те символы, которые отсутствуют в наборе сканируемых символов. Если в строке форматирования встретился символ, отличный от разделителя, то функция scanf() прочитает и отбросит его. Если заданный символ не найден, то функция scanf() завершает работу.
В таких средах разработки как MS Visual Studio 2008 и 2010 рекомендуется для безопасной работы применять функции gets_s() и scanf_s(). Для этих функций при чтении символа или строки следует указать размер в байтах, соответственно для символа или строки. Например, scanf_s("%c", ch, 1). В Visual Studio 2010 тип данных char занимает 1 байт.
Для приводимых примеров будем приводить только текст программы и результат ее выполнения. Программы должны быть написаны в Visual Studio (см. тему 1).
Пример 1. Напишите программу ввода символа, строки, действительных и целых чисел. Действительные числа сложите, целые числа перемножьте. Для действительных чисел использовать типы float и double.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
int main (void) {
// Объявления
char ch, str[79+1];// С учетом одного места для символа '\0'
int x, y, z;
float a, b, c;
double A, B, C;
// Выполнение программы
printf("\n\t Enter a symbol: ");
ch = getchar();
printf("\t The symbol is: %c\n", ch);
_flushall();
printf("\n\t Enter a string: ");
gets_s(str, 79);
printf("\t The string is: %s\n", str);
a = 2.42F; b = 3.58F;
c = a + b;
printf("\n\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c);
A = 12.1234567796602;
B = 2.7182818284509;
C = A + B;
printf("\n\t The sum %1.13f and %1.13f \n\t is equal (as double): %1.13f\n", A, B,C);
x = 2; y = 7;
z = x*y;
printf("\n\t Multiplication %d on %i (as an integer) is equal: %d\n", x, y, z);
printf("\n\n Press any key: ");
_getch();
return 0;
}
В объявлении символьного массива str[79+1] в методических целях сделано напоминание, что для строки следует предусмотреть символ ее завершения, т. е. '\0'. В определении переменных типа float добавлены суффиксы F.
(рис 2.1) Результат программы с базовыми типами данныхРезультат выполнения программы показан на рис 2.1.
Добавим считывание данных с помощью функции scanf_s(). В результате получим следующую программу:
#include <stdio.h>
#include <conio.h>
int main (void)
{
// Объявления
char ch, str[79+1];
int x, y, z;
float a, b, c;
double A, B, C;
// 1-я часть
printf("\n\t Enter a symbol: ");
ch = getchar();
printf("\t The symbol is: %c\n", ch);
_flushall();
printf("\n\t Enter any string: ");
gets_s(str, 79);
printf("\t The string is: %s\n", str);
a = 2.42F;
b = 3.58F;
c = a + b;
printf("\n\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c);
A = 12.1234567796602;
B = 2.7182818284509;
C = A + B;
printf("\n\t The sum %1.13f and %1.13f \n\t is equal (as double): %1.13f\n", A, B,C);
x = 2;
y = 7;
z = x*y;
printf("\n\t The multiplication %d on %i (as an integer) is equal: %d\n", x, y, z);
// 2-я часть
printf("\n\t Enter a symbol: ");
scanf_s("%c", ch, 1);
printf("\t The symbol is: %c\n", ch);
printf("\n\t Enter any string: ");
scanf_s("%s", str, 79);
printf("\t The string is: %s\n", str);
_flushall(); // для устранения пустой строки
printf("\t Enter a real number a: ");
scanf_s("%f", a);
printf("\t Enter a real number b: ");
scanf_s("%f", b);
c = a + b;
printf("\t The sum %1.2f and %1.2f (as float) is equal: %1.4f\n", a, b, c);
printf("\n\t Enter a real number A: ");
scanf_s("%lf", A);
printf("\t Enter a real number B: ");
scanf_s("%lf", B);
C = A + B;
Результат выполнения видоизмененной программы показан на рис 2.2.
(рис 2.2) Результат программы с различным вводом данныхВ начале функции int main(void) сделано объявление переменных, которые будут использоваться в программе. Каждый тип переменных объявлен через запятую. В частности, char str[81] означает printf() выводят либо только сообщения, либо еще заданные переменные соответствующих типов.
Функция _flushall() используется для того, чтобы устранить пробельную строку, образованную либо после действия функции getchar(), либо после действия функции scanf(). В некоторых компиляторах функция _flushall() используется без префиксного нижнего подчеркивания.
Функция gets() позволяет считывать символы с наличием разделителей, в частности, с пробелами. В Microsoft Visual Studio 2010 рекомендуется использовать gets_s(), чтобы не было предупреждений.
Следует обратить внимание на формат записи функций scanf(). Если сканируются числа, или одиночные символы, то присваивание этих символов переменным, которые были объявлены через соответствующие типы данных, осуществляется с помощью взятия адреса этих переменных, т.е. с помощью символа , например, scanf_s("%c",ch, 1). При сканировании массива символов, т.е. при сканировании строки, символ не используется. Имя массива само по себе является указателем. double в функции scanf_s() используется спецификатор l.
Задание 1
\t. Для вывода строки предусмотрите табулированный вывод с помощью спецификатора формата %xs, где х – требуемое число позиций отступа.gets_s(), превышающую число 1._flushall(). В отчет вставьте полученный результатfloat с десятью знаками после десятичной точки. Выведите и проанализируйте результат сложения. Объясните результат.puts() и примените ее вместо функции printf(), которая использовалась в режиме сообщений. В отчет вставьте полученный результат. Объясните результат.Пример 2. Напишите программу вычисления алгебраических выражений с приведением типов char, int, float, double.
Возможный программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main (void) {
char ch;
int a, b;
float x;
double y, z;
ch = 'C';
a = 2; b = 5;
x = 5.5F;
y = 6.0 ;
z = ch + a + b + x + y;
// Результат приведения типов
printf("\n\t The result of the conversion types: %lf\n", z);
// Явное преобразование типов
z = (double) ch + (double) a + (double) b + (double) x + y;
printf("\n\t The apparent conversion types: %lf\n", z);
z = sqrt((double)a/b);
printf("\n\t z = sqrt(%d/%d) = %lf\n", a, b, z);
printf("\n\t z = lg(%d/%d) = %lf\n", a, b, log10(z));
printf("\n\t z = ln(%d/%d) = %lf\n", a, b, log(z));
printf("\n Press any key: ");
_getch();
return 0;
}
В программу включена библиотека математических функций math.h, в которой sqrt() – функция извлечения квадратного корня, log10() – логарифмическая функция по основанию 10, log() – функция натурального логарифма. Все эти функции возвращают результат типа double и вычисляют от числа (выражения) также типа double.
Результат выполнения программы показан на рис 2.3.
(рис 2.3) Вычисления с приведением типовЗадание 2
у задайте в виде у = 6.U, F, L и произведите с ними арифметические действия.10Х по основанию 2Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Выполните тестовый пример для проверки вычислений, т.е. для заданного основания подберите число, от которого логарифм с заданным основанием даст целое число. Например, log10(100.0) = 2.0000.Пример 3.Напишите программу вычисления площади круга и его длины окружности по заданному радиусу, вводимого пользователем с клавиатуры, а также вывода на консоль максимальных значений чисел типа int, float и double.
Для решения примера следует воспользоваться математической библиотекой компилятора, т. е. включить в программу заголовочный файл <math.h>., а также заголовочные файлы <limits.h>, <float.h>.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
// Для числа пи
#define _USE_MATH_DEFINES
#include <math.h>
#include <limits.h>
#include <float.h>
int main (void)
{
double R;
double Sr, Lr;
printf("\n Enter a real greater than zero: ");
scanf_s("%lf", R);
Sr = M_PI*R*R;
Lr = 2*M_PI*R;
printf("\n Area of a circle of radius R = %g is %g", R, Sr);
printf("\n The length of a circle of radius R = %g is %g",R,Lr);
puts("");
printf("\n Maximum integer: %d\n ", INT_MAX);
printf(" Maximum real number of float: %g\n ", FLT_MAX);
printf("Maximum real number type double: %g\n ", DBL_MAX);
printf("\n Press any key: ");
_getch();
return 0;
}
В программу включена константа _USE_MATH_DEFINES для работы с числом M_PI ( $$\pi$$ ). Остальные константы можно найти в справочной документации компилятора. Например, через меню Help $$\to$$ Index системы MS Visual Studio 2008.
Функция scanf_s() определена в компиляторе языка С системы MS Visual Studio 2008. С этой функцией компилятор не выдает предупреждений.
Результат выполнения программы показан на рис 2.4.
(рис 2.4) Пример использования предопределенных константЗадание 3
char, short int, long int.printf() и puts() при консольном выводе информации?math.h?gets_s() с какими разделителями может происходить считывание информации с консоли?gets_s() при считывании информации?scanf_s()?scanf_s()?printf()?5, 5.0, 5.0F, "5", '5', 5u, 5L, 5.0L?
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.