Язык Си - руководство для начинающих - M. УЭИТ
Шрифт:
Интервал:
Закладка:
где NULL определен в файле stdio.h как 0. При помощи указателя массиву name присваивается значение. Наличие возврата позволяет присваивать значение всей gets(name) и выполнять проверку на EOF. Этот двоякий подход более компактен, чем использование функции getchar( ), которая имеет возврат без аргумента.
while((ch = getchar( )) != EOF)
Функция scanf( )
Мы уже использовали ранее функцию scanf( ) и формат %s для считывания строки. Основное различие между scanf( ) и gets( ) заключается в том, как они определяют, что достигли конца строки: scanf( ) предназначена скорее для получения слова, а не строки. Функция gets( ), как мы уже видели, принимает все символы до тех пор, пока нс встретит первый символ "новая строка". Функция scanf( ) имеет два варианта. Для любого из них строка начинается с первого встретившегося непустого символа. Если вы используете формат %s, строка продолжается до (но не включая) следующего пустого символа (пробел, табуляция или новая строка). Если вы определяете размер поля как %10s, то функция scanf( ) считает нe более 10 символов или же считает до любого пришедшего первым пустого символа.
Функция scanf( ) возвращает целое значение, равное числу счи танных символов, если ввод прошел успению, или символ EОF, ее ли он встретился.
/* scanf( ) и подсчет количества */
main( )
{
static char name1[40], name2[11];
int count;
printf(" Введите, пожалуйста, 2 имени.n");
count = scanf(" %s %10s", name1, name2);
printf(" Я считал %d имен %s и %s.n", count, name1, name2);
}
Вот два примера работы программы:
Введите, пожалуйста, два имени.
Джсссика Джукс.
Я считал два имени
Джсссика и Джукс.
Введите, пожалуйста, 2 имени.
Лиза Апплеботтхэм
Я считал 2 имени Лиза и Апплеботтхэм.
Во втором примере были считаны только первые 10 символов от Апплеботтхэм, так как мы использовали формат %10s.
Если вы получаете только текст с клавиатуры, лучше применять, функцию gets( ). Она проще в использовании, быстрее и более компактна. Функция scanf( ) предназначена в основном для ввода смеси типов данных в некоторой стандартной форме. Например, если каждая вводимая строка содержит наименование инструмента, количество его на складе и стоимость каждого инструмента, вы можете использовать функцию scanf( ) или можете создать свою собственную функцию, которая выполняет проверку некоторых ошибок при вводе.
ВЫВОД СТРОК
Опять мы должны полагаться на библиотечные функции, которые могут немного изменяться от системы к системе. Функции puts( ) и printf( ) - две рабочие лошадки, используемые при выводе строк.
Функция puts( )
Это очень простая функция; у нее есть только один аргумент, являющийся указателем строки. Нижеследующий пример иллюстрирует некоторые из многих способов ее применения.
/* простые выдачи */
#include <stdio.h>
#define DEF "Я строка #define."
main( )
{
static char str1[ ] = "Массив инициализирован мной.";
static char *str2 = "Указатель инициализирован мной.";
puts(" Я аргумент функции puts( )." );
puts(DEF);
puts(str1);
puts(str2);
puts(&str1[4]);
puts(str2 + 4);
}
В результате работы программы получаем
Я аргумент функции puts( ).
Я строка #define.
Массив инициализирован мной.
Указатель инициализирован мной.
ив инициализирован мной.
атель инициализирован мной.
Этот пример напоминает нам, что фразы в кавычках и имена строк символьных массивов являются указателями. Обратите внимание на два последних оператора. Указатель &strl[4] ссылается на пятый элемент массива str1. Этот элемент содержит символ 'и', и функция puts( ) использует его в качестве начальной точки. Аналогично str2 + 4 ссылается на ячейку памяти, содержащую 'а' в "указателе", и с нее начинается вывод строки.
Как puts( ) узнает, когда остановиться? Она прекращает работу, если встречает нуль-символ, поэтому лучше, чтобы он был. Не пытайтесь делать так!
/* нет строки! */
main( )
{
static char dont[ ] = (' H', ' Г , ' ! ', ' ! ');
puts(dont); /* dont не является строкой */
}
Поскольку в dont отсутствует завершающий нуль-символ, она не является строкой. Так как нуль-символ отсутствует, puts( ) не знает, когда ей останавливаться. Она будет просто перебирать ячейки памяти, следующие за dont до тех пор, пока не найдет где-нибудь нуль-символ. Если повезет, она, может быть, найдет его в ближайшей ячейке, но может и нe повезти.
Обратите внимание, что любая строка, вводимая функцией puts( ), начинается с новой строки. Если puts( ) в конце концов находит завершающий нуль-символ, она заменяет его символом "новой строки" и затем выводит строку.
Функция printf( )
Мы уже обсуждали функцию printf( ) довольно основательно. Подобно puts( ), она использует указатель строки в качестве аргумента. Функция printf( ) менее удобна, чем puts( ), но более гибка.
Разница заключается в том, что printf( ) не выводит автоматически каждую строку текста с новой строки. Вы должны указать, что хотите выводить с новых строк. Так,
printf(" %sn" , string);
дает то же самое, что и
puts(string);
Вы можете видеть, что первый оператор требует ввода большего числа символов и большего времени при выполнении на компьютере. С другой стороны, printf( ) позволяет легко объединять строки для печати их в одной строке. Например:
printf(" Хорошо, %s, %s n", name, MSG);
объединяет " Хорошо" с именем пользователя и c символьной строкой MSG в одну строку.
СОЗДАНИЕ СОБСТВЕННЫХ ФУНКЦИЙ
Не ограничивайте себя при вводе и выводе только этими библиотечными функциями. Если у вас нет нужной функции, или она вам не нравится, можно создавать свои собственные версии, используя для этого getchar( ) и putchar( ).
Предположим, у вас нет функции puts( ). Вот один из путей ее создания:
/* put1 - печатает строку */
put1(string);
char *string;
{
while(*string != ' ') putchar(*string++);
putchar('n');
}
Символьный указатель string вначале ссылается на первый элемент вызванного аргумента. После печати его содержимого указатель увеличивается и ссылается уже на следующий элемент. Это продолжается до тех пор, пока указатель не дойдет до элемента, содержащего нуль-символ. Затем в конце строки будет поставлен символ новой строки.
Предположим, у вас есть puts( ), но вам нужна функция, которая, кроме того, сообщает, сколько напечатано символов. Эту возможность легко добавить:
/* put2- - печатает строку и считывает символы */
put2 (string);
char *string;
{
int count = 0;
while(*string != ' ') {
putchar(* string++);
count++;
putchar('n');
return(count);
}
Вызов:
put2(" пицца" );
печатает строку пицца, в то время как оператор
num = puts(" пицца");
передаст, кроме того, количество символов в num; в данном случае это число 5. Вот несколько более сложный вариант, показывающий вложенные функции:
/* вложенные функции */
#include <stdio.h>
main( )
{
put1("Если бы я имел столько денег, сколько могу потратить,");
рrintf("Я считаю %d символа.n",
put2(" Я никогда бы нe жаловался, что приходится чинить старые стулья.");
}
(Мы включили в программу при помощи директивы #include файл stdio.h, потому что в нашей системе в нем определена функция putchar( ), а она используется в нашей новой функции.)
Да-а, мы используем функцию printf( ) для печати значения put2( ), но в процессе нахождения значения put2( ) компьютер должен сначала заставить ее поработать - напечатать строку. Вот что получается при этом: