Как вывести символ в си
Перейти к содержимому

Как вывести символ в си

  • автор:

Как выводить русские символы в си?

Поскольку русский — не часть ASCII, работает это по-разному в зависимости от кодировки. Если предположить, что исходник в UTF-8, то русские символы закодированы двумя байтами, а %c выводит только один. Если на одном выведенном байте остановиться — получится фигня с вопросом. Но если вывести подряд все байты многобайтового символа — получится этот символ.

как исправить

вариантов несколько. Самый простой — выводить строки целиком. Если надо выводить посимвольно, можно узнавать количество байт в представлении одного символа функцией mblen , типа того:

#include #include #include #include int main() < char *a = "Привет, мир"; int s; setlocale(LC_ALL, ""); for (; *a != '\0'; a+=s) < s = mblen(a, strlen(a)); printf("%.*s-", s, a); >return 0; >

Здесь setlocale нужен для того, чтобы mblen понял, в какой кодировке символы на входе. Локаль в момент выполнения должна быть совместимой с кодировкой исходника в момент компиляции, если это условие не выполняется, работать будет неправильно.

Ещё вариант — работать не с многобайтовой кодировкой а с wchar_t :

#include #include #include int main() < wchar_t *a = L"Привет, мир"; setlocale(LC_ALL, ""); for (; *a != '\0'; a++) < printf("%lc-", *a); >return 0; >

Здесь setlocale нужен для другого: он говорит внутренностям printf в какую локаль выполняется вывод чтобы в неё конвертировать wchar_t . Если локаль во время выполнения не будет соответствовать кодировке исходника, код всё равно будет работать.

Символы и строки

До сих пор мы работали только с числовыми данными, как целыми, так и действительными. Но очень часто (если речь идет не о сугубо научных рассчетах) приходится оперировать с текстовой информацией. В этом листочке содержится основная информация о принципах работы с символами и текстами.

Символьный тип char

Любой текст состоит из символов. Символ — это некоторый значок, изображение. Один и тот же символ можно записать по-разному, например, два человека по-разному напишут от руки букву “A”, и даже в компьютерном представлении одна и та же буква будет выглядеть по-разному, если ее отображать разными шрифтами, при этом это будет все равно один и тот же символ. Верно и другое: разные символы могут быть записаны одинаково, например, вот две разные буквы, одна — латинского алфавита, другая — русского: “A” и “А”. Несмотря на то, что они выглядят одинаково, удобней считать их разными символами.

Итак, способ хранения текстовой информации в компьютере не связан напрямую с изображением этого текста. Вместо символов хранятся их номера — числовые коды, а вот то, как выглядит символ с данным числовым кодом на экране напрямую зависит от того, какой используется шрифт для отображения символов. При этом, разумеется, следовало бы договориться о единообразном способе кодирования символов числовыми кодами, иначе текст, записанный на одном компьютере, невозможно будет прочитать на другом компьютере.

Первоначально договорились под кодирование одного символа отвести один байт, то есть 8 бит информации. Таким образом можно было закодировать 256 различных значений, то есть в записи текста можно использовать 256 различных символов. Этого достаточно, чтобы отобразить все символы латинского алфавита, цифры, знаки препинания и некоторые другие символы. Стандарт, указывающий, какие числовые коды соответствуют каким основным символам, называется ASCII. В таблицу ASCII включены символы с кодами от 0 до 127, то есть ASCII — это семибитный код. Вот так выглядит таблица ASCII:

Char Dec Oct Hex | Char Dec Oct Hex | Char Dec Oct Hex | Char Dec Oct Hex ------------------------------------------------------------------------------------- (nul) 0 0000 0x00 | (sp) 32 0040 0x20 | @ 64 0100 0x40 | ` 96 0140 0x60 (soh) 1 0001 0x01 | ! 33 0041 0x21 | A 65 0101 0x41 | a 97 0141 0x61 (stx) 2 0002 0x02 | " 34 0042 0x22 | B 66 0102 0x42 | b 98 0142 0x62 (etx) 3 0003 0x03 | # 35 0043 0x23 | C 67 0103 0x43 | c 99 0143 0x63 (eot) 4 0004 0x04 | $ 36 0044 0x24 | D 68 0104 0x44 | d 100 0144 0x64 (enq) 5 0005 0x05 | % 37 0045 0x25 | E 69 0105 0x45 | e 101 0145 0x65 (ack) 6 0006 0x06 | & 38 0046 0x26 | F 70 0106 0x46 | f 102 0146 0x66 (bel) 7 0007 0x07 | ' 39 0047 0x27 | G 71 0107 0x47 | g 103 0147 0x67 (bs) 8 0010 0x08 | ( 40 0050 0x28 | H 72 0110 0x48 | h 104 0150 0x68 (ht) 9 0011 0x09 | ) 41 0051 0x29 | I 73 0111 0x49 | i 105 0151 0x69 (nl) 10 0012 0x0a | * 42 0052 0x2a | J 74 0112 0x4a | j 106 0152 0x6a (vt) 11 0013 0x0b | + 43 0053 0x2b | K 75 0113 0x4b | k 107 0153 0x6b (np) 12 0014 0x0c | , 44 0054 0x2c | L 76 0114 0x4c | l 108 0154 0x6c (cr) 13 0015 0x0d | - 45 0055 0x2d | M 77 0115 0x4d | m 109 0155 0x6d (so) 14 0016 0x0e | . 46 0056 0x2e | N 78 0116 0x4e | n 110 0156 0x6e (si) 15 0017 0x0f | / 47 0057 0x2f | O 79 0117 0x4f | o 111 0157 0x6f (dle) 16 0020 0x10 | 0 48 0060 0x30 | P 80 0120 0x50 | p 112 0160 0x70 (dc1) 17 0021 0x11 | 1 49 0061 0x31 | Q 81 0121 0x51 | q 113 0161 0x71 (dc2) 18 0022 0x12 | 2 50 0062 0x32 | R 82 0122 0x52 | r 114 0162 0x72 (dc3) 19 0023 0x13 | 3 51 0063 0x33 | S 83 0123 0x53 | s 115 0163 0x73 (dc4) 20 0024 0x14 | 4 52 0064 0x34 | T 84 0124 0x54 | t 116 0164 0x74 (nak) 21 0025 0x15 | 5 53 0065 0x35 | U 85 0125 0x55 | u 117 0165 0x75 (syn) 22 0026 0x16 | 6 54 0066 0x36 | V 86 0126 0x56 | v 118 0166 0x76 (etb) 23 0027 0x17 | 7 55 0067 0x37 | W 87 0127 0x57 | w 119 0167 0x77 (can) 24 0030 0x18 | 8 56 0070 0x38 | X 88 0130 0x58 | x 120 0170 0x78 (em) 25 0031 0x19 | 9 57 0071 0x39 | Y 89 0131 0x59 | y 121 0171 0x79 (sub) 26 0032 0x1a | : 58 0072 0x3a | Z 90 0132 0x5a | z 122 0172 0x7a (esc) 27 0033 0x1b | ; 59 0073 0x3b | [ 91 0133 0x5b | < 123 0173 0x7b (fs) 28 0034 0x1c | < 60 0074 0x3c | \ 92 0134 0x5c | | 124 0174 0x7c (gs) 29 0035 0x1d | = 61 0075 0x3d | ] 93 0135 0x5d | >125 0175 0x7d (rs) 30 0036 0x1e | > 62 0076 0x3e | ^ 94 0136 0x5e | ~ 126 0176 0x7e (us) 31 0037 0x1f | ? 63 0077 0x3f | _ 95 0137 0x5f | (del) 127 0177 0x7f

При этом символы с кодами, меньшими 32 — это специальные управляющие символы, которые не отображаются на экране. Например, для того, чтобы обозначить конец строки в системе Linux используется один символ с кодом 10, а в системе Windows — два подряд идущих символа с кодами 13 и 10, символы с кодами 48-57 соответствуют начертанию арабских цифр (обратите внимание, символ с кодом 0 — это вовсе не символ, отображающийся на экране, как “0”), символы с кодами 65-90 — заглавные буквы буквы латинского алфавита, а если к их кодам прибавить 32, то получатся строчные буквы латинского алфавита. В промежутках между указанными диапазонами находятся знаки препинания, математические операции и прочие символы.

Но в ASCII-таблицы нет русских букв! А также нет букв сотен других национальных алфавитов. Первоначально для отображения букв национальных алфавитов использовали вторую половину возможного значения байта, то есть символы с кодами от 128 до 255. Это приводило к множеству проблем, например, поскольку 128 значений явно недостаточно для того, чтобы отобразить символы всех национальных алфавитов (даже недостаточно для того, чтобы отобразить символы одного алфавита, например, китайской письменности. Поэтому в настоящее время для кодирования символов используется стандарт Unicode, последняя версия 5.2 которого (октябрь, 2009) включает 107361 различный символ. Естественно, для кодирования Unicode-символов недостаточно одного байта на символ, поэтому используются многобайтовые кодировки (для представления одного символа необходимо несколько байт).

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

В языке C++ для хранения однобайтового символа используется тип данных char . Переменную типа char можно рассматривать двояко: как целое число, занимающее 1 байт и способное принимать значения от -128 до 127 (тип signed char , есть также беззнаковая модификация unsigned char , принимающая значения от 0 до 255) и как один символ текста. Само по себе определение char может оказаться как знаковым, так и беззнаковым, в зависимости от операционной системы и компилятора. Поэтому использовать тип char не рекомендуется, лучше явно указывать будет ли он знаковым ( signed ) или беззнаковым ( unsigned ).

Как и целые числа, данные типа char можно складывать, вычитать, умножать и даже делить. Но если операции умножения и деления, как правило, бессмысленны, то сложение и вычитание вполне осмысленно. Например, если к символу ‘A’ прибавить 1, то получится символ ‘B’ , а если вычесть 1, то получится символ ‘@’ . То есть в следующем фрагменте кода на экран будет выведена буква B .

char c = 'A'; c = c + 1; cout 

В этом примере видно, что переменным типа char можно присваивать значения, равные ASCII кодам символов, если эти символы заключать в кавычки. То есть запись 'A' будет соответствовать символу A , или ASCII коду 65.

Также в этом примере видно, что при выводе на экран переменной типа char мы увидим изображение этого символа. Как же узнать значение ASCII-кода символа? Его не нужно узнавать, сам символ - это и есть ASCII-код. А как его вывести на экран? Очень просто - нужно преобразовать значение величины типа char к значению типа int . Например, вот так:

cout 

Имя типа, записанное в скобочках перед значением, это и есть оператор преобразования значения к указанному типу.

Аналогично, при считывании переменной типа char через поток cout , из потока ввода считывается один символ, переменная получает значение, равное его ASCII-коду. Например, если написать программу, содержающую строчку

char c; cin >> c;

запустить ее, ввести символ A (безо всяких кавычек!), то в переменную c будет записано значение 65 - ASCII-код символа A .

Переменным типа char можно и явно присваивать числовые значения. Например, можно сделать так:

#include using namespace std; int main() < unsigned char c = 'A'; cout << c << " " << (int) c << endl; c = 126; // char можно присвоить и числовое значение cout

Эта программа выведет две строки: “ A 65 ” и “ ~ 126 ”, то есть символы с ASCII-кодами 65 (A) и 126 (~) и сами ASCII-коды.

Организовать последовательное посимвольное считывание всего входного потока можно при помощи цикла while :

#include using namespace std; int main() < char c; while (cin >> c) // Цикл пока считывание успешно < // Делаем необходимые действия, // обрабатывая символ c >return 0; >

В этом примере программа будет посимвольно считывать входной поток (по умолчанию — ввод с клавиатуры), пока не встретит признак конца файла. Для того, чтобы сообщить программе о завершении входного потока при вводе с клавиатуры необходимо нажать клавиши Ctrl-d в системе Linux и Ctrl-z в системе Windows.

Эта программа при считывании данных будет игнорировать символы–разделители: пробелы, символы новой строки и табуляции. Если нужно, чтобы в переменную c считывались все символы, в том числе и разделители, то необходимо для потока ввода cin установить манипулятор noskipws при помощи инструкции:

cin >> noskipws;

>S; // считать строку S с клавиатуры --> >S1>>S2>>S3; --> >S) // Цикл до тех пор, пока считывание успешно --> >. -->

Строки в языке C++

Текстовая строка - это последовательность символов. Поскольку символы в строке пронумерованы, то естественным представлением для строки был бы массив символов. Так строки и представлялись в языке C - строкой считался массив символов, а для обозначения конца строки использовался символ с ASCII-кодом 0, что позволяло хранить строки переменной длины (то есть в массиве char[n] можно было хранить строки любой длины, не превосходящей n-1 . Такой способ хранения строк порождал ряд неудобств: любая строка была ограничена по длине размером массива, а чтобы вычислить длину строки необходимо было пройти по всей строке до появления нулевого символа, то есть определение длины строки требует количество операций, пропорциональное этой длине.

В языке C++ для представления строк существует более совершенный тип данных string , в основе которого лежит такой же массив символов, завершающийся нулевым символом, но содержащий еще ряд дополнительных возможностей. Для работы со строками языка C++ необходимо в начале программы подключить описание типа string , которое находится в одноименном файле:

#include

Переменная для хранения строковых данных объявляется так:

string S;

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

S = "Hello, world!";

С записью строк в тексте программы в кавычках мы уже встречались, когда выводили текст в поток cout . Обратите внимание - константы типа char записываются в одинарных кавычках, а строки - в двойных кавычках. В частности, 'A' - это символ, а "A" - это строка, состоящая из одного символа. Поэтому переменной типа char нельзя присвоить значение "A" , поскольку они имеют несовместимые типы данных.

По сути, переменная типа string является массивом символов и с каждым символом этой строки можно работать по-отдельности, обращаясь к ним по индексу, как к элементам массива. Например:

cout 

Для определения длины строки есть метод size() , применяемый к строке. Он возвращает целое число - количество символов в строке. Его можно использовать так:

string S; cin >> S; cout 

Для начала нам понадобится две операции над строками: сложение двух строк и изменение размера строки.

Основная операция над строками - сложение: например, при сложении строк "Hello, " и "world!" получится строка "Hello, world!" . Такая операция над строками называется .

Вот пример использования конкатенации строк:

string S, S1, S2; // Объявление трех строк cout > S1; // Считали строку S1 S2 = "Hello, " // Присвоили строке значение S = S2 + S1; // Использование конкатенации cout 

Другая операция - изменение размера строки. Для этого существует метод resize , который применяется к строке. У метода resize есть две формы записи: с одним и с двумя параметрами. Если он вызывается с одним параметром, то этот параметр задает новую длину строки. Например, так:

string S = "abcdefg" S.resize(3); cout 

Второй параметр метода resize задает символ, которым будут заполнены символы в строке, если размер строки увеличивается в результате изменения размера. Например:

string S = "abc" S.resize(6, 'd'); cout 

При считывании строк из входного потока считываются все символы, кроме символов–разделителей (пробелов, табуляций и новых строк), которые являются границами между строками. Например, если при выполнении следующей программы

string S1, S2, S3; // объявили 3 строки cin>>S1>>S2>>S3;

ввести текст ‘ Мама мыла раму ’ (с произвольным количеством пробелов между словами), то в массив S1 будет записана строка "Мама" , в S2 — "мыла" , в S3 — "раму" .

Таким образом, организовать считывание всего файла по словам, можно следующим образом:

string s; while (cin >> s) // Цикл пока считывание успешно < // Делаем необходимые действия >

Если нужно считать строку со всеми пробелами, то необходимо использовать функцию getline следующим образом:

string S; getline(cin, S);

В данном случае если запустить эту программу и ввести строку "Мама мыла раму" , то именно это значение и будет присвоено строке S . Считать же весь входной поток по строкам можно при помощи следующего кода:

string s; while (getline(cin, S)) // Цикл пока считывание успешно < // Делаем необходимые действия >

Упражнения

3A: ASCII-код символа

Считайте со стандартного ввода символ и выведите его ASCII-код. Решите эту задачу с использованием только одной переменной типа char .

Программа получает на вход один символ с ASCII кодом от 33 до 126.

3B: Символ с данным ASCII-кодом

Считайте со стандартного ввода целое число и выведите ASCII-символ с таким кодом. Решите эту задачу с использованием только одной переменной типа int .

Программа получает на вход число от 33 до 126.

3C: Таблица ASCII

Выведите все символы ASCII с кодами от 33 до 126 и их коды в следующем виде:

! 33 " 34 # 35 . > 125 ~ 126

3D: Символы в заданном интервале

Выведите подряд, без пробелов, все символы, лежащие в таблице ASCII между двумя заданными символами.

Программа получает на вход один символ с ASCII-кодом от 33 до 126, являющийся начальным символом интервала и число от 33 до 126, являющееся ASCII-кодом символа, завершающего интервал.

A 68
ABCD
0 57
0123456789

3E: IsDigit

Для данного символа, считанного со стандартного ввода, проверьте, является ли он цифрой. Программа должна вывести слово YES , если символ является цифрой, или слово NO .

Решение оформите в виде функции bool IsDigit(char c) . В решении нельзя использовать циклы. В решении нельзя использовать константы с неочевидным значением типа 48 или 57.

3F: ToUpper

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

Считайте один символ со стандартного ввода и переведите его в верхний регистр. В решении нельзя использовать циклы. В решении нельзя использовать константы с неочевидным значением.

3G: Сменить регистр символа

Напишите функцию char CaseChange (char c) , меняющую регистр символа, то есть переводящую заглавные буквы в строчные, а строчные - в заглавные, остальные символы не меняющие.

Считайте один символ со стандартного ввода, выведите результат работы данной функции. В решении нельзя использовать циклы. В решении нельзя использовать константы с неочевидным значением.

3H: Нижний регистр

Дана строка, возможно, содержащая пробелы. Считайте эту строку и переведите все символы этой строки в нижний регистр. Решение оформите в виде функции void ToLower (string & S) , получающей в качестве параметра строку по ссылке и изменяющая символы этой строки.

Для перевода одного символа в нижний регистр напишите отдельную функцию.

Hello, world!
hello, world!

3I: Проверить строки на равенство

Даны две строки (возможно, с пробелами). Проверьте, равны ли они. Если строки равны, выведите слово YES , если строки не равны, выведите слово NO .

Решение оформите в виде функции bool IsEqual(const string &S1, const string & S2) .

После того, как вы решите эту задачу, вам разрешается использовать оператор == для сравнения строк.

Hi
HI
Bye
Bye

3J: Извлечь цифры

Дана строка, возможно, содержащая пробелы. Извлеките из этой строки все символы, являющиеся цифрами и составьте из них новую строку. Решение оформите в виде функции string ExtractDigits (const string & S) , получающей на вход исходную строку S и возвращающую новую строку, содержащую только цифры данной строки.

Указание. Заведите строку Answer , пройдите по всем символам данной строки, при обнаружении цифры добавляйте ее в конец строки Answer , увеличивая ее размер на 1. По завершении цикла верните значение Answer .

3K: Значение выражения - 1

Дана строка, состоящая из n цифр, между которыми стоит n-1 знак операции, каждый из которых может быть либо +, либо -. Вычислите значение данного выражения.

Решение оформите в виде функции int Evaluate(const string & S) .

3L: StrToInt

Дана строка, содержащее запись в виде символов целого числа от 0 до 10 9 -1. Определите значение этого числа в виде переменной int. Решение задачи оформите в виде функции int StrToInt (const string & S) .

Функция main должна быть такой:

int main() < string S; cin >> S; cout

3M: IntToStr

Дана целое число от -10 9 +1 до 10 9 -1. Запишите это число в строку, то есть выполните преобразование, обратное предыдущей задаче (но только допускаются отрицательные числа).

Решение задачи оформите в виде функции string IntToStr (int n) .

Функция main должна быть такой:

int main() < int n; cin >> n; cout

4A: Самое длинное слово

Дана строка. Найдите в этой строке самое длинное слово и выведите его. Если в строке несколько слов одинаковой максимальной длины, выведите первое из них. Решение оформите в виде функции string LongestWord (const string & S) .

In a hole in the ground there lived a hobbit.
ground

4B: Слова с прописной буквы

Дана строка. Измените регистр символов в этой строке так, чтобы первая буква каждого слова была заглавной, а остальные буквы - строчными.

Решение оформите в виде функции void Capitalization (string & S) .

In a hole in the ground there lived a hobbit.
In A Hole In The Ground There Lived A Hobbit.

4C: Шифр Цезаря

В шифре Цезаря каждый символ заменяется на другой символ, третий по счету в алфавите после данного, с цикличность. То есть символ A заменяется на D, символ B - на E, символ C - на F, . символ Z на C. Аналогично строчные буквы заменяются на строчные буквы. Все остальные символы не меняются.

Дана строка, зашифруйте ее при помощи шифра Цезаря. Решение оформите в виде функции void CaesarCipher (string & S) .

Указание: сделайте функцию char CaesarCipher (char c) , шифрующую один данный символ.

In a hole in the ground there lived a hobbit.
Lq d kroh lq wkh jurxqg wkhuh olyhg d kreelw.

4D: Значение выражения - 2

Дано выражение одно из следующих видов: “A+B”, “A-B” или “A*B”, где A и B - целые числа от 0 до 10 9 . Определите значение этого выражения.

Решение оформите в виде функции Eval(const string & S) .

100-101

4E: Значение выражения - 3

Дана строка, содержащая одно или более целых чисел от 0 до 10 9 , разделенных знаками “+” или “-”. Вычислите значение этого выражения.

Решение оформите в виде функции Eval(const string & S) .

21+7-10

4F: Поиск подстроки

Даны две строки, возможно, содержащие пробелы. Выведите слово YES , если первая строка является подстрокой второй строки или слово NO в противном случае.

Решение оформите в виде функции bool IsSubstring(const string & Pattern, const string & Source) .

hole in the ground
In a hole in the ground there lived a hobbit.
hole on the ground
In a hole in the ground there lived a hobbit.

5A: Look-and-say sequence

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

1 11 21 1211 111221 312211 13112221 1113213211 .

Дано натуральное число \(N\). Выведите \(N\)-й член этой последовательности.

1211

5B: Палиндром - 2

Дана строка, возможно, содержащая пробелы. Определите, является ли эта строка палиндромом, при условии, что заглавные и строчные буквы не различаются, а все символы, не являющиеся буквами, должны быть пропущены. Выведите слово YES , если слово является палиндромом и словов NO , если не является.

Решение оформите в виде функции bool IsPalindrome (const string & S) . При решении этой задачи нельзя пользоваться вспомогательными массивами или строками.

Was it a rat I saw?
abca

5C: Удалите лишние пробелы

Строка состоит из одного или нескольких слов, разделенных одним или несколькими пробелами. Удалите из строки лишние пробелы: два и более подряд идущих пробелов замените на один и удалите все пробелы в начале и в конце строки.

Сложность алгоритма должна быть пропорциональная длине исходной строки.

После вывода результата на экран выводите обязательно символ конца строки!

В примере ниже для наглядности пробелы изображаются при помощи символа “·”.

·one··two···three··
one·two·three

5D: Значение выражения - 4

Строка состоит из целых чисел, принимающих значения от 0 до 10 9 , разделенных знаками операций “+”, “-” и “*”. Вычислите значение этого выражения выполняя действия по правилам арифметики.

Тесты к этой задаче закрытые.

Ввод и вывод символьных строк в Си

Итак, строки в языке Си. Для них не предусмотрено отдельного типа данных, как это сделано во многих других языках программирования. В языке Си строка – это массив символов. Чтобы обозначить конец строки, используется символ '\0' , о котором мы говорили в прошлой части этого урока. На экране он никак не отображается, поэтому посмотреть на него не получится.

Создание и инициализация строки

Так как строка – это массив символов, то объявление и инициализация строки аналогичны подобным операциям с одномерными массивами.

Следующий код иллюстрирует различные способы инициализации строк.

char str[10]; char str1[10] = ; char str2[10] = "Hello!"; char str3[] = "Hello!";

Объявление и инициализация строк

Рис.1 Объявление и инициализация строк

В первой строке мы просто объявляем массив из десяти символов. Это даже не совсем строка, т.к. в ней отсутствует нуль-символ \0 , пока это просто набор символов.

Вторая строка. Простейший способ инициализации в лоб. Объявляем каждый символ по отдельности. Тут главное не забыть добавить нуль-символ \0 .

Третья строка – аналог второй строки. Обратите внимание на картинку. Т.к. символов в строке справа меньше, чем элементов в массиве, остальные элементы заполнятся \0 .

Четвёртая строка. Как видите, тут не задан размер. Программа его вычислит автоматически и создаст массив символов нужный длины. При этом последним будет вставлен нуль-символ \0 .

Как вывести строку

Дополним код выше до полноценной программы, которая будет выводить созданные строки на экран.

#include int main(void) < char str[10]; char str1[10] = ; char str2[10] = "Hello!"; char str3[] = "Hello!"; for(int i = 0; i

Различные способы вывода строки на экран

Рис.2 Различные способы вывода строки на экран

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

  • использовать функцию printf со спецификатором %s
  • использовать функцию puts
  • использовать функцию fputs , указав в качестве второго параметра стандартный поток для вывода stdout .

Единственный нюанс у функций puts и fputs . Обратите внимание, что функция puts переносит вывод на следующую строку, а функция fputs не переносит.

Как видите, с выводом всё достаточно просто.

Ввод строк

С вводом строк всё немного сложнее, чем с выводом. Простейшим способом будет являться следующее:

#include int main(void)

Функция gets приостанавливает работу программы, читает строку символов, введенных с клавиатуры, и помещает в символьный массив, имя которого передаётся функции в качестве параметра.
Завершением работы функции gets будет являться символ, соответствующий клавише ввод и записываемый в строку как нулевой символ.
Заметили опасность? Если нет, то о ней вас любезно предупредит компилятор. Дело в том, что функция gets завершает работу только тогда, когда пользователь нажимает клавишу ввод. Это чревато тем, что мы можем выйти за рамки массива, в нашем случае — если введено более 20 символов.
К слову, ранее ошибки переполнения буфера считались самым распространенным типом уязвимости. Они встречаются и сейчас, но использовать их для взлома программ стало гораздо сложнее.

Итак, что мы имеем. У нас есть задача: записать строку в массив ограниченного размера. То есть, мы должны как-то контролировать количество символов, вводимых пользователем. И тут нам на помощь приходит функция fgets :

#include int main(void)

Функция fgets принимает на вход три аргумента: переменную для записи строки, размер записываемой строки и имя потока, откуда взять данные для записи в строку, в данном случае — stdin . Как вы уже знаете из 3 урока, stdin – это стандартный поток ввода данных, обычно связанный с клавиатурой. Совсем необязательно данные должны поступать именно из потока stdin , в дальнейшем эту функцию мы также будем использовать для чтения данных из файлов.

Если в ходе выполнения этой программы мы введем строку длиннее, чем 10 символов, в массив все равно будут записаны только 9 символов с начала и символ переноса строки, fgets «обрежет» строку под необходимую длину.

Обратите внимание, функция fgets считывает не 10 символов, а 9 ! Как мы помним, в строках последний символ зарезервирован для нуль-символа.

Давайте это проверим. Запустим программу из последнего листинга. И введём строку 1234567890 . На экран выведется строка 123456789 .

Пример работы функции fgets

Рис.3 Пример работы функции fgets

Возникает вопрос. А куда делся десятый символ? А я отвечу. Он никуда не делся, он остался в потоке ввода. Выполните следующую программу.

#include int main(void)

Вот результат её работы.

Непустой буфер stdin

Рис.4 Непустой буфер stdin

Поясню произошедшее. Мы вызвали функцию fgets . Она открыла поток ввода и дождалась пока мы введём данные. Мы ввели с клавиатуры 1234567890\n ( \n я обозначаю нажатие клавиша Enter ). Это отправилось в поток ввода stdin . Функция fgets , как и полагается, взяла из потока ввода первые 9 символов 123456789 , добавила к ним нуль-символ \0 и записала это в строку str . В потоке ввода осталось ещё 0\n .

Далее мы объявляем переменную h . Выводим её значение на экран. После чего вызываем функцию scanf . Тут-то ожидается, что мы можем что-то ввести, но т.к. в потоке ввода висит 0\n , то функция scanf воспринимает это как наш ввод, и записывается 0 в переменную h . Далее мы выводим её на экран.

Это, конечно, не совсем такое поведение, которое мы ожидаем. Чтобы справиться с этой проблемой, необходимо очистить буфер ввода после того, как мы считали из него строку, введённую пользователем. Для этого используется специальная функция fflush . У неё всего один параметр – поток, который нужно очистить.

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

#include int main(void) < char str[10]; fgets(str, 10, stdin); fflush(stdin); // очищаем поток ввода puts(str); int h = 99; printf("do %d\n", h); scanf("%d",&h); printf("posle %d\n", h); return 0; >

Теперь программа будет работать так, как надо.

Сброс буфера stdin функцией fflush

Рис.4 Сброс буфера stdin функцией fflush

Подводя итог, можно отметить два факта. Первый. На данный момент использование функции gets является небезопасным, поэтому рекомендуется везде использовать функцию fgets .

Второй. Не забывайте очищать буфер ввода, если используете функцию fgets .

На этом разговор о вводе строк закончен. Идём дальше.

Сохрани в закладки или поддержи проект.

Практика

Решите предложенные задачи:

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

Исследовательские задачи для хакеров

  1. Проверьте как ведет себя ваш компилятор в случае переполнения буфера.

Дополнительные материалы

  1. пока нет

Как вывести символ в си

Чтение символов с клавиатуры может использоваться даже в самых простых программах. Оно может быть связано с выбором варианта в меню, ответа типа ДА/НЕТ или даже с вводом отдельной буквы какого-нибудь имени. Самым распространенным способом чтения символа, введенного с клавиатуры, является макрокоманда getchar, формат которой имеет вид:

#include int getchar(void);

При успешном завершении макрокоманда getchar возвращает считанный символ в коде ASCII. В случае ошибки или обнаружения конца файла (обычно при переназначенном вводе) getchar возвращает EOF. В следующей программе GETCHAR.C макрокоманда getchar используется для получения вводимого с клавиатуры ответа Y, означающего "да", или N, означающего "нет":

#include #include void main(void) < int letter; рrintf ("Для продолжения введите Y или N и нажмите" "Enter\n "); do < letter = toupper(getchar( )); >while ((letter != 'Y') && (letter != 'N')); printf("Введено %c\n", ((letter == 'Y') ? 'Y': 'N')); >

Как видно, в программе организуется циклический вызов geichar оператором do while до тех пор, пока пользователь не введет Y или N.

Примечание. Для обеспечения поддержки переназначенного ввода в определении макрокоманды geichar в действительности используется ввод с slain - стандартный ввод (по умолчанию соответствует вводу с клавиатуры).

287. Вывод символа на экран

В С286 рассматривалось использование макрокоманды getchar для чтения символа, введенного с клавиатуры. Подобным образом, используя в Си макрокоманду putchar, можно выводить символ на экран (stdout - стандартный вывод). Формат макрокоманды putchar.

#include int putchar(int letter);

При успешном завершении макрокоманда putchar возвращает выведенный символ. В случае ошибки putchar возвращает EOF. В следующей программе PUTCHAR.С макрокоманда putchar используется для вывода букв алфавита:

#include void main(void)

Примечание. Поскольку макрокоманда putchar выводит символ в stdout (файловый поток стандартного вывода), в команде запуска программы PUTCHAR.С на выполнение можно использовать оператор DOS для переназначения вывода, если нужно вывести результат работы программы в файл или на принтер.

288. Буферизованный ввод

При вводе с клавиатуры чтение вводимых символов в программе обеспечивается как операциями прямого, или непосредственного ввода, так и посредством буферизации. При использовании буферизованного ввода набранные символы не передаются в программу до тех пор, пока пользователь не нажмет клавишу Enter. Таким образом, пользователь может изменять введенные символы, используя при необходимости клавиши Backspace или Rubout. После нажатия Enter все введенные символы могут обрабатываться программой. Макрокоманда getchar использует буферизованный ввод. При использовании getchar для чтения ответа пользователя (например, Y или N) макрокоманда не считывает введенный символ, пока пользователь не закончит ввод нажатием Enter. Если пользователь ввел несколько символов, то все они накапливаются в буфере, и каждый из них доступен для getchar. В следующей программе BUFFERIO.С демонстрируется работа с буферизованным вводом. Запустите программу и затем введите строку текста. Введенные символы не обрабатываются программой, пока не будет нажата клавиша Enter. После нажатия Enter программа считает и выведет на экран символы, включая символ перевода строки (возникающий именно в результате нажатия клавиши Enter):

#include void main(void) < int letter; do < letter = getchar(); putchar(letter); >while (letter != '\n'); >

Во время выполнения этой программы предлагается поэкспериментировать с вводом символов, используя Backspace, Rubout и т. д. Можно убедиться, что символы, переданные программе, совпадают с результирующей строкой ввода.

289. Ввод символов с клавиатуры в строковую переменную

В разделе "Строки" этой книги дается несколько различных способов обработки строковых переменных. При вводе-последовательности символов с клавиатуры самой необходимой является операция присваивания введенных символов строковой переменной. В следующей программе FILLSTR.C для присваивания символов элементам строковой переменной string (массив символов) используется макрокоманда getchar. Для этого в программе просто организуется цикл, в котором элементам строки присваиваются символы до тех пор, пока не встретится символ "конец строки". По окончании цикла текущему элементу массива присваивается NULL-СИМВОЛ (маркер конца строки):

#include void main(void)

290. Комбинирование getchar и putchar

Известно, что getchar дает возможность прочитать символ с клавиатуры (стандартный ввод stdin), в то время как putchar выводит символ на экран (стандартный вывод stdout). В программах часто бывает нужно вводить и одновременно выводить символы. Здесь показан цикл while, в котором вводятся и выводятся символы, включая символ конца строки:

do < letter = getchar( ); putchar(letter); >while (letter != '\n');

Поскольку getchar и putchar работают с целыми значениями, операторы в предыдущем примере можно комбинировать следующим образом:

do putchar (letter = getchar( )); while (letter != '\n');

Здесь символ, полученный от getchar, присваивается переменной letter, в результате чего putchar выведет значение переменной letter.

291. getchar и putchar - макрокоманды

При разработке программы с использованием putchar и getchar необходимо помнить, что это макрокоманды, а не функции. А если так, то следует иметь в виду, что некоторые компиляторы не позволяют опускать пробел между именем макрокоманды и открывающейся скобкой:

letter = getchar(); putchar(letter);

Если вы просмотрите заголовочный файл stdio.h, то вы найдете описания макрокоманд getchar и putchar. В разделе "Переназначение ввода-вывода и обработка командной строки" эти два макроопределения описаны более подробно.

292. Чтение символа с использованием прямого ввода-вывода

В С288 говорилось о том, что при вводе с клавиатуры считывание вводимых символов может быть прямым (непосредственным) или буферизованным. При использовании прямого чтения символы, вводимые с клавиатуры, сразу же обрабатываются программой. Другими словами, не существует буфера для хранения символов. Если пользователь нажмет клавишу Backspace для стирания предыдущего символа, то программа должна обработать операцию редактирования сама (удалить предыдущий символ с экрана и из буфера). Функция getche дает возможность считывать с клавиатуры, используя прямой ввод. Формат функции getche следующий:

#include int getche(void);

В следующей программе GETCHE.С используется функция getche для ввода ответа Y (Да) или N (Нет) с клавиатуры:

#include #include #include void main(void) < int letter; printf("Продолжить? (Y/N): "); do < letter = getche ( ); letter = toupper (letter); >while ((letter != 'Y') && (letter != 'N') ); if (letter == 'Y' ) printf("\nВы ответили ДА (Y) \n "); else printf("\nВы ответили НЕТ (N) \n "); >

В отличие от программы GETCHAR.C, требующей от пользователя нажать Enter для ввода ответа, программе GETCHE.C ввод символа Y или N обрабатывается немедленно.

293. Ввод с клавиатуры без отображения на экран

В С292 рассматривалось использование функции getche для ввода символов с клавиатуры и их немедленной обработки (с использованием прямого ввода-вывода). При использовании getche вводимые пользователем символы автоматически отображаются на экран. В программе может возникнуть необходимость считывания символов с клавиатуры без отображения этих символов на экран. Например, если в программе дается подсказка пользователю на ввод пароля, то символы, вводимые пользователем, вообще говоря, не должны появляться на экране. Функция getch дает возможность ввести символы с клавиатуры без отображения их на экран (эффект "эхо"). Формат функции getch следующий:

#include int getch(void);

В следующей программе GETCH.C для ввода символов с клавиатуры используется функция getch. Считываемые (с помощью getch) буквы преобразуются из строчных в прописные и выводятся на экран. Программа GETCH.C показывает, как просто делается такая обработка:

#include #include #include void main(void) < int letter; printf("Введите строку символов и нажмите Enter\n "); do < letter = getch ( ); letter = toupper(letter); putch(letter); >while (letter != '\r'); >

294. Правильное использование управляющих символов '\r' и '\n'

Как известно, в языке Си употребляется специальный символ '\r' для задания действия "возврат каретки". Вместе с тем употребляется также и символ '\n', обозначающий "возврат каретки и перевод строки" и задающий переход на новую строку. При использовании в программе буферизованного ввода (например, с помощью макрокоманды getchar) нажатие клавиши Enter преобразуется в последовательность действий ВОЗВРАТ КАРЕТКИ и ПЕРЕВОД СТРОКИ. Если же используется прямой ввод-вывод с применением функций getch и getche, то ввод Enter воспринимается просто как возврат каретки ('\r').Для проверки правильного использования специального символа в программе предлагается следующий тест:

do < letter = getcharO; putchar(letter); >while (letter != '\n'); do < letter = getch(); putchar(letter); >while (letter != '\r');

295. Реализация прямого вывода

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

#include int putch(int letter);

При успешном завершении putch возвращает выведенный на экран символ, в случае ошибки - EOF. Для выполнения быстрого вывода putch либо связывается с видеосервисом BIOS, либо обращается к видеопамяти компьютера непосредственно. С другой стороны, такие функции как putchar реализуются с помощью функций файловой системы, которые, в свою очередь, уже обращаются к функциям BIOS. Функция putch делает преобразования символа "перевод строки" в последовательность "возврат каретки" и "перевод строки". В следующей программе PUTCH.C для 1001-кратного вывода букв английского алфавита используются функции putch и putchar. После этого программа показывает время, затраченное на выполнение каждой из этих двух функций.

#include #include #include void main(void)

296. Возврат символа в буфер клавиатуры

Как известно, чтение символа, введенного с клавиатуры, может быть выполнено функцией getch. Иногда возникает необходимость чтения и запоминания подряд всех нажимаемых клавиш до тех пор, пока не встретится заданный символ, а затем - обработки всей совокупности. После завершения обработки считываются остальные символы. При таком сценарии программы может понадобиться "прочитать назад" какой-нибудь символ, т.е. перейти к предыдущему. Для этого используется функция ungetch:

#include int ungetch(int character);

Кроме того, может потребоваться поместить заданный символ в буфер клавиатуры так, чтобы следующим символом ввода с клавиатуры был именно этот символ. Для этой же цели используется функция ungetch. В следующей программе UNGETCH.C считываются символы ввода с клавиатуры до тех пор, пока не встретится прописная буква. После этого программа выводит буквы и затем вводит и выводит символы в другую строку.

#include #include #include void main(void) < int letter; int done = 0; int uppercase_found = 0; do < letter = getch(); if (islower(letter)) putchar(letter); else < if (isupper(letter)) < ungetch(letter); uppercase found = 1; putchar('\n'); >done = 1; > > while (! done); if (uppercase_found) do < letter = getch(); putchar(letter); >while (letter != '\r'); >

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

ungetc(letter, stdin );

297. Быстрый форматированный вывод с использованием функции cprintf

Как известно, функция printf дает возможность организовать в программе форматированный вывод. В определении функции printf устройство вывода задается ссылкой на файловый поток stdout - стандартны и вывод. Поэтому вывод результата работы printf можно переназначать с экрана дисплея в файл или на другое устройство. Такое использование stdout в функции printf предопределяет использование файловой системы языка Си, внутри которой используются функции DOS, которые, в свою очередь, вызывают служебные функции BIOS. Для более быстрого форматированного вывода можно использовать функцию cprintf, которая работает непосредственно с BIOS или с видеопамятью компьютера:

#include int cprintf(const char *format[,arguments. ]);

Следующая программа CPRINTF. С выводит строку "1001 совет по С/С++" 1001 раз, используя сначала printf и затем cprintf. После этого программа показывает время, затраченное на выполнение каждой из этих функций:

#include #include #include void main(void) < int count; time_t start_time, stop_time; time(&start_time); for (count = 0; count < 1001; count++) printf("1001 совет по C/C++\r\n "); time(&stop_time); printf("\n\nHa вывод функцией printf требуется %d секунд\n ", stop_time-start_time); printf("Нажмите любую клавишу. \n "); getch(); time(&start_time); for (count = 0; count < 1001; count++) cprintf("1001 совет по C/C++\r\n "); time(&stop time); printf("\n\nHa вывод функцией cprintf требуется %d секунд\n ", stop time-start time); >

Примечание. Функция cprintf не выполняет преобразование символа "переход на новую строку " и последовательность "ВОЗВРАТ КАРЕТКИ/ПЕРЕВОД СТРОКИ".

298. Быстрый форматированный ввод с клавиатуры

Для выполнения быстрого вывода данных на экран дисплея без привлечения файловой системы используется функция cprintf (C297). Похожим образом функция cscanf дает возможность выполнить в программе быстрый форматированный ввод с клавиатуры:

#include int cscanf(char *format[,arguments]);

В следующей nporpaммe CSCANF.C выдается подсказка на ввод трех целых чисел, после чего выполняется считывание значений с использованием cscanf:

#include void main(void)

299. Вывод на экран символьной строки

Форматированный вывод на экран дисплея выполняется в программе с помощью функции printf. Используя printf, можно вывести строку, целое число, число с плавающей точкой или произвольную комбинацию перечисленных типов значений. Если в программе необходимо вывести только символьную строку, то эффективнее использовать функцию puts вместо printf:

#include int puts(const char *string);

Функция puts выполняет вывод строк, оканчивающихся двоичным нулем, на экран дисплея (в действительности, на устройство стандартного вывода). При успешном выполнении puts возвращает неотрицательное число. В случае ошибки возвращается EOF. Функция puts автоматически записывает в конце выводимых данных символ перевода строки. В следующей программе PUTS.C функции printf и puts используются для 1001-кратного вывода строки "1001 совет по C/C++". После этого программа показывает время, затраченное на выполнение каждой из этих функций:

#include #include #include void main(void) < int count; time_t start_time, stop_time; time(&start_time); for (count =0; count < 1001; count++) printf("1001 совет по C/C++\n"); time(&stop_time); printf("\n\nHa вывод функцией printf требуется %d секунд\n", stop_time-start_time); printf("Нажмите любую клавишу. \n"); getch( ); time(&start_time); for (count = 0; count < 1001; count++) puts("1001 совет по С/С++\n"); time(&stop_time); printf("\n\nHa вывод функцией puts требуется %d секунд\n", stop time-start time); >

Примечание. Поскольку функция puts сама автоматически добавляет символ перевода строки, символьная строка, задаваемая в этой функции в качестве параметра, не содержит этого символа.

300. Быстрый вывод строки с использованием прямого ввода-вывода

Мы уже видели (С299), как с помощью функции puts выполнить вывод символьной строки. Однако, функция puts использует файловую систему и осуществляет вывод на stdout, стандартное устройство вывода (благодаря чему допускает возможность переназначения). Используя функцию cputs, вывод строки можно выполнить быстрее:

#include int cputs(const char string);

Как uputs, функция cputs выводит строки, оканчивающиеся двоичным нулем. В отличие от puts, функция cputs невыполняет автоматическое добавление символа перевода строки. В следующей программе CPUTS.C функции puts и cputs используются для 1001-кратного вывода строки "1001 совет по C/C++". После этого программа показывает время, затраченное на выполнение каждой из этих функций:

#include #include #include void main(void) < int count; time_t start_time, stop_time; time(&start_time); for (count =0; count < 1001; count++) puts("1001 совет по C/C++"); time(&stop_time); рrintf ("\n\nВывод с использованием puts требует %d секунд\n", stop_time-start_time); printf("Нажмите любую клавишу. \n"); getch( ); time(&start_time); for (count =0; count < 1001; count++) cputs ("1001 совет по C/C++\r\n"); time(&stop_time); printf("\n\nВывод с использованием cputs требует %d секунд\n", stop_time-start_time); >

301. Считывание символьной строки с клавиатуры

Мы уже знаем (С299), как вывести символьную строку на экран дисплея с помощью функции puts. Похожим образом функция gets дает возможность выполнить в программе считывание символьной строки, вводимой с клавиатуры:

#include char *gets(char *string);

При успешном выполнении функция gets возвращает указатель на символьную строку. В случае ошибки или обнаружения конца файла gets возвращает значение NULL. Функция gets считывает все символы строки сразу, включая символ перевода строки. При этом gets заменяет символ перевода строки на двоичный нуль. В следующей программе GETS.C функция gets используется для чтения строки символов, введенной с клавиатуры:

#include void main(void)

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

302. Быстрый ввод строки с клавиатуры

Функция gets (C301) дает возможность выполнить в программе считывание символьной строки, введенной с клавиатуры. Функция gets на самом-то деле осуществляет ввод со стандартного устройства stdin и использует для этого файловую систему, что обеспечивает возможность переназначения ввода. Если переназначение ввода при выполнении программы не планируется использовать, то для ввода строки символов с клавиатуры эффективнее использовать функцию cgets:

#include char *cgets(char *string);

При успешном завершении cgets возвращает указатель на string[2]. В случае ошибки возвращается NULL-значение. Поведение функции cgets отличается от поведения функции gets. Поскольку при вызове cgets создается как параметр символьная строка, то перед вызовом необходимо присвоить элементу siring [О] максимально возможное количество считываемых символов. После выполнения string[1] будет содержать количество фактически считанных символов. Реальная строка символов, оканчивающаяся двоичным нулем, фактически начинается с элемента string[2]. В следующей программе CGETS.C демонстрируется использование функции cgets:

#include #include void main(void) < char buffer[256]; buffer[0] = 253; // Максимальное количество считываемых символов printf("Введите строку и нажмите Enter\n"); cgets(buffer); printf("\n\nСчитано %d символов\n", buffer[l]); printf("Введена строка: %s\n", &buffer[2]); >

Запустив программу, можно попробовать уменьшить,скажем, до десяти, количество введенных символов. Если пользователь попытается ввести больше десяти символов, толишние символы будут проигнорированы.

303. Вывод на экран в цветном режиме

Вывод на экран в цветном режиме можно осуществить, используя управляющие последовательности драйвера ANSI.SYS. Кроме того, многие Си-компиляторы предоставляют специальные функции вывода, которые могут выводить текст в различных цветах. В Borland C++ и Microsoft С ++ такой функцией является функция outtext (называемая _outtext в Microsoft C++). В Borland C++ функция outtext может использоваться только в графическом режиме, тогда как функция _outtext в Microsoft C++ работает как в графическом, так и в текстовом режиме. При необходимости вывода в цветном режиме за информацией об использовании этих функций следует обращаться к документации по компилятору. Компилятор обеспечивает функции по установке курсора в определенную позицию выводимого текста, выбору цвета и графического режима. Поскольку эти функции обычно привязываются к конкретному компилятору, они не описаны в этой книге.

304. Очистка экрана дисплея

Как правило. Си-компиляторы не предоставляют функцию, очищающую экран дисплея. Однако, в компиляторах Borland и Microsoft имеется функция clrscr для очистки содержимого окна в текстовом режиме:

#include void clrscr(void);

В следующей программе CLRSCR.C функция clrscr используется для очистки экрана дисплея:

#include void main(void)

305. Очистка текущей строки до ее конца

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

#include void clreol(void);

Функция очищает содержимое строки без перемещения курсора.

306. Удаление текущей строки с экрана

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

#include void delline(void);

В следующей программе DELLINE.C экран заполняется 24 строками текста. После нажатия Enter программа, используя delline, уничтожит строки 12, 13 и 14.

#include void main(void)

307. Позиционирование курсора на экране

Для позиционирования курсора в операциях вывода на экран может быть использован 1 драйвер ANSI.SYS. Многие Си-компиляторы, работающие в среде DOS, предоставляют функцию gotoxy, которая дает возможность перемещать курсор по заданным значениям столбца и строки:

#include void gotoxy(int column, int row);

Параметр column указывает номер столбца (х-координата) от 1 до 80. Параметр row указывает номер строки (у-координата) от 1 до 25. Если эти ограничения нарушены, вызов функции gotoxy игнорируется. В следующей программе GOTOXY.C функция gotoxy используется для последующего вывода в указанной позиции:

#include void main(void)

308. Определение позиции строки и столбца

Для перемещения курсора в позицию по указанным значениям строки и столбца используется функция gotoxy. Часто в программе, работающей с экранными образами, возникает необходимость в определении текущей позиции курсора. Функции wherex и wherey возвращают соответственно номер столбца и номер строки позиции курсора:

#include int wherex(void); int wherey(void);

В следующей программе WHEREXY.C сначала очищается экран и выводятся три строки. Затем функции wherex и wherey используются для определения текущей позиции курсора:

#include void main(void)

309. Вставка пустой строки

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

#include void insline(void);

В результате вызова функции insline текст, следующий за курсором, опускается на одну строку. Нижняя строка исчезает с экрана. В следующей программе INSLINE.C сначала выводится информация, заполняющая весь экран. После этого программа использует функцию insline для вставки текста в строке 12:

#include void main(void)

310. Копирование текста с экрана в буфер

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

#include int gettext(int left, int top, int right, int bottom, void *buffer);

В параметрах left и top указываются, соответственно, номер столбца и номер строки, верхнего левого угла прямоугольной области экрана, текст которой должен быть скопирован в буфер. В параметрах right и bottom указываются номер столбца и номер строки нижнего правого угла этой области. Параметр buffer -область памяти, в которую копируются текст и его атрибуты. Для хранения атрибутов одного символа текста используется один байт. Например, если копируется 10 символов, то для буфера хранения выделяется 20 байтов, 10 символов ASCII и 10 атрибутных байтов. В следующей программе SAVESCR.C текущее содержимое экрана в текстовом режиме сохраняется в файле SAVESCR.DAT.

#include #include #include #include void main(void) < char buffer[8000]; int handle; if ((handle = creat("SAVESCR.DAT", S_IWRITE)) == -1) cprintf("Ошибка при открытии файла SAVESCRN.DAT\r\n"); else < gettext(1, 1, 80, 25, buffer); write(handle, buffer, sizeof(buffer)); close(handle); >>

Примечание: В большинстве случаев текущий атрибут текста равен 7. Если попробовать вывести содержимое файла SAVESCR.DAТ c помощью команды TYPE, то система будет издавать звук на каждом атрибутном символе.

311. Вывод текстового буфера в указанное место экрана

Как уже упоминалось, многие Си-компиляторы, работающие в среде DOS, предоставляют функции, которые могут использоваться в программах для управления выводом на экран. Например, в С310 для копирования заданной области экрана в буфер (вместе с атрибутными символами) была использована функция gettexl. Копию содержимого экрана, сохраненную в буфере, можно вывести обратно на экран, используя функцию puttext:

#include int puttext(int left, int top, int right, int bottom, void *buffer);

В параметрах left, top, right и bottom указывается прямоугольная область экрана, в которую выводится содержимое буфера. Параметр buffer содержит символы и их атрибуты, сохраненные ранее функцией getlext. В следующей программе PUTTEXT.C организуется передвижение текста "Ямса. 1001 Совет по С/ C++" по экрану до тех пор, пока не будет нажата клавиша:

#include #include #include #include #include #include void main(void) < char buffer[128]; int row, column; clrscr( ); cprintf("1001 совет по C/C++\r\n"); gettext(1, 1, 23, 1, buffer); while (! kbhit( )) < clrscr( ); row =1 + random(24); column = 1 + random(58); puttext(column, row, column+22, row, buffer); delay(2000); >>

312. Определение параметров текстового режима экрана

Многие Си-компиляторы для управления операциями экранного ввода-вывода предоставляют множество различных функций, работающих с текстом. Для определения текущих параметров экрана можно воспользоваться функцией gettextinfo:

#include void gettextinfo(struct text_info *data);

Параметр data задает указатель на структуру типа text_info, имеющую вид:

struct text_info < unsigned char winleft; // Левая граница окна unsigned char wintop; // Верхняя граница окна unsigned char winright; // Правая граница окна unsigned char winbottom; // Нижняя граница окна unsigned char attribute; // Текущий атрибут текста unsigned char normattr; // Нормальный атрибут текста unsigned char currmode; // Текущий текстовый режим unsigned char screenheight; // Количество строк unsigned char screenwidth; // Количество столбцов unsigned char curx; // Текущая позиция курсора, столбец unsigned char cury; // Текущая позиция курсора, строка >;

В программе TEXTINFO.C функция gettextinfo используется для вывода текущих параметров экрана:

#include void main(void)

313. Управление цветом на экране

Вывод в цвете в программе может быть организован с использованием управляющих последовательностей драйвера ANSI.SYS. Однако, многие Си-компиляторы в среде DOS предоставляют функцию textattr, в которой можно указать цвет текста и цвет фона:

#include void textattr(int attribute);

Параметр attribute содержит 8 битов, в которых указываются желаемые цвета текста и фона. В четырех младших значащих битах содержится цвет текста. Следующие три бита определяют цвет фона, а последний (самый старший) бит управляет мерцанием. Для выбора цвета необходимо первым семи битам присвоить требуемое значения. В табл. 313 указаны значения кодов цветов.

Таблица 313. Параметры кодов цветов

Константа Цвет Значение Использование
BLACK Черный 0 Текст и фон
BLUE Синий 1 Текст и фон
GREEN Зеленый 2 Текст и фон
CYAN Бирюзовый 3 Текст и фон
RED Красный 4 Текст и фон
MAGENTA Фиолетовый 5 Текст и фон
BROWN Коричневый 6 Текст и фон
LIGHTGRAY Ярко-серый 7 Текст и фон
DARKGRAY Темно-серый 8 Фон
LIGHTBLUE Ярко-синий 9 Фон
LIGHTGREEN Ярко-зеленый 10 Фон
LIGHTCYAN Ярко-бирюзовый 11 Фон
LIGHTRED Ярко-красный 12 Фон
LIGHTMAGENTA Ярко-фиолетовый 13 Фон
YELLOW Желтый 14 Фон
WHITE Белый 15 Фон
BLINK Мерцание 128 Фон

В следующей программе TEXTATTR.C демонстрируются допустимые цвета текста:

#include void main(void) < int color; for (color =1; color < 16; color++) < textattr (color); cprintf("Текущий цвет - %d\r\n", color); >textattr(128 + 15); cprintf("Мерцание включено\r\n"); >

314. Цвет фона

Функция textattr в программе выбирает цвет для текста и фона (С313). Для установки цвета фона функцией textattr программа должна присвоить соответствующие значения цвета битам с 4-го по 6-й. Для этого можно либо использовать битовую операцию СДВИГ ВЛЕВО (

Константа Цвет Значение
BLACK Черный 0
BLUE Синий 1
GREEN Зеленый 2
CYAN Бирюзовый 3
RED Красный 4
MAGENTA Фиолетовый 5
BROWN Коричневый 6
LIGHTGRAY Ярко-серый 7
DARKGRAY Темно-серый 8
LIGHTBLUE Ярко-синий 9
LIGHTGREEN Ярко-зеленый 10
LIGHTCYAN Ярко-бирюзовый 11
LIGHTRED Ярко-красный 12
LIGHTMAGENTA Ярко-фиолетовый 13
YELLOW Желтый 14
WHITE Белый 15
BLINK Мерцание 128

В программе TXTCOLOR.C приводится использование функции textcolor для установки цвета текста:

#include void main(void) < int color; for (color = 1; color < 16; color++) < textcolor(color); cprintf("Текущий цвет - %d\r\n", color); >textcolor(128 + 15); cprintf("Мерцание разрешено\r\n"); >

316. Установка цвета фона с помощью функции textbackground

Как уже известно, Си-компиляторы в среде DOS предоставляют функцию textattr, которая дает возможность выбрать необходимые цвета для текста и фона при выводе текста. Для упрощения процесса установки цвета для фона можно использовать функцию textbackground:

#include void textbackground (int backgroundcolor);

В параметре backgroundcolor указывается одно из значений кода цвета, перечисленных в табл. 316.

Таблица 316. Допустимые значения цветов фона

Константа Цвет Значение
BLACK Черный 0
BLUE Синий 1
GREEN Зеленый 2
CYAN Бирюзовый 3
RED Красный 4
MAGENTA Фиолетовый 5
BROWN Коричневый 6
LIGHTGRAY Ярко-серый 7

В программе BACKGRND.C используется функция lextbackground для установки цвета фона:

#include void main(void) < int color; for (color = 0; color < 8; color++) < textbackground(color); cprintf("Текущий цвет - %d\r\n", color); cprintf("Для продолжения нажмите любую клавишу \r\n"); getch( ); >>

317. Управление яркостью при выводе текстов

Как уже известно, многие Си-компиляторы в среде DOS предоставляют множество функции для управления экранным выводом. При использовании этих функций для вывода текста на экран может возникнуть необходимость вывод с разной яркостью. В этом случае для выбора яркости можно использовать одну из трех функций:

#include void highvideo(void); void lowvideo(void); void normvideo(void);

Эти функции управляют яркостью вывода текста на экран. В следующей программе NTENSITY.C демонстрируется использование этих функций.

#include void main(void)

318. Определение текущего текстового режима

Многие Си-компиляторы в среде DOS предоставляют функции для управления экранныи выводом. При их использовании в программе может возникнуть необходимость определять и, возможно, изменять параметры текущего текстового режима экрана. Например, программа, рассчитанна на вывод 80 колонок текста, может выводить неверные результаты в текстовом режиме на 40 колонок. Для изменения параметров текущего текстового режима используется функция textmode:

#include void textmode(int desired mode);

Параметр desired_mode указывает требуемый текстовый режим. В табл. 318 даны допустимые текстовые режимы.

Таблица 318. Допустимые текстовые режимы

Константа Значение Режим
LASTMODE -1 Предыдущий
BW40 0 Черно-белый 40 Х 25
С40 1 Цветной 40 X 25
BW80 2 Черно-белый 80 X 25
С80 Цветной 40 X 25
MONO 7 Монохромный 80 X 25
С4350 64 EGA 80 X 43 или VGA 80 X 50

Следующий оператор, например, устанавливает 80 столбцов и 43 строки текста в EGA или режим 80Х50 в VGA:

textmode(C4350);

Примечание: Если в программе использована функция textmode для изменения текущего текстового режима, то это изменение остается в силе и после выхода из программы.

319. Перемещение текста на экране

Как известно, многие Си-компиляторы в среде DOS предоставляют множество функций для управления экранным выводом. При этом может возникнуть необходимость копирования или перемещения текста с одной части экрана на другую. Для копирования текста на экране программа может использовать функцию movetext:

#include int movetext(int left, int top, int right, int bottom, int destination_left, int destination_top);

Параметры left, top, right и bottom задают прямоугольную область текста, подлежащего копиро-ванию.Параметры destination_left и destination_top задают позицию левого верхнего угла, куда надлежит копировать текст. В следующей программе MOVETEXT.C сначала на экран выводится пять строк текста, азатем ожидается нажатие клавиши. После этого программа выполняет копирование текста на новое место.

#include void main(void)

Для перемещения текста без сохранения его на старом месте (в отличие от копирования) необходимо удалить скопированный текст после завершения movetext.

320. Установка размеров текстового окна

Как известно, многие Си-компиляторы в среде DOS предоставляют множество функций для управления экранным выводом. Они по умолчанию работают со всем экраном. В зависимости от требований к программе, можно ограничить вывод некоторой прямоугольной областью. Для этого используется функция window.

#include void window(int left, int top, int right, int bottom);

В параметрах left, top, right и bottom задаются левый верхний и правый нижний углы области экрана, в которую направляется вывод. В следующей программе WINDOW.C вывод ограничен верхней левой четвертью экрана:

#include void main(void) < int i, j; window(1, 1, 40, 12); for (i = 0; i < 15; i++) < for (j = 0; j < 50; j++) cprintf("%d", j); cprintf("\r\n"); >>

Когда вывод в окне программы достигнет правой границы окна, происходит переход на новую строку. По окончании программы для операций вывода используется снова полный экран.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *