C как вывести символ
При запуске программы на Си автоматически открываются ряд потоков, основными из которых являются следующие:
- Стандартный поток ввода stdin
- Стандартный поток вывода stdout
- Стандартный поток вывода сообщений об ошибках stderr
Стандартный поток ввода stdin по умолчанию соответствует клавиатуре, а потоки stdout и stderr — экрану монитора.
Для управления вводом-выводом с помощью этих потоков используются ряд функций:
- getchar() : ввод с клавиатуры одного символа
- putchar() : вывод на консоль одного символа
- fgets() : ввод одной строки
- puts() / fputs() : вывод одной строки на консоль
- scanf() : ввод с консоли с форматированием данных
- sscanf() : ввод с из строки с форматированием данных
- printf() : вывод с форматированием данных
Функции printf и scanf уже рассматривались ранее, поэтому посмотрим, как применять остальные функции.
Ввод и вывод символов
Для ввода и вывода символа применяются функции getchar() и putchar() . Но следует сказать, что на самом деле они полноценными функциями не являются, а определены как макросы в заголовочном файле stdio.h :
#define getchar() getc(stdin) #define putchar(c) putc((c), stdout)
Вывод символа
Для вывода отдельного символа на консоль предназначена функция putchar() со следующим прототипом:
int putchar(int c);
Выводимый символ в виде числового кода передается в putchar в качестве параметра, он же возвращается функцией.
#include int main(void) < char c = 'A'; putchar(c); // Выводим символ A >
Ввод символа
Для ввода одного символа с клавиатуры применяется функция getchar() , которая имеет следующий прототип:
int getchar(void);
В качестве результата функция возвращает числовой код введенного символа.
При использовании функции getchar следует учитывать, что при печати текста посредством клавиатуры в буфер операционной системы заносятся коды печатаемых символов, а сами символы отображаются на экране. Поучение программой введенного символа из буфера производится с помощью нажатия клавиши Enter.
И если буфер операционной системы не пуст, то при вызове функции getc() она получает очередной символ из буфера. Если же буфер пуст, то происходит чтение байта из потока ввода с помощью системной функции, название которой зависит от операционной системы.
При этом при нажатии клавиши Enter, в буфер также помещается код этой клавиши. То есть если мы введем один символ и нажмем на Enter, в буфере окажутся два числовых кода — введенного символа и клавиши Enter. И это надо учитывать при работе с функцией getchar. В частости, рассмотрим простой, но показательный пример:
#include int main(void) < printf("1"); getchar(); // ожидание ввода символа printf("2"); getchar(); // ожидание ввода символа printf("3"); return 0; >
Сначала на экран выводится цифра 1, после чего функция getchar ожидает ввода символа. Если после ввода символа мы нажмем Enter, то в буфер будет помещены два числовых кода — введеного символа и клавиши Enter. Поэтому при втором вызове getchar эта функция считывает байт из буфера — то есть числовой код клавиши Enter.
Например, введем при первом вызове функции getchar символ «a», а затем Enter:
1a 23
Но если при каждом вызове getchar мы будем только нажимать клавишу Enter, тогда в буфер будет заноситься только код этой клавиши, и соответственно программа будет работать, как и ожидалось:
1 2 3
Применим функции getchar и putchar для ввода и вывода символов с клавиатуры:
#include int main(void) < int c; while((c=getchar())!=EOF) < putchar(c); >return 0; >
Функция getchar() считывает числовой код символа, который потом выводится в функции putchar() . Для вывода из программы необходимо ввести комбинацию клавиш Ctrl+C.
Ввод и вывод строк
Вывод строк и puts
Для вывода одной строки на консоль предназначена функция puts() со следующим прототипом:
int putchar(char *s);
В качестве параметра передается указатель на строку, а возвращаемым результатом функции является последний выведенный символ.
При этом функция puts() будет выводить символы переданной строки, пока не дойдет до нулевого символа ‘\0’. Если же выводимый массив символов не содержит этого символа, то результат программы неопределен. Например:
#include int main(void) < puts("Hello World"); // выводим строковый литерал char* name = "Hello Metanit.com"; puts(name); // выводим значение переменной return 0; >
Hello World Hello Metanit.com
Вывод строк и fputs
Функция fputs() также записывает в поток вывода строку, то есть набор символов, который завершается символом ‘\0’. При записи строки нулевой символ ‘\0’ не записывается. Она имеет следующий прототип:
int fputs(const char *s, FILE *stream);
Первый параметр функции — записываемая строка, а второй — указатель на поток вывода. В качестве результата функция возвращает неотрицательное целое число. При ошибках в процессе записи возвращается значение EOF .
Применим функцию для записи в стандартный поток вывода, то есть на консоль. В этом случае в качестве второго параметра надо передать значение stdout :
#include int main(void)
Ввод строк и fgets
Для ввода строки с клавиатуры применяется функция fgets() , которая имеет следующий прототип:
char *fgets(char *str, int count, FILE *stream);
- char *str : строка, в которую производится считывание.
- int count : сколько символов необходимо считывать.
- FILE *stream : файловый поток, из которого производится считывание. В качестве потока ввода может выступать и консольный ввод.
Функция fgets() прекращает считывание, когда пользователь нажимает клавишу ENTER, то есть когда в поток добавляется символ перевода строки.
Рассмотрим считывание строки с консоли. Для этого в качестве третьего параметра в функцию передается значение stdin :
#include #define MAX 15 int main(void)
Здесь функция fgets считывает не более 15 символов в строку name, а В реальности функция предложит ввести 14 символов, так как последний символ зарезервирован для нулевого символа ‘\0’. Если будет введено больше символов, то fgets все равно считает не более 15 символов. Таким образом функция позволяет проверить количество считываемых символов и поэтому считается безопасной.
Пример работы программы:
Enter name: Tom Smith Your name: Tom Smith
Стоит отметить, что функция fgets() возвращает указатель char * — указатель на буфер, в который считаны данные. В реальности это тот же самый буфер, который передавался в качестве первого параметра, то есть в примере выше — это массив name. Однако этот результат может нам пригодится для проверки успешности выполнения функции — если считывание прошло неудачно, то функция возвращает NULL :
#include #define MAX 15 int main(void) < char name[MAX]; printf("Enter name: "); if(fgets(name, MAX, stdin) != NULL) // if(fgets(name, MAX, stdin)) - можно сократить < printf("Your name: %s\n", name); >else < printf("Critical Error. "); >return 0; >
Для эмуляции ошибки можно передать в функцию вторым параметром число 0.
fgets и scanf
При использовании функции fgets() после функции scanf() мы можем столкнуться с некорректным вводом:
#include #define N 32 int main(void) < int age; char name[N]; // считываем возраст в переменную age printf("Input age: "); scanf("%d", &age); // считываем строку в переменну. name printf("Input name: "); fgets(name, N, stdin); // проверяем ввод printf("Age: %d\n", age); printf("Name: %s\n", name); >
В данном случае сначала с помощью функции scanf() считываем число в переменную age. После этого считываем имя — строку с помощью функции fgets() в переменную name. Но посмотрим, какой будет результат работы программы:
Input age: 39 Input name: Age: 39Name:
В данном случае мы видим, что ввод имени с помощью fgets вроде как пропускается. По крайней мере мы не можем ввести имя, а программа сразу же выводит результат.
Все дело в том, что функция scanf() считывает именно то, что ей предписано — число в виде переменной типа int. Все остальные символы остаются в буфере, в который предварительно попадают введенные с клавиатуры символы. Так, после ввода возраста мы нажимаем на клавишу Enter, и в буфер попадает символ «\n», то есть перевод строки. И fgets считывает этот символ из буфера, после чего ввод имени завершается. Очевидно, это не то поведение, на которое мы рассчитывали.
Чтобы исправить ситуацию, мы можем использовать различные хаки. Рассмотрим пару из них. Все они сводятся к тому, чтобы вынуть из буфера этот символ перевода строки.
Первый способ — считывание символа с помощью вызова scanf(«%*c») :
#include #define N 32 int main(void) < int age; char name[N]; // считываем возраст в переменную age printf("Input age: "); scanf("%d", &age); scanf("%*c"); // вытаскиваем символ из буфера // считываем строку в переменну. name printf("Input name: "); fgets(name, N, stdin); // проверяем ввод printf("Age: %d\n", age); printf("Name: %s\n", name); >
Второй способ — мы можем считать символ с помощью getchar() :
#include #define N 32 int main(void) < int age; char name[N]; // считываем возраст в переменную age printf("Input age: "); scanf("%d", &age); getchar(); // вытаскиваем символ из буфера // считываем строку в переменну. name printf("Input name: "); fgets(name, N, stdin); // проверяем ввод printf("Age: %d\n", age); printf("Name: %s\n", name); >
Результат работы программы:
Input age: 39 Input name: Tom Age: 39 Name: Tom
Как вывести символы из строки?
Всем привет! Прошу помощи, дали такое задание: «Программа, которая читает строку длиной до 20 символов от пользователя (необходимо выяснить, не превышает ли строка заданную длину, если да, то нужно ввести заново), подсчитывает и перечисляет количество гласных, согласных, знаков препинания, чисел и других символов (через запятую). Пример: слово Auto, гласные: 3 — A, u, o и т. д.» .
Код на поиск и подсчет гласных, согласных и т.д. уже есть. Не знаю как теперь вывести все посчитанные символы из строки, и как поставить условие что, если строка больше 20 символов, то надо ввести ее заново? Помогите пожалуйста.
#include #include #define N 21 int main()< char str[N]; const char vovels[]="eyuioaEYUIOA"; const char consonants[]="qwrtpsdfghjklzxcvbnmQWRTPFGHJKLZXCVBNM"; char digits[]="0123456789"; const char punctuation[]=". ;!?\"()-"; const char symbols[]="@#$%^&*<>[]<>_+=\'¹%|\\/`~"; const char spaces[]=" "; int v, c, d, p, s, sp; v = c = d = p = s = sp = 0; printf("Enter a string no more than 20 symbols :\n\n"); gets(str); for (int i=0; str[i] != '\0'; i++) if (strchr(vovels,str[i])) v++; else if (strchr(consonants,str[i])) c++; else if (strchr(digits,str[i])) d++; else if (strchr(punctuation,str[i])) p++; else if (strchr(symbols,str[i])) s++; else if (strchr(spaces,str[i])) sp++; printf("\nVowels: %d\n", v); printf("\nConsonants: %d\n", c); printf("\nDigits: %d \n", d); printf("\nPunctuation: %d\n", p); printf("\nSymbols: %d\n", s); printf("\nSpaces: %d\n", sp); return 0; >
- Вопрос задан более трёх лет назад
- 455 просмотров
2 комментария
Простой 2 комментария
Saboteur @saboteur_kiev
Так а что вы пытались сделать, и что не получилось?
А то такое ощущение, что вы у кого-то стырили кусок кода, в котором даже не попытались разобраться, и ждете пока вам все остальное сделают.
Ну попробуйте же приложить хоть каплю усилий самостоятельно?

Saboteur, Ага, есть такое впечатление. Массивы названы правильно, хотя студенты обычно не задуряются такими вещами 🙂
Решения вопроса 0
Ответы на вопрос 2

Внимание! Изменился адрес почты!
man strlen (и даже неудобно такое писать — strlen() — это одна из первых строковых функций 🙂 )
man calloc
Для перечисления нужно завести отдельные массивы и копировать туда символ если условие сработало. А потом этот массив просто вывести.
Кроме того, статические массивы — зло, память надо брать динамически. Код я не привожу намеренно, потому что Вы учитесь и Ваше обучение и состоит в изучении того, какие есть строковые функции а не в копипастинге. Как основа эта программа годится. Но в ней нужно:
— заменить статическую память на динамическую
— после чтения строки проверить ее длину, если она > 20 — спросить заново, что нас естественно приводит к тому, что запрос будет делаться в бесконечном цикле
— в разборочном if не только крутить нужные счетчики, но и копировать символ в соответствущий массив.
— после окончания разбора вывести все отобранные массивы.
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Wundarshular @Wundarshular
Прежде всего настоятельно рекомендую сначала ознакомиться с основами языка, а также используемыми вами функциями ввода вывода. Язык С очень прост: если вы хотите выстрелить себе в ногу, вы стреляете.
Беглый просмотр вашего кода показывает, что вы не заботитесь о входных данных. Например, вот эта конструкция хоть и позволяет вам считать строку, но не даёт никаких гарантий, что она не превысит размер в 21 символ.
#define N 21 . char str[N]; printf("Enter a string no more than 20 symbols :\n\n"); gets(str);
А вот здесь вы наивно надеетесь, что у строки точно есть конец.
for (int i=0; str[i] != ‘\0’; i++)
Язык С очень прост: если вы хотите считать строку, вы её считаете. Но какой вы её получите — это ваша проблема.
Что до вашей задачи, то, полагаю, самым простым способом в вашем случае будет цикл в цикле: главным циклом вы проходитесь по полученной строке, побочными циклами ищите совпадения в ваших справочниках (массивы vovels и тд) и при нахождении оного либо выводите сразу, либо копируете символ куда-либо для вывода позже.
Вы значительно упростите код в этой части, если посмотрите таблицу ASCII.
Задача ограничения длины решается, например, чтением справочника языка — all-ht.ru/inf/prog/c/func/fgets.html — или просто бесцеремонным обрубанием введённой строки. Для принуждения повторного ввода, думаю, вам подойдёт while либо do while — что больше нравится.
Синтаксис спецификации форматирования: printf и wprintf функции
Различные функции printf и wprintf принимают строку формата и необязательные аргументы и создают форматированную последовательность символов для выходных данных. Строка формата не содержит ни одной или содержит несколько директив, которые являются либо литеральными символами для выходных данных, либо закодированными спецификациями преобразования, описывающими способ форматирования аргумента в выходных данных. Эта статья описывает синтаксис для кодирования спецификаций преобразования в строке формата. Список этих функций см. в разделе Потоковый ввод-вывод.
Спецификация преобразования состоит из необязательных и обязательных полей, имеющих следующий вид:
Каждое поле спецификации преобразования — это символ или число, указывающее конкретный параметр формата или описатель преобразования. Обязательное поле type определяет тип преобразования, которое применяется к аргументу. Необязательные флаги, ширина и точность полей определяют другие аспекты формата, такие как начальные пробелы или нули, обоснование и отображаемая точность. Поле size указывает размер использованного и преобразованного аргумента.
Базовая спецификация преобразования содержит только символ процента и символ type. Например, %s определяет преобразование строк. Чтобы вывести символ знака процента, используйте %% . Если за символом процента следует символ, который не имеет смысла в поле формата, вызывается обработчик недопустимого параметра. Дополнительные сведения см. в разделе «Проверка параметров».
Для обеспечения безопасности и стабильности убедитесь, что строки спецификации преобразования формата не определены конечным пользователем. Например, рассмотрим программу, которая предлагает пользователю ввести имя и сохраняет введенные данные в строковой переменной с именем user_name . Чтобы распечатать user_name , никогда не сделайте следующее:
printf( user_name ); /* Danger! If user_name contains «%s», program will crash */
Вместо этого используйте следующий код:
printf( «%s», user_name );
В Visual Studio 2015 printf были объявлены inline и scanf перемещены в заголовки и семейства функций. Если вы переносите старый код, вы можете увидеть LNK2019 в связи с этими функциями. Дополнительные сведения см. в журнале изменений Visual C++ 2003 – 2015.
Спецификатор преобразования типов
Символ спецификации преобразования type определяет, как должен интерпретироваться соответствующий аргумент: как символ, строка, указатель, целое число или число с плавающей запятой. Символ type — единственное обязательное поле спецификации преобразования; он указывается после всех необязательных полей.
Аргументы, которые следуют за строкой формата, интерпретируются согласно соответствующему символу type и необязательному префиксу size. Преобразования для типов char символов и wchar_t указываются с помощью или C однобайтовой и многобайтовой и широкой символьной строки задаются с c помощью s или S в зависимости от используемой функции форматирования. Аргументы символов и строк, указанные с помощью и c s интерпретируются как char char* и семейными printf функциями, а также wchar_t wchar_t* как и семейными функциями wprintf . Аргументы символов и строк, указанные с помощью и C S интерпретируются как wchar_t wchar_t* и семейными printf функциями, а также char char* как и семейными функциями wprintf . Это поведение зависит от Корпорации Майкрософт. По историческим причинам wprintf функции используют c и s ссылаются на wchar_t символы, а также C S указывают узкие символы.
Целые типы, такие как short , int , long long long и их unsigned варианты, указываются с помощью d , , i , o , u x и X . Типы с плавающей запятой, такие как float double , e f A E и long double , указываются с помощью , a , F g и . G По умолчанию, если они не изменяются префиксом размера , целочисленные аргументы принужаются к int типу и аргументы с плавающей запятой принуживаются к double . В 64-разрядных системах int используется 32-разрядное значение. Поэтому 64-разрядные целые числа будут усечены при форматировании выходных данных, если не используется префикс ll размера или I64 не используется. Типы указателей, указанные с помощью p размера указателя по умолчанию для платформы.
Только для систем Майкрософт:
Символ Z типа и поведение c символов , C s а S также символов типов при их использовании с printf функциями wprintf — расширения Майкрософт. Стандарт ISO C использует и s согласованно используется c для узких символов и строк, а C S также для расширенных символов и строк во всех функциях форматирования.
Символы поля типа
| Символ типа | Аргумент | Формат вывода |
|---|---|---|
| c | Символ | При использовании с функциями printf определяет однобайтовый символ; при использовании с функциями wprintf определяет расширенный символ. |
| C | Символ | При использовании с функциями printf определяет расширенный символ; при использовании с функциями wprintf определяет однобайтовый символ. |
| d | Целое | Десятичное целое число со знаком. |
| i | Целое | Десятичное целое число со знаком. |
| o | Целое | Восьмеричное целое число без знака. |
| u | Целое | Десятичное целое число без знака. |
| x | Целое | Целое число без знака; использует значение » abcdef «. |
| X | Целое | Целое число без знака; использует значение » ABCDEF «. |
| e | С плавающей запятой | Подписанное значение с формой [ — ]dddd e [ + — |]dd[d], где d — одна десятичная цифра, dddd — одна или несколько десятичных цифр в зависимости от указанной точности или шести по умолчанию, а dd[d] — две или три десятичные цифры в зависимости от формата вывода и размера экспонента. |
| E | С плавающей запятой | Идентичен формату e , за исключением того, что E вместо e представления экспонента. |
| f | С плавающей запятой | Подписанное значение, которое имеет форму [ — ]dddd . dd, где d имеет одну или несколько десятичных цифр. Количество цифр перед десятичной запятой зависит от величины числа, а количество знаков после десятичной запятой зависит от указанной точности либо используется шесть по умолчанию. |
| F | С плавающей запятой | Идентичен формату, за исключением бесконечности и выходных f данных NaN. |
| g | С плавающей запятой | Подписанные значения отображаются в f формате или e формате, в зависимости от того, что является более компактным для заданного значения и точности. Формат e используется только в том случае, если экспонент значения меньше -4 или больше или равен аргументу точности . Нули в конце отбрасываются, а десятичная запятая отображается только в том случае, если за ней следует хотя бы одна цифра. |
| G | С плавающей запятой | Идентичен формату g , за исключением того, что e E вместо этого представляет экспонент (где это необходимо). |
| a | С плавающей запятой | Подписанное шестнадцатеричное значение двойной точности с плавающей запятой, которое имеет форму [] 0x hh + | — p []dd, где h.hh являются шестнадцатеричными цифрами (с использованием строчных букв) мантисса, и dd — один или несколько цифр для экспонента. — Точность определяет количество цифр после запятой. |
| A | С плавающей запятой | Подписанное шестнадцатеричное значение двойной точности с плавающей запятой, которое имеет форму [ — ] 0X hhh P [ — + |]dd, где h.hhhh являются шестнадцатеричными цифрами (используя буквы букв) мантисса, и dd — один или несколько цифр для экспонента. Точность определяет количество цифр после запятой. |
| n | Указатель на целое число | Число символов, которые успешно записаны на данный момент в поток или буфер. Это значение хранится в целом числе, адрес которого указан в качестве аргумента. Размер целочисленного значения, на которое ссылается указатель, управляется префиксом спецификации размера аргумента. Описатель n отключен по умолчанию. Дополнительные сведения см. в примечании по безопасности. |
| p | Тип указателя | Отображение аргумента в виде адреса в шестнадцатеричных цифрах. |
| s | Строка | При использовании с функциями printf определяет строку однобайтовых или многобайтовых символов; при использовании с функциями wprintf определяет строку расширенных символов. Символы отображаются до первого нулевого символа или до тех пор, пока не будет достигнуто значение precision. |
| S | Строка | При использовании с функциями printf определяет строку расширенных символов; при использовании с функциями wprintf определяет строку однобайтовых или многобайтовых символов. Символы отображаются до первого нулевого символа или до тех пор, пока не будет достигнуто значение precision. |
| Z | Структура ANSI_STRING или UNICODE_STRING | VS 2013 и более ранних версий Когда адрес ANSI_STRING или UNICODE_STRING структура передается в качестве аргумента, отображает строку, содержащуюся в буфере, на которую указывает Buffer поле структуры. Используйте префикс модификатора размера для указания аргумента w UNICODE_STRING , например %wZ . Поле Length структуры должно содержать значение длины строки в байтах. Поле MaximumLength структуры должно содержать значение длины буфера в байтах. |
Универсальная среда выполнения C (UCRT)
Существует известная проблема в UCRT, которая в настоящее время поддерживается для обеспечения совместимости. S Как и описатель, Z описатель без префикса модификса размера ссылается на UNICODE_STRING использование узкой функции печати (например printf ) и ANSI_STRING при использовании широкой функции печати (например wprintf ).
Вместо этого Z используйте для hZ указания ANSI_STRING значения . wZ (или lZ ) можно по-прежнему использовать для указания UNICODE_STRING значения .
В Visual Studio 2015 и более поздних версиях, если аргумент, соответствующий описатель преобразования с плавающей запятой ( a , , f E e F A g ) G является бесконечным, неопределенным или NaN, форматированные выходные данные соответствуют стандарту C99. В этой таблице перечислены форматированные выходные данные.
| Значение | Выходные данные |
|---|---|
| Infinity | inf |
| Несигнальное значение NaN | nan |
| Сигнальное значение NaN | nan(snan) |
| Неопределенное значение NaN | nan(ind) |
Любой из этих строк может быть префиксирован знаком. Если символ описателя преобразования type с плавающей запятой является прописной буквой, выходные данные форматируются также прописными буквами. Например, если спецификатором формата является %F вместо %f , бесконечность форматируется как INF вместо inf . Функции scanf также могут анализировать эти строки, поэтому эти значения могут совершать круговой путь через функции printf и scanf .
До выхода Visual Studio 2015 в среде CRT использовался другой нестандартный формат для выходных данных значений бесконечности, неопределенных значений и значений NaN.
| Значение | Выходные данные |
|---|---|
| + Бесконечность | 1.#INF случайные цифры |
| -Бесконечности | -1.#INF случайные цифры |
| Неопределенное (то же, что и не число без вызова исключения) | цифра .#IND случайные цифры |
| Не число | цифра .#NAN случайные цифры |
Любой из этих строк может быть префиксирован знаком и может быть отформатирован по-разному в зависимости от ширины поля и точности, иногда с необычными эффектами. Например, печать 1.#J , printf(«%.2f\n», INFINITY) так как #INF будет «округлено» до двух цифр точности.
Если аргумент, который соответствует %s или %S , или поле Buffer аргумента, который соответствует %Z , является указателем NULL, отображается значение «(NULL)».
Во всех экспоненциальных форматах минимальное отображаемое количество цифр показателя степени по умолчанию равно двум (три используются только при необходимости). С помощью _set_output_format функции можно задать число цифр, отображаемых в три для обратной совместимости с кодом, написанным для Visual Studio 2013 и раньше.
%n Так как формат по сути небезопасн, он отключен по умолчанию. При %n обнаружении в строке формата вызывается обработчик недопустимых параметров, как описано в разделе проверки параметров. Сведения о включении %n поддержки см. в статье _set_printf_count_output .
Директивы флагов
Первое необязательное поле в спецификации преобразования содержит директивы флага. Это поле содержит ноль или несколько символов флагов, которые указывают выходное обоснование и контрольные выходные данные знаков, пустые значения, начальные нули, десятичные точки и шестнадцатеричные префиксы. В спецификации преобразования может быть указано несколько директив флагов, и символы флагов могут размещаться в любом порядке.
Символы флагов
| Флаг | Значение | По умолчанию |
|---|---|---|
| — | Выравнивание результата по левому краю в пределах заданной ширины поля. | Выравнивание по правому краю. |
| + | Используйте знак (+ или -), чтобы префиксировать выходное значение, если оно имеет подписанный тип. | Знак отображается только для отрицательных значений со знаком –. |
| 0 | Если ширина префиксирована 0 , начальные нули добавляются до достижения минимальной ширины. Если указаны одновременно 0 и — , знак 0 игнорируется. Если 0 задан для целочисленного формата ( i , , u x , X , , o ) d и спецификации точности также присутствуют ( например, %04.d — 0 игнорируются). Если 0 задано для a формата с A плавающей запятой, начальные нули добавляются в мантиссу после 0x префикса или 0X префикса. | Без заполнения. |
| пустой (» «) | Используйте пустое значение, чтобы префиксировать выходное значение, если оно подписано и положительно. Пустой префикс игнорируется, если одновременно с ним присутствует флаг +. | Пустой префикс не отображается. |
| # | Если он используется с параметром o , x или X форматом # , флаг использует 0 0x (или 0X соответственно) префикс любого выходного значения, отличного от нуля. | Префикс не отображается. |
| При использовании с флагом e , E , f a F A или форматированием # флаг заставляет выходное значение содержать десятичную точку. | Десятичный разделитель появляется, только если после него есть цифры. | |
| Если используется в сочетании с форматом g или G , флаг # принудительно добавляет десятичный разделитель к выходному значению и запрещает отбрасывать конечные нули. |
Спецификация ширины
В спецификации преобразования необязательное поле спецификации ширины отображается после любых символов флага. Аргумент width — это неотрицательное целое число, которое управляет минимальным числом символов, которые являются выходными. Если количество символов в выходном значении меньше заданной ширины, к значениям слева или справа (в зависимости от того, определен ли флаг выравнивания по левому краю ( — )) добавляются пробелы, в количестве, необходимом для достижения минимальной ширины. Если width префикс равен 0, начальные нули добавляются в целочисленные или с плавающей запятой преобразования до достижения минимальной ширины, за исключением случаев, когда преобразование равно бесконечности или NaN .
Спецификация ширины никогда не вызывает усечения значения. Если число символов в выходном значении больше указанной ширины или если width оно не указано, все символы значения являются выходными, при условии точной спецификации.
Если в качестве спецификации ширины указана звездочка ( * ), значение ширины задается аргументом int из списка аргументов. Аргумент width должен предшествовать значению, отформатируемого в списке аргументов, как показано в этом примере:
printf(«%0*d», 5, 3); /* 00003 is output */
Отсутствующее или небольшое width значение в спецификации преобразования не приводит к усечению выходного значения. Если результат преобразования превышает width значение, поле расширяется, чтобы содержать результат преобразования.
Спецификация точности
В спецификации преобразования третье необязательное поле является спецификацией точности. Он состоит из периода ( . ), за которым следует неотрицательное целое число, которое в зависимости от типа преобразования указывает количество строковых символов, число десятичных разрядов или число значимых цифр, которые должны быть выходными.
В отличие от спецификации ширины, спецификация точности может вызывать либо усечение выходного значения, либо округление значения с плавающей запятой. Если precision задано значение 0, а преобразованное значение равно 0, результат не выводит символов, как показано в этом примере:
printf( «%.0d», 0 ); /* No characters output */
Если спецификация точности представляет собой звездочку ( * ), аргумент int из списка аргументов предоставляет значение. В списке аргументов аргумент precision должен предшествовать форматируемому значению, как показано в следующем примере:
printf( «%.*f», 3, 3.14159265 ); /* 3.142 output */
Символ type определяет интерпретацию precision или точность по умолчанию при precision опущении, как показано в следующей таблице.
Влияние значений точности на тип
| Тип | Значение | По умолчанию |
|---|---|---|
| a , A | Точность определяет количество цифр после запятой. | Точность по умолчанию — 13. Если точность равна 0, десятичная запятая не выводится, если не используется флаг # . |
| c , C | Точность не применяется. | Символ выводится. |
| d , i , o , u , x , X | Точность определяет минимальное выводимое количество цифр. Если количество цифр в аргументе меньше значения precision, выходное значение дополняется слева нулями. Значение не усечено, если число цифр превышает точность. | Точность по умолчанию — 1. |
| e , E | Выводимое количество знаков дробной части задается спецификацией точности. Последняя выводимая цифра округляется. | Точность по умолчанию — 6. Если точность равна 0 или период ( . ) отображается без числа после него, десятичная точка не выводится. |
| f , F | Значение точности задает количество цифр после десятичной запятой. Если десятичная запятая присутствует, перед ней присутствует по крайней мере одна цифра. Значение округляется до соответствующего количества цифр. | Точность по умолчанию — 6. Если точность равна 0 или если период ( . ) отображается без числа после него, десятичная точка не выводится. |
| g , G | Точность определяет максимальное выводимое количество значащих цифр. | Выводятся шесть значащих цифр, а конечные нули усекаются. |
| s , S | Точность определяет максимальное количество выводимых символов. Символы, выходящие за рамки precision, не выводятся. | Символы печатаются до тех пор, пока не будет найден пустой символ. |
Спецификация размера аргумента
В спецификации преобразования поле size — это модификатор длины аргумента для описателя преобразования type. Префиксы поля размера в поле типа , j h hh , l , (строчные буквы), L , I w t z ll (верхний регистр i), I32 и I64 —укажите «размер» соответствующего аргумента — длинный или короткий, 32-разрядный или 64-разрядный, однобайтовый или широкий символ в зависимости от того, что они изменяют. Эти префиксы размера используются с символами type в семействах функций printf и wprintf для определения интерпретации размеров аргументов, как показано в следующей таблице. Поле size является необязательным для некоторых типов аргументов. Если префикс размера не указан, модуль форматирования использует целые аргументы, например подписанные или не подписанные char , short , int , long и типы перечисления как 32-разрядные типы int , а аргументы float , double и long double с плавающей запятой используются как 64-разрядные типы double . Такое поведение соответствует правилам повышения уровня аргументов по умолчанию для списков аргументов переменных. Дополнительные сведения о продвижении аргументов см. в разделе Многоточие и аргументы по умолчанию в выражениях Postfix. В 32-разрядных и 64-разрядных системах спецификация преобразования 64-разрядного целочисленного аргумента должна содержать префикс ll размера или I64 . В противном случае поведение модуля форматирования не определено.
Некоторые типы имеют разный размер в 32-разрядном и 64-разрядном коде. Например, size_t на 32 бита длиннее в коде, скомпилированном для x86, и на 64 бита длиннее в коде, скомпилированном для x64. Чтобы создать код форматирования для типов с переменным количеством байт, не зависящий от платформы, можно использовать модификатор размера аргумента с переменным количеством байт. Вместо этого используйте модификатор размера 64-разрядного аргумента и явно повысить тип аргумента переменной ширины до 64 бит. Модификатор размера аргумента ( I в верхнем регистре i) обрабатывает целые аргументы переменной ширины, но рекомендуется использовать модификаторы типа j t z и модификаторы для переносимости.
Префиксы размера для описателей типов формата printf и wprintf
| Чтобы указать | Используемый префикс | Со спецификатором типа |
|---|---|---|
| char unsigned char |
hh | d , i , o , u , x или X |
| short int short unsigned int |
h | d , i , o , u , x или X |
| __int32 unsigned __int32 |
I32 | d , i , o , u , x или X |
| __int64 unsigned __int64 |
I64 | d , i , o , u , x или X |
| intmax_t uintmax_t |
j или I64 | d , i , o , u , x или X |
| long double | l (строчная буква L) или L | a , A , e , E , f , F , g или G |
| long int long unsigned int |
l (строчная L) | d , i , o , u , x или X |
| long long int unsigned long long int |
ll (строчные буквы LL) | d , i , o , u , x или X |
| ptrdiff_t | t или I (верхний регистр i) | d , i , o , u , x или X |
| size_t | z или I (верхний регистр i) | d , i , o , u , x или X |
| Однобайтовый символ | h | c или C |
| Расширенный символ | l (строчная буква L) или w | c или C |
| Строка однобайтовых символов | h | s , S или Z |
| Строка расширенных символов | l (строчная буква L) или w | s , S или Z |
Типы ptrdiff_t и size_t являются __int32 или unsigned __int32 на 32-разрядных платформах и __int64 или unsigned __int64 на 64-разрядных платформах. I Префиксы (верхний регистр i), j t и z размеры принимают правильную ширину аргумента для платформы.
В Visual C++ хотя long double является отдельным типом, он имеет то же внутреннее представление, что и тип double .
Описатель hc или описатель типов является синонимом c функций printf и функций wprintf C hC . Описатель lc типов или wC описатель типов является синонимом функций printf C и функций c wprintf . lC wc Описатель hs или описатель типов является синонимом s функций printf и функций wprintf S hS . Описатель ls типов или wS описатель типов является синонимом S функций printf и функций s wprintf . lS ws
Только для систем Майкрософт:
I Префиксы модификатора размера аргументов (прописные буквы i), I32 I64 а также w префиксы размера аргументов являются расширениями Майкрософт и не совместимы с ISO C. Префикс h при использовании с данными типа char и l префиксом (строчным регистром L) при использовании с данными типа double являются расширениями Майкрософт.
Ввод-вывод в Си
Основной задачей программирования является обработка информации, поэтому любой язык программирования имеет средства для ввода и вывода информации. В языке Си нет операторов ввода-вывода.
Ввод и вывод информации осуществляется через функции стандартной библиотеки. Прототипы рассматриваемых функций находятся в файле stdio.h . Эта библиотека содержит функции
- printf() — для вывода информации
- scanf() — для ввода информации.
Вывод информации
Функция printf() предназначена для форматированного вывода. Она переводит данные в символьное представление и выводит полученные изображения символов на экран. При этом у программиста имеется возможность форматировать данные, то есть влиять на их представление на экране.
Общая форма записи функции printf() :
printf( «СтрокаФорматов» , объект1, объект2, …, объектn);
СтрокаФорматов состоит из следующих элементов:
- управляющих символов;
- текста, представленного для непосредственного вывода;
- форматов, предназначенных для вывода значений переменных различных типов.
Объекты могут отсутствовать.
Управляющие символы не выводятся на экран, а управляют расположением выводимых символов. Отличительной чертой управляющего символа является наличие обратного слэша ‘\’ перед ним.
Основные управляющие символы:
- ‘\n’ — перевод строки;
- ‘\t’ — горизонтальная табуляция;
- ‘\v’ — вертикальная табуляция;
- ‘\b’ — возврат на символ;
- ‘\r’ — возврат на начало строки;
- ‘\a’ — звуковой сигнал.
- %d — целое число типа int со знаком в десятичной системе счисления;
- %u — целое число типа unsigned int ;
- %x — целое число типа int со знаком в шестнадцатеричной системе счисления;
- %o — целое число типа int со знаком в восьмеричной системе счисления;
- %hd — целое число типа short со знаком в десятичной системе счисления;
- %hu — целое число типа unsigned short ;
- %hx — целое число типа short со знаком в шестнадцатеричной системе счисления;
- %ld — целое число типа long int со знаком в десятичной системе счисления;
- %lu — целое число типа unsigned long int ;
- %lx — целое число типа long int со знаком в шестнадцатеричной системе счисления;
- %f — вещественный формат (числа с плавающей точкой типа float );
- %lf — вещественный формат двойной точности (числа с плавающей точкой типа double );
- %e — вещественный формат в экспоненциальной форме (числа с плавающей точкой типа float в экспоненциальной форме);
- %c — символьный формат;
- %s — строковый формат;
- %p — указатель, вывод адреса переменной.
Строка форматов содержит форматы для вывода значений. Каждый формат вывода начинается с символа % . После строки форматов через запятую указываются имена переменных, которые необходимо вывести. Количество символов % в строке формата должно совпадать с количеством переменных для вывода. Тип каждого формата должен совпадать с типом переменной, которая будет выводиться на это место. Замещение форматов вывода значениями переменных происходит в порядке их следования.
1
2
3
4
5
6
7
8
9
10
Результат работы программы