ЖАНРЫ

Язык Си - руководство для начинающих

Д. МАРТИН

Шрифт:

printf(Извините, я не могу открыть % s. До свидания.\n", name1);

else

{ puts(" Итак, начнем!");

f2 = fopen(name2, "w");

while((ch = getc(f1)) != EOF)

if(crit == UPPER)

ch = islower(ch) ? toupper(ch) : ch;

else

ch = isupper(ch) ? tolower(ch) : ch;

putc(ch, f2);

} fclosc(f2);

fclosc(f1);

puts("Сделано!");

} }

РИС. 15.3. Программа преобразования строчных букв в прописные и обратно.

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

while(getchar != '\n');

Этот цикл включен для решения проблемы, с которой мы столкнулись в гл. 14. Когда пользователь отвечает на вопрос о виде преобразования, скажем, буквой U, он нажимает клавишу U, а затем клавишу [ввод], которая передает '\n'.

Первоначальная функция getchar извлекает U, но оставляет '\n' для следующего чтения строки. Функция gets, входящая в getnames, интерпретировала бы '\n' как пустую строку, поэтому мы использовали малый цикл while, чтобы избавиться от символа "новая строка". Действительно, простая getchar, сделала бы это, если бы пользователь непосредственно за U нажимал бы [ввод]. Но наша версия, кроме того, предусматривает возможность нажать на клавишу пробела несколько раз перед [ввод].

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

Функция conv является функцией копирования с выполнением преобразования. Значение crit используется для определения требуемого преобразования. Работа выполняется простым условным оператором, таким как

ch = islower(ch) ? toupper(ch) : ch;

Он проверяет, является ли ch строчной буквой. Если да, то символ преобразуется в прописную букву. Если нет, остается как есть.

Макрофункции файла ctype.h предоставляют удобные и полезные средства для программирования. Теперь давайте займемся некоторыми более сложными функциями преобразования.

ПРЕОБРАЗОВАНИЯ СИМВОЛЬНЫХ СТРОК: atoi, atof

Использование scanf для считывания цифровых значений не является самым надежным способом, поскольку scanf легко внести в заблуждение ошибками пользователей при вводе чисел с клавиатуры. Некоторые программисты предпочитают считывать даже числовые данные как символьные строки и преобразовывать строку в соответствующее числовое значение. Для этого используются функции atoi и atof. Первая преобразует строку в целое, вторая - в число с плавающей точкой. Вот (рис. 15.4) образец их использования:

/* включение atoi */

#include <stdio.h>

#define issign(c) (((с) == '-' || (с) == '+') ? (1) : (0))

#define SIZE 10

#define YES 1

#define NO 0

main

{

char ch;

static char number[SIZE];

int value;

int digit = YES;

int count = 0;

puts(" Введите, пожалуйста, целое.");

gets(number);

if(number[SIZE - 1] != '\0')

{ puts("Слишком много цифр; вы уничтожили меня.");

exit(1);

} while((ch = number[count]) !='0' && digit == YES)

if(!issign(ch) && iisdigit(ch) && !isspace(ch))

digit = NO;

if(digit == YES)

{ value = atoi(number);

printf(" Число было %d.\n" , value); }

else

printf(" Это не похоже на целое.");

}

РИС. 15.4. Программа использования atoi.

Мы предусмотрели проверку некоторых ошибок. Во-первых, следует посмотреть, умещается ли входная строка в предназначенном для нее массиве. Поскольку number является статическим символьным массивом, он инициализируется нулями. Если последний элемент массива не является нулем, значит что-то неверно, и программа прекращает работу. Здесь мы использовали библиотечную функцию exit, которая выводит нас из программы. Немного позже мы расскажем кратко об этой функции.

Затем посмотрим, не содержит ли строка что-нибудь кроме пробелов, цифр и алгебраических знаков. Функция отвергает такие строки, как "дерево" или "1.2Е2". Ее устраивает смесь, подобная "3 - 4 + 2", но atoi будет выполнять дальнейший отбор. Вспомним, что ! является операцией отрицания, поэтому !isdigit(c) означает: "с не является цифрой". Строка

value = atoi(nuinbcr);

показывает, как используется функция atoi. Ее аргумент является указателем символьной строки; в этом случае мы применили имя массива number. Функция возвращает целое значение для такой строки. Таким образом, "1234" является строкой из четырех символов и переводится в 1234 - единое число типа int.

Функция atoi игнорирует ведущие пробелы, обрабатывает ведущий алгебраический знак, если он есть, и обрабатывает цифры вплоть до первого символа, нс являющегося цифрой. Поэтому наш пример "3 - 4 + 2" был бы превращен в значение 3. Посмотрите "Вопросы" в конце главы для возможного применения этой функции.

Функция atof выполняет подобные действия для чисел с плавающей точкой. Она возвращает тип double, поэтому должна быть описана как double в использующей ее программе.

Поделиться с друзьями: