ТОП 10:

Стандартная библиотека языка Си. Ввод, вывод данных



Для обмена данными между компьютером и пользователем в стандартной библиотеке языка Си есть специальные функции – это printf и scanf. Первая выводит данные в стандартный консольный вывод, вторая получает данные и записывает их в переменные. Так же есть функции putc и getc, которые проделывают это с одним символом.

Функции – это подпрограммы в Си, выполняющие определённые операции. Есть функции в стандартной библиотеке, но можно добавить в программу свои. Функция может возвращать значение, которое может быть использовано в программе. Например, функция printf возвращает количество выведенных символов, а scanf – количество распознанных элементов. Функции принимают аргументы, которые являются параметрами для выполнения. Аргументы перечисляются через запятую.

В функции printf первым аргументом является выводимая строка, в которую вставляются, а вторым и последующими аргументами – эти самые переменные. Спецификаторы формата в первом аргументе определяют типы переменных и их форматирование. 1-му спецификатору формата соответствует 2-й аргумент, второму – 3-ий, и т.д.

Общий вид спецификаций формата: %[флаг][ширина][.точность][h|l|L]тип

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

Подробнее форматирование рассмотрим позже, данные могут выводиться и при отсутствии элементов, условно поставленных в квадратные скобки. Поэтому минимальный вид спецификаторов формата таков: %тип. Рассмотрим некоторые их типы: c Символ

s Строка символов d, i Целое десятичное со знаком o Целое восьмеричное

u Целое десятичное без знака x, X Целое шестнадцатеричное

f Дробное число в фиксированном формате e, E Дробное число в научном формате

g, G Дробное число в научном или фиксированном формате

p Указатель (в шестнадцатеричном виде).

Пример спецификаторов формата: %d – целое число %s - строка

Аналогичные спецификаторы применяются и в scanf, первый аргумент определяет вид поступающих данных, только второй и последующий аргументы функции – указатели на переменные. Это необходимо для того, чтобы функция получила доступ к самим данным, а не к копии переменной, как это делается в случае передачи переменной в функцию. Чтобы получить указатель на переменную, необходимо добавить перед ней знак &.

Итак, перейдём к практике. Рассмотрим следующий пример:

// так обозначаются комментарии, они не учитываются компилятором

#include

int main() // главная функция

{

int i;

printf("Enter integer number: ", i);

scanf("%d", &i); // получение числа из стандартного ввода в переменную i

i = i*i+3; // действия над переменной

printf("Result: %d\n", i); // вывод результата, \n означает перевод строки

return 0;

}

Данная программа получает число, возводит его в квадрат и прибавляет 3.


 

fprintf(name,“<управляющая строка>”[, <список аргументов>])

fscanf (name,“<управляющая строка>”[, <список аргументов>])

Управляющая строка содержит обычные символы, которые выводятся на экран, спецификации преобразования и управляющие символы константы. Каждая спецификация начинается с символа % и заканчивается символом преобразования. Между ними могут записываться “ – ” ,” . ”,” l ”, указываться размер поля или максимальное число символов или цифр для вывода.

Символы преобразования: d- аргумент преобразуется в десятичное целое со знаком u- аргумент преобразуется в десятичное целое без знака o- аргумент преобразуется в восьмеричное целое без знака x- аргумент преобразуется в шестнадцатеричное целое без знака c- значением аргумента является одиночный символ s- значением аргумента является строка символов g- значением аргумента является вещественное: либо f, либо e e- значением аргумента является вещественное типа float или double в форме с плавающей точкой f- значением аргумента является вещественное типа float или double в форме с фиксированной точкой p- значением аргумента является указатель. Для произвольного перемещения по файлу и прямого доступа к его компонентам используется функция

fseek(name, long offset, int point),

которая устанавливает указатель текущей позиции в файле на offset байт относительно точки отсчета, определенной значением point ( 0- от начала файла, 1- от текущей позиции, 2- от конца файла). Функция возвращает значение 0, если операция выполнена правильно, и –1, если есть ошибка.

Для закрытия файла используется функция fclose(name).

41 Файловый ввод-вывод с использованием потоков.Для осуществления операций с файлами предусмотрено три класса: ifstream, ofstream и fstream. Эти классы являются производными, соответственно, от классов istream, ostream и iostream. Поскольку эти последние классы, в свою очередь, являются производными от класса ios, классы файловых потоков наследуют все функциональные возможности своих родителей (перегруженные операции << и >> для встроенных типов, функции и флаги форматирования, манипуляторы и пр.). Для реализации файлового ввода-вывода нужно включить в программу заголовочный файл fstream.h. Существует небольшое отличие между использованием предопределенных и файловых потоков. Файловый поток должен быть связан с файлом прежде, чем его можно будет использовать. С другой стороны, предопределенные потоки могут использоваться сразу после запуска программы, даже в конструкторах статических классов, которые выполняются даже раньше вызова функции main(). Можно позиционировать файловый поток в произвольную позицию в файле, в то время как для предопределенных потоков это обычно не имеет смысла. Для создания файлового потока эти классы предусматривают следующие формы конструктора: создать поток, не связывая его с файлом:

ifstream(); // ofstream(); // fstream();

создать поток, открыть файл и связать поток с файлом:

ifstream(const char *name, ios::openmode mode = ios::in) ;

ofstream(const char* name, ios::openmode mode=ios::out | ios::trunc);

fstream(const char * name, ios::openmode mode = ios::in | ios::out);

Чтобы открыть файл для ввода или вывода, можно использовать вторую форму нужного конструктора fstream fs("FileName.dat"); или вначале создать поток с помощью первой формы конструктора, а затем открыть файл и связать поток с открытым файлом, вызвав функцию-член open(). Эта функция определена в каждом из классов потокового ввода-вывода и имеет следующие прототипы:

void ifstream::open(const char *name, ios::openmode mode = ios::in);

void ofstream::open

(const char * name, ios::openmode mode = ios::out | ios::trunc);

void fstream::open

(const char * name, ios::openmode mode = ios::in | ios::out);

Здесь name - имя файла, mode - режим открытия файла. Параметр mode является перечислением.

Режимы открытия файла представляют собой битовые маски, поэтому можно задавать два или более режима, объединяя их побитовой операцией ИЛИ. В следующем фрагменте кода файл открывается для вывода с помощью функции open():

ofstream ofs;

ofs.open("FileName.dat");

Обратим внимание, что по умолчанию режим открытия файла соответствует типу файлового потока. У потока ввода или вывода флаг режима всегда установлен неявно. Например, для потока вывода в режиме добавления файла можно вместо оператора

ofstream ofs("FName.txt", ios::out | ios::app);

написать

ofstream ofs("FName.txt", ios::app);

Между режимами открытия файла ios::ate и ios::app имеется небольшая разница.

Если файл открывается в режиме добавления, весь вывод в файл будет осуществляться в позицию, начинающуюся с текущего конца файла, безотносительно к операциям позиционирования в файле. В режиме открытия ios::ate (от английского "at end") можно изменить позицию вывода в файл и осуществлять запись, начиная с нее. Для потоков вывода режим открытия эквивалентен ios::out | ios::trunc, то есть можно опустить режим усечения файла. Однако для потоков ввода-вывода его нужно указывать явно. Файлы, которые открываются для вывода, создаются, если они еще не существуют.

Если открытие файла завершилось неудачей, объект, соответствующий потоку, будет возвращать 0:

if (!ofs){ cout << "Файл не открыт\n";}

Проверить успешность открытия файла можно также с помощью функции-члена is_open(), имеющей следующий прототип:

int is_open() const;

Функция возвращает 1, если поток удалось связать с открытым файлом. Например,

if (!ofs.is_open()){ cout << "Файл не открыт\n"; return; }

Если при открытии файла не указан режим ios::binary, файл открывается в текстовом режиме и после того, как файл успешно открыт, для выполнения операций ввода-вывода можно использовать операторы извлечения и вставки в поток. Для проверки, достигнут ли конец файла, можно использовать функцию ios::eof(), имеющую прототип int eof();

Завершив операции ввода-вывода, необходимо закрыть файл, вызвав функцию-член close() с прототипом void close():

ofs.close();

Закрытие файла происходит автоматически при выходе потокового объекта из области существования, когда вызывается деструктор потока.

 


42 Препроцессор. Директивы #include, #define, #if…

Во всех компиляторах с языков C/C++ есть некая фаза, называемая препроцессированием. Фаза эта запускается автоматически и по большому счёту является прозрачной для пользователя (программиста). Т.е. пользователь в большинстве случаев препроцессор самостоятельно НЕ запускает.

Препроцессирование - это процесс, на вход которого подаётся текст (текстовый файл) и на выходе формируется текст. Во время работы препроцессор занимается тем, что видоизменяет исходный текстовый файл. Команды препроцессора (их наз директивами) начинаются на символ #, который должен первым непробельным символом в строке. Первыми директивами препроцессора, с которыми сталкиваются начинающие, являются директивы #include и #define

Директива include включает в текст программы содержимое указанного файла и имеет две формы: #include"имя файла" #include <имя файла>

Имя файла должно соответствовать соглашениям ОС и может состоять только из имени файла, либо из имени файла с указанием пути к этому файлу. Способ поиска файла зависит от того, заключено ли его имя в двойные кавычки или в угловые скобки. Если имя файла задано в угловых скобках, поиск файла проводится в специальном каталоге. Обычно таким каталогом является каталог INCLUDE интегрированной среды разработки (IDE). Если имя файла указано в кавычках, то поиск файла начинается с текущего каталога, а если файл не найден, поиск продолжается в каталоге INCLUDE.

Заголовочный файл (объект-заголовок) снабжает компилятор необходимой информацией о данных и функциях, которые могут использоваться в программе, имеет расширение .h (header) и представляет собой текстовый файл. Заголовочный файл может содержать определение типов, прототипы функций, объявление внешних переменных (extern), директивы препроцессора и комментарии.

Любая C-программа должна содержать хотя бы одну директиву. Так, для реализации ввода/вывода должна присутствовать директива: #include <stdio.h>

Файл stdio.h (standard input/output header) содержит необходимую информацию о средствах ввода/вывода информации.

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

Директива define имеет две синтаксические формы:

#define идентификатор текст #define идентификатор (список параметров) текст

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

Директива препроцессора #if во многом похожа на оператор if. Ее синтаксис имеет вид:

#if условие фрагмент кода #endif

В этой записи условие является целочисленным выражением. Если это выражение возвращает не нуль (истинно), то фрагмент кода, заключенный между директивой #if и директивой #endif, компилируется. Если же выражение возвращает нуль (ложно), то этот фрагмент игнорируется и препроцессором, и компилятором.


43 Одномерные массивы. Инициализация одномерных массивов. Ввод и инициализация массива символов.С++ позволяет инициализировать глобальные и локальные массивы на этапе объявления. Стандартный вид инициализации массива аналогичен инициализации переменных, как показано ниже:

спецификатор типа имя_массива [размерN] ... [размер1] = {список значений};

Список значений - это разделенный запятыми список констант, совместимых по типу со спецификатором типа. Первая константа помещается в первый элемент массива, вторая - во второй и так далее. За последней константой списка нет запятой. Обратим внимание, что точка с запятой следует за }. В следующем примере 10-элементный целочисленный массив инициализируется числами от 1 до 10: int i [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Это означает, что i[0] получит значение 1, i[9] - 10.

Массивы символов, содержащие строки, допускают удобную инициализацию в виде

char имя_массива [размер] = "строка";

При данной инициализации нулевой терминатор автоматически добавляется к концу строки. Нижеприведенный фрагмент кода инициализирует строку str фразой «hello»:

char str[6] = "hello";

Это можно также записать:

char str [ 6 ] = {'h', 'е', 'l', 'l', 'o', '\0'};

Обратим внимание, что в данной версии следует явным образом указать нулевой символ. Поскольку все строки в С оканчиваются нулевым символом, следует убедиться, что массив достаточно длинный для его вмещения. Именно поэтому str состоит из 6 символов, хотя «hello» имеет только 5 символов.







Последнее изменение этой страницы: 2016-08-14; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.235.66.217 (0.007 с.)