Определение строковой переменной
Рис. 3.10. Данные строкового типа в памяти
|
Как вы помните, язык Си не содержит строкового типа данных и не имеет никаких средств для работы со строками. К счастью, Си позволяет работать с данными строкового типа, используя массивы. Раньше мы уже определяли строку как ряд последовательных символов. Именно этим она и является — рядом символьных переменных, объединенных в нечто, называемое массивом. Элементы строки хранятся вместе в последовательных элементах памяти. В качестве примера на рис.3.10 показано, как выглядит переменная, имеющая значение "Привет". Каждая буква хранится в отдельном элементе памяти так же, как одиночная символьная переменная, но вся строка может быть выведена на экран монитора как единое целое при помощи одной функции puts(). Последовательность \0 является специальным символом, который Си вставляет после каждой строки. Он отмечает конец строки, указывая функции типа puts(), где следует прекратить вывод символов на экран.
Вы уже знаете как определить строковую константу — с помощью директивы #define, заключив символы строки в кавычки:
#define CLIENT "Кейт Тиммонс"Чтобы определить строковую переменную, необходимо использовать тип char и указать максимальное число символов, которое может содержать строка. Например, так:
char var_name[N];где var_name означает имя переменной, а N — максимальное количество символов, которое всегда заключается в квадратные скобки: прямую [ и обратную ].
Число, указанное в скобках, должно быть на единицу больше максимального количества символов, которое вы собираетесь использовать, так как Си нуждается в дополнительном пространстве, чтобы поставить нулевой символ. Например, переменная, содержащая аббревиатуры названий штатов, может быть определена следующим образом:
char state[3];
Рис. 3.11. Определение строковой переменной
при этом, как показано на рис.3.11, создается строковая переменная, которая называется state и содержит два символа, плюс нулевой символ, означающий конец строки (\0).
Вы не можете записать в строку больше символов, чем было указано при ее определении, так как Си отводит ровно столько памяти, сколько необходимо для хранения заданного числа символов. Поэтому, прежде чем определять переменную, хорошенько подумайте, сколько символов может вам потребоваться.
Почему это так важно, можно пояснить на следующем жизненном примере. Допустим, вы вводите переменную, содержащую имена клиентов. Вы определили ее следующим образом:
char client[10];
Программа работает безупречно до тех пор, пока вы не получаете заказ от господина Флаглехоффена. Когда вы попытаетесь ввести его имя в список, ваша программа остановится из-за ошибки выполнения, что иллюстрирует рис.3.12.
Рис. 3.12. Нельзя присвоить строковой переменной значение,имеющее большее количество символов, чем было для нее зарезервировано
Для того чтобы избежать подобной неприятности, вы могли бы в определении переменной несколько увеличить допустимое количество символов:
char client[80];но если в программе будет несколько таких переменных, вы впустую потратите немало памяти компьютера.
Определив строковую переменную, вы тут же можете инициализировать ее, присвоив ей начальное значение в тексте программы. Помимо этого, значение можно присвоить, введя его с клавиатуры или из дискового файла, как это делается для переменных любого другого типа (подробнее о том, как вводить значение строковой переменной с клавиатуры, вы узнаете в следующей главе). В языке Си нельзя присваивать значение строковой переменной так, как это сделано в примере:
main() { char client[15]; client = "Кейт"; puts(client); }где употребляется не разрешенная инструкция
client = "Кейт";Если вы хотите присвоить начальное значение строковой переменной, это можно сделать, определив используемую переменную одним из двух допустимых способов.
Вы можете присвоить значение определением переменной перед функцией main():
char client[] = "Флаглехоффен"; main() { puts(client); }
Рис. 3.13. Инициализация строки
Заметьте, что в этом случае значение максимального числа символов строковой переменной в квадратных скобках не проставлено. Максимальное число символов строковой переменной при таком способе определения зависит от используемого компилятора, но практически определяется количеством символов в начальном значении плюс один (рис.3.13). Заметим, что в качестве параметра функции puts() используется только имя переменной без каких-либо квадратных скобок.
Другой способ присваивания начального значения внутри функции main() несколько более сложен:
main(){ static char greet[] = "Привет"; puts(greet);}Определение выполняется внутри функции main(), но начинается со слова static, а переменная называется статической. Определяемая таким образом переменная может быть использована только внутри функции, в теле которой она была определена. Если вы желаете присвоить начальное значение строковой переменной, определяемой внутри функции, то ее следует определить как статическую переменную (подробнее смотри в главе 7).
Типы данных и функции
Тип, присвоенный константе или переменной, определяет то, каким образом функции могут их использовать. Большинство функций может использовать в качестве параметров только данные определенного типа. Например, функция puts() может работать только со строками, так что при компиляции программы
#define PI 3.14 main() { puts(PI); }будет возникать ошибка. Функция puts() не может работать с вещественными числами.
Распространенной ошибкой начинающих программистов является использование двойных кавычек при попытке определить символьную константу:
#define INITIAL "A"Си воспримет определение как попытку задать строковую константу, и вы получите ошибку компиляции, когда попробуете использовать эту константу при вызове функции, требующей в качестве параметра данные типа char. Даже один символ, заключенный в двойные кавычки, рассматривается Си как строка.
Когда мы будем рассматривать ввод и вывод в следующих главах, обращайте особое внимание на то, данные какого типа использует в качестве параметров каждая функция.
Литералы
Литералом* называется любой элемент данных, который вводится непосредственно в инструкции языка Си. Литералом может являться любое число, символ или строка, которые вы вводите как начальное значение переменной. В примере:
count = 5;число 5 является литералом. Это означает, что вы хотите, чтобы именно это число было присвоено переменной в качестве ее значения. В примере:
#define INIT 'C'rate = 0.55;client = "Кейт";puts("555-1234");буква C, число 0.55, слово Кейт и телефонный номер 555-1234 являются литералами.
Проектирование программы
Данные имеют огромное значение для программы на языке Си. Если перед тем как писать программу вы не решите как именно будете использовать данные, вероятность ошибок компиляции и выполнения вырастет во много раз.
В этой главе мы рассматривали константы и переменные в отношении данных, которые вы должны ввести в программу, но данные необходимо рассматривать и в качестве информации, которую вы хотите получить от программы. Для того чтобы это было возможно, надо определить также и переменные для хранения этой информации.
____________________
* В литературе чаще используется термин «константное выражение». (Прим.перев.)
Фактически, многие программисты начинают писать план программы именно с вывода. Определив, какую именно информацию вы хотите получить от программы, легче определить, какую информацию необходимо ввести и как ее следует обрабатывать.
Давайте для примера рассмотрим программу, которая рассчитывает налог на продажи. Вот последовательность шагов определения необходимых констант и переменных.
- Решить, какая информация необходима программе:
- Вывод — объем всех продаж плюс налог на продажи.
- Для того чтобы получить эту информацию, необходимо ввести: стоимость каждого наименования товара и ставку налога. Стоимость товара считается в долларах, следовательно, необходимо определить переменную типа float. Ее можно назвать sale. Ставка налога является для каждого штата фиксированной величиной, так что ее можно определить как константу. Назовем ее TAX_RATE.
- Программа должна умножить стоимость товара на ставку налога. Например, если цена равна 25.00 доллара, а ставка налога равна 0.05, величина налога на продажи составит 1.25 доллара. Для хранения этого значения нужна переменная типа float. Назовем ее sales_tax.
- Программа должна прибавить сумму налога к цене товара для того, чтобы получить стоимость с учетом налога. В нашем примере эта стоимость равна 26.25 доллара. Для хранения этого значения необходима переменная типа float. Назовем ее total.
- Написать директивы #define для определения необходимых констант: #define TAX_RATE 0.05
- Написать определения переменных: float sale, sales_tax, total;
Теперь, когда вы спланировали все необходимые данные, можно приступать к написанию программы.
<> | Вопросы |
|
<> | Упражнения |
|
ГЛАВА 4. ВЫВОД В СИ/СИ++
Выводом называется процедура переноса данных из памяти компьютера в другое место. Данные можно вывести на экран, отпечатать на принтере или сохранить на диске в виде файла. Кроме того, данные можно сохранить на магнитной ленте или послать по телефонной линии через модем или по факсу.
Вывод данных не означает, что они удаляются из памяти компьютера или что изменяется способ их хранения, компьютер просто копирует данные и посылает их куда-то еще.
В этой главе вы научитесь выводить данные на экран монитора.
|
Функции, используемые для вывода данных, зависят от типа данных и способа их представления. Наиболее прост вывод строк и символьных данных.
Функция puts()
По предыдущим главам вы уже хорошо знакомы с функцией puts(), которая осуществляет вывод информации на экран. Параметр (информация, заключенная в круглые скобки, которая выводится на экран) должен относиться к одному из следующих типов данных:
- Строковый литерал:
· Строковая константа:
#define MESSAGE "Всем привет" main() { puts(MESSAGE); }· Строковая переменная:
char greeting[]="Всем привет"; main() { puts(geering); }
|
Использование любого другого типа констант, переменных или литералов приведет к ошибке компиляции. Строковый литерал, в отличие от имени константы или переменной, должен быть заключен в двойные кавычки.
Большинство компиляторов выполняют перевод строки после выполнения функции puts(). Это значит, что после того, как данные выведены на экран монитора, курсор автоматически переходит в начало следующей строки.
Однако некоторые компиляторы не выполняют перевод строки. При работе с такими компиляторами для перевода курсора вы должны вставить специальный управляющий код \n в конце строки, предназначенной для вывода на экран (подробнее об управляющих кодах смотри дальше в этой главе). Хотя это свойство компилятора выглядит как недостаток, на самом деле оно может оказаться довольно полезным. Если автоматический перевод строки отсутствует, можно использовать несколько инструкций puts() для вывода на экран одной строки, поставив код \n только в том месте, где вы хотите закончить ее и перейти на следующую.
|
Функция putchar()
Функция putchar() предназначена для вывода единичного символа на экран. Параметром функции может являться:
· символьный литерал:
putchar('H');· символьная константа:
#define INITIAL 'H' main() { putchar(INITIAL); }· символьная переменная:
main() { char letter; letter='G'; putchar(letter); }С помощью функции putchar() можно отображать только один символ. Инструкция
putchar('Hi');приведет к ошибке компиляции.
При выводе на экран символьного литерала или управляющего кода их следует заключать в одинарные кавычки.
Большинство компиляторов Си не имеет автоматического перевода строки после функции putchar(), и курсор остается сразу за выведенным символом, не переходя к началу следующей строки. Для перехода на новую строку вы должны ввести управляющий код \n, который рассматривается дальше в этой главе.
|