Главная страница
Навигация по странице:

  • 24. Ссылки, передача в функцию ссылок. Константные ссылки.

  • 25. Функции с переменным количеством параметров.


  • 27. Перегрузка функций, шаблоны функции. Перегрузка функций

  • 28. Общие сведения о вводе выводе в Си++. Понятие потока ввода-вывода, классификация потоков. Стандартные потоки ввода вывода (объекты std::cin, std::cout, std::cerr, std::clog).

  • Общие сведения о вводе-выводе

  • Некоторые классы для задания потоков ios

  • Стандартные потоки ввода-вывода

  • 31 – 33 .Ввод вывод в файлы, основные классы и функции. Примеры открытия файлов для записи и чтения. Функции для перемещения курсора (файлового указателя) внутри файла.

  • 32.Ввод вывод в файлы. Пример записи в файл и чтения из файла в текстовом режиме. 33.Ввод вывод в файлы. Пример записи в файл и чтения из файла в двоичном режиме.

  • Основные элементы языка программирования Си алфавит, идентификаторы, ключевые слова, константы


    Скачать 0.78 Mb.
    НазваниеОсновные элементы языка программирования Си алфавит, идентификаторы, ключевые слова, константы
    Дата04.03.2022
    Размер0.78 Mb.
    Формат файлаdocx
    Имя файлаAYa.docx
    ТипДокументы
    #382846
    страница5 из 7
    1   2   3   4   5   6   7

    23.Передача в функцию массивов и строк.

    Передача в функцию массивов, не являющихся строками

    Имя массива без скобок является указателем на массив, в функцию массив

    передается по указателю (передается адрес первого элемента) и в качестве отдельного

    параметра передается число элементов массива (за исключением случая, когда

    размерность заранее определена и задается константой).

    Ниже представлен пример функции, которая считает сумму элементов массива.

    #include

    using namespace std;

    int GetSum(int *p, int n) // p - указатель на массив, n - число элементов
    {
    int sum = 0; // Начальное значение суммы
    int i;
    for (i = 0; i < n; i++) sum += p[i]; // Прибавляем к сумме элементы массива
    return sum;
    }

    int main() {
    int M[] = {1, 2, 3, 4, 5};
    int sum = GetSum(M, 5); // Вызов функции
    cout << "sum=" << sum << endl; // sum=15
    return 1;
    }

    При передаче массивов в функцию разрешена другая форма записи заголовка

    функции:

    int GetSum(int p[], int n)

    Передача в функцию строк

    При передаче строк достаточно передать адрес первого символа строки, число

    символов определяется по символу с кодом 0 (признак конца строки), число элементов

    массива можно не передавать. Ниже представлен пример функции для расчета длины

    строки.

    #include

    using namespace std;

    int GetLen(char *str) // str - указатель на строку
    {
    int len;
    for (len = 0; str[len]; len++); // Пока не встретится 0 увеличиваем индекс len
    return len;
    }

    int main() {
    char S[] = "Hello world";
    cout << "len=" << GetLen(S) << endl; // Будет напечатано len=11
    return 1;
    }

    24. Ссылки, передача в функцию ссылок. Константные ссылки.

    В языке Си++ появился новый тип – ссылки. В некоторых случаях их удобно

    использовать вместо указателей в качестве параметров функции, так как ссылка, по сути,

    является указателем, но к ней не надо применять операцию обращения по адресу («*»). В

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

    #include

    using namespace std;

    void MyFun(int &la) // Параметр функции - ссылка
    {
    la = 100; // Не нужно применять операцию – обращение по адресу
    }

    int main() {
    int a = 10;
    MyFun(a);
    cout << "a=" << a << endl; // Будет напечатано a=10
    return 1;
    }

    25. Функции с переменным количеством параметров.

    В языке Си существуют функции, количество параметров в которых заранее

    неизвестно (когда пишется исходный код функции), точное число параметров

    определяется только в момент вызова. Эти функции называются функция с переменным количеством параметров.

    Формат функции:

    <тип_возвращаемого_значения> <имя_функции>

    (<спецификация_обязательных_параметров>, …) { …. }

    В таких функциях должен быть хотя бы один обязательный параметр.

    Функция с переменным количеством параметров должна иметь при своем

    выполнении механизм определения количества параметров и их типов. Возможны два

    подхода:

    - передача в функцию числа реально используемых параметров в качестве одного из

    обязательных параметров;

    - добавление в конец списка параметров параметра с уникальным значением.

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

    стеке. В Си по умолчанию первым в стек помещается последний параметр, при этом он

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

    определить с модификатором pascal (модификатор устарел, не используется),

    противоположный ему модификатор __cdecl, ранее cdecl, функция имеет по умолчанию.

    Функции с модификатором pascal не могли иметь переменное количество параметров.

    Следует отметить, что модификатор __cdecl в режиме компиляции на языке Си++ многие

    среды разработки уже не используют (это модификатор языка Си).

    Ниже представлены две функции с переменным количеством параметров,

    демонстрирующих два описанных выше подхода для определения числа реальных

    параметров.

    #include

    using namespace std;

    int getSum(int n, ...) // Функция считает сумму параметров n - число параметров
    {
    int *p = &n; // Настраиваем указатель на 1-ый параметр
    int sum = 0; // Начальное значение суммы
    for (int i = 0; i < n; i++) // Суммируем n параметров
    sum += *++p; // Суммируем параметры (увеличиваем указатель на 1 и
    // обращаемся по адресу)
    return sum;
    }

    double
    getProiz(double par1, ...) // Функция считает произведение параметров, признак окончания списка параметров значение 0.0
    {
    double pr = 1; // Начальное значение произведения
    double *p = &par1; // Настраиваем указатель на 1-ый параметр
    for (; *p; p++) pr *= *p; // Умножаем на очередной параметр пока не встретится 0
    return pr;
    }

    int main() {
    double x = 1.45, x2 = 13.2;
    int a1 = 2, a2 = 6, a3 = 7;
    cout << getSum(5, a1, a2, a3, 1, 3) << endl;
    cout << getProiz(x, x2, 2.2, 3.3, 0.0) << endl;
    return 0;
    }

    Следует отметить, что представленный выше в программе подход, является

    небезопасным, работает в 32 разрядной версии Microsoft Visual C++, в других средах

    может работать не верно. Он демонстрирует особенности доступа к параметрам

    функции через указатели, в реальных программах так не следует делать.

    Рекомендуется использовать дополнительные средства для работы со списком

    параметров переменной длины, определенные в файле сstdarg.

    В файле определены макросы:

    va_start

    va_arg

    va_end

    Специальный тип данных va_list.

    Ниже представлен пример использования макросов.

    #include
    #include

    using namespace std;

    int getSum(int n, ...) {
    std::va_list args; // Список необязательных параметров функции
    va_start(args, n); // Задает первый необязательный параметр в списке
    int sum = 0;
    for (int i = 0; i < n; i++) {
    sum += va_arg(args, int); // Извлекает значение из списка параметров и переходит к следующему параметру в списке
    }
    va_end(args); // Освобождает список
    return sum;
    }

    double getProiz(double x1, ...) {
    double pr = x1;
    std::va_list args; // Список необязательных параметров функции
    va_start(args, x1); // Задает первый необязательный параметр в списке
    while (1) {
    double x = va_arg(args,
    double);// Извлекает значение из списка параметров и переходит к следующему параметру в списке
    if (x == 0.0) break;
    pr *= x;
    }
    va_end(args); // Освобождает список
    return pr;
    }

    int main() {
    double x = 1.45, x2 = 13.2;
    int a1 = 2, a2 = 6, a3 = 7;
    cout << getSum(5, a1, a2, a3, 1, 3) << endl;
    cout << getProiz(x, x2, 2.2, 3.3, 0.0) << endl;
    return 0;
    }

    26. Подставляемые (инлайн-) функции, указатели на функции.

    Подставляемая функция — это функция, определяемая с модификатором inline

    (__inline). Для обычной функции код функции существует в единственном экземпляре не

    зависимо от количества ее вызовов. Для подставляемой функции код функции

    существует в стольких экземплярах, сколько раз функция вызывается. Компилятор

    подставляет исполняемый код функции в точку вызова. Недостаток подставляемых

    функций - объем исполняемого кода программы возрастает, преимущество – возможен

    некоторый выигрыш в быстродействии, так как не требуется время на передачу

    управления на код функции при ее вызове.

    Подставляемые функции появились в языке Си++, в исходном языке Си их не

    было.

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

    Функция не может быть подставляемой:

    • функция слишком велика;

    • функция рекурсивная;

    • обращение к функции идет до ее определения;

    • функция вызывается более 1 раза в одном выражении;

    • функция имеет цикл, переключатель или оператор goto.

    При невыполнении перечисленных ограничений ошибки не будет, просто

    компилятор будет считать данную функцию не подставляемой, некоторые компиляторы

    могут при этом выдавать предупреждение. Обычно подставляемые функции являются

    небольшими, их основное назначение – вызов других функций. Ниже представлена

    подставляемая функция для вычисления длины вектора на плоскости.

    #include
    #include

    using namespace std;

    inline double getVect(double x, double y)
    // Функция считает длину вектора, заданного точкой x, y
    {
    return sqrt(x * x + y * y);
    }

    int main() {
    cout << getVect(3., 4.) << endl;
    return 1;
    }

    27. Перегрузка функций, шаблоны функции.

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

    функции должны отличаться количеством или типами параметров.

    Иногда говорят, что количество и типы параметров определяют сигнатуру

    функции. Сигнатура функции — это краткая запись функции, по которой она однозначно

    опознается компилятором, в языке Си++ сигнатура определяется именем и

    последовательностью типов ее параметров, имена параметров не нужны.

    Перегрузка функций появилась в языке Си++, в исходном языке Си такой

    возможности не было. Ниже представлен пример перегрузки функций.

    #include

    using namespace std;

    int summa(int a, int b) // Функция считает сумму 2-х параметров типа int
    {
    return a + b;
    }

    int summa(int a, int b, int c) // Функция считает сумму 3-х параметров типа int
    {
    return a + b + c;
    }

    double summa(double x, double y, double z) // Функция считает сумму 3-х параметров типа double
    {
    return x + y + z;
    }

    int main() {
    int s1, s2;
    double s3;
    s1 = summa(2, 3); // Вызывается первая функция
    s2 = summa(5, 5, 1); // Вызывается вторая функция
    s3 = summa(1., 2., 1.5); // Вызывается третья функция
    cout << "s1=" << s1 << " s2=" << s2 << " s3=" << s3 << endl;
    return 1;
    }

    28. Общие сведения о вводе выводе в Си++. Понятие потока

    ввода-вывода, классификация потоков. Стандартные потоки ввода вывода (объекты std::cin, std::cout, std::cerr, std::clog).

    Общие сведения о вводе-выводе

    В Си отсутствуют встроенные операторы (операции) ввода-вывода. Для ввода-вывода

    используются стандартные библиотеки функций (или классов).

    Основное понятие – поток ввода-вывода.

    Потоком (stream) называется источник или получатель данных, который можно

    ассоциировать с диском или другим внешним устройством ввода- вывода (файл, принтер,

    монитор, клавиатура и др.).

    Поток можно рассматривать как последовательность байтов (символов). С точки

    зрения программы поток не зависит от устройства, с которым он связан.

    Классификация потоков

    По направлению:

     входные;

     выходные;

     двунаправленные.

    По использованию буфера в оперативной памяти:

     буферизированные;

     небуферизированные.

    По особенностям «устройства», к которому подключен поток:

     стандартные;

     консольные (класс constream, в ОС Windows устарел);

     строковые;

     файловые.

    Использование буфера ввода- вывода в оперативной памяти позволяет с некоторых

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

    операции ввода- вывода с внешними устройствами, быстродействие которых существенно меньше (на порядки), чем быстродействие оперативной памяти. При буферизированном вводе выводе данные вначале отправляются в специальный буфер в оперативной памяти, по заполнению буфера они отправляются дальше (в переменные программы или во внешнее устройство вывода). Управляет буфером, как правило, операционная система, но существуют функции в библиотеке для сброса буфера. Схема буферизированного ввода- вывода представлена на рисунке 1.



    Некоторые классы для задания потоков

    ios - базовый потоковый класс

    istream - класс входных потоков

    ostream - класс выходных потоков

    iostream - класс двунаправленных потоков ввода - вывода

    istrstream - класс входных строковых потоков

    ostrstream - класс выходных строковых потоков

    strstream - класс двунаправленных строковых потоков ввода - вывода

    ifstream - класс входных файловых потоков

    ofstream - класс выходных файловых потоков

    fstream - класс двунаправленных файловых потоков ввода - вывода

    constream - класс консольных потоков (устарел).

    Стандартные потоки ввода-вывода

    Объекты соответствующих классов:

    -cin – станд. поток ввода (объекта класса istream), по умолчанию клавиатура консоли;

    -cout – станд. поток вывода (объекта класса ostream), по умолчанию дисплей консоли;

    -cerr – станд. небуферизированный поток для вывода сообщений об ошибках, по

    умолчанию дисплей консоли (объекта класса ostream);

    -clog – станд. буферизированный поток для вывода сообщений об ошибках, по

    умолчанию дисплей консоли (объекта класса ostream).

    Основные перегруженные операции (изначально операции поразрядного сдвига): «<<»

    - операция вставки, используется для вывода в поток, «>>» - операция извлечения,

    используется для чтения из потока.

    29. Форматирование при вводе-выводе: использование функций класса, использование флагов форматирования, использование манипуляторов.

    Обеспечивают форматирующие функции-члены класса, флаги и манипуляторы.

    Функции члены (для объекта вывода):

    cout.fill('/*symbol*/'); // устанавливает символ заполнитель

    // где symbol - символ заполнитель,

    cout.width(/*width_field*/); // задает ширину поля

    // где width_field - количество позиций


    cout.precision(/*number*/); // задает количество знаков после десятичной точки

    // где number - количество знаков после десятичной точки

    Флаги форматирования позволяют включить или выключить один из параметров

    ввода/вывода. Чтобы установить флаг ввода/вывода, необходимо вызвать функцию setf(),

    если необходимо отключить флаг, то используется функция unsetf().



    Манипуляторы

    Манипулятор — объект особого типа, который управляет потоками ввода/вывода, для

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

    заголовочный файл iomanip

    Некоторые манипуляторы:

    endl (переход на новую строку, сбрасывает буфер, действует при выводе), ends (добавляет 0 –

    конец строки, сбрасывает буфер, действует при выводе), flush (сбрасывает буфер, действует

    при выводе), boolalpha (вывод логического типа в текстовом виде), noboolalpha (отмена вывода

    логического типа), oct (восьмеричная СС), dec (ДСС), hex (ВСС), showbase (вывод основания

    СС), showpos (вывод знака + для положительных), scientific (экспоненциальная форма), fixed

    (форма с точкой), setw(int number) (мин. ширина поля вывода), right, left (выравнивание),

    setprecision(int count) (число цифр после точки), setfill(int symbol) (символ для заполнения).

    ?? 31 – 33 .Ввод вывод в файлы, основные классы и функции. Примеры открытия файлов для записи и чтения. Функции для перемещения курсора (файлового указателя) внутри файла.

    32.Ввод вывод в файлы. Пример записи в файл и чтения из файла в текстовом режиме.

    33.Ввод вывод в файлы. Пример записи в файл и чтения из файла в двоичном режиме.

    Ввод вывод в файлы
    Основные классы: ifstream, ofstream, fstream, заголовочный файл fstream.
    Открытие файла – функция базового класса (fstreambase) (или конструкторы классов с
    такими параметрами):


    void open(const char *filename,
    int mode=
    умал_значение,
    int protection=
    умал_значение)
    После открытия проверить наличие ошибок можно с помощью операции ! применяемой
    к объекту-потоку. Если ошибок нет, !объект поток вернет 0

    Режимы открытия:
    ios::in - чтение
    ios::out - запись
    ios::ate – при открытии искать конец файла
    ios::app – дописывать данные в конец файла
    ios::trunc – если файл существует, то он удаляется
    ios::nocreate – не открывать новый файл
    ios::noreplace – не открывать существующий файл (кроме режима добавления)
    ios::binary – открыть файл в двоичном режиме


    В текстовом режиме (установлен по умолчанию) при чтении последовательность
    символов \r\n преобразуется в \n, при записи происходит обратное преобразование. Символ \r (шестнадцатеричный код D) – возврат каретки, перемещает позицию печати в крайнее левое положение (исходно — без перевода на следующую строку). Символ \n (шестнадцатеричный код А) – перевод строки, перемещает позицию печати на одну строку вниз (исходно — без возврата каретки).
    Третий параметр определяет защиту файла.
    Для класса fstream второй параметр должен быть задан явно.
    Для закрытия файла используется функция: close().
    Примеры записи в файл и чтения из файла массива (vector) переменных структурного
    типа «Книга» в текстовом и двоичном режимах приведены ниже. Режимы приложения
    задаются как параметры командной строки: вначале чтение или запись, затем текстовый или
    двоичный режим, далее имя файла, например:
    write binary MyFile.dat режим записи, файл в двоичном режиме, имя файла MyFile.dat;
    read text MyFile.txt режим чтения, файл в текстовом режиме, имя файла MyFile.txt
    #include
    #include
    #include
    #include

    using namespace std;
    struct BOOK // Структура - книга
    {
    string Author;
    string Title;
    string Firm;
    int year, page;
    };

    // Печатаем массив книг
    void print_books(ostream &out, vector &Books) {
    for (auto &pos: Books)
    out << pos.Author << ". " << pos.Title << ". " << pos.Firm << ", " << pos.year <<
    ", " << pos.page << " c." << endl;
    }

    int main(int argc, const char *argv[]) {
    if (argc != 4) {
    cerr << "Error: Use four parameters\n";
    return 5;
    }
    const string mode(argv[1]); // Режим работы (запись или чтение)
    const string open_mode(argv[2]); // Режим открытия файла (текстовый или двоичный)
    const string file_name(argv[3]); // Имя файла
    int n; // Переменная, задающая число элементов массива
    vector Books; // массив структур
    if (mode == "write") { // Запись в файл
    // Ввод данных с клавиатуры
    cout << "n=";
    cin >> n; // Ввод числа книг
    Books.resize(n); // Задаем размер массива (вектора)
    for (int i = 0; i < n; i++) // Цикл ввода данных о книгах с клавиатуры
    {
    cout << "Book N=" << (i + 1) << endl;
    cout << "Author: ";
    cin.ignore(); // Пропускаем один символ из потока
    getline(cin, Books[i].Author);
    cout << "Title: ";
    getline(cin, Books[i].Title);
    cout << "Firm: ";
    getline(cin, Books[i].Firm);
    cout << "year: ";
    cin >> Books[i].year;
    cout << "page: ";
    cin >> Books[i].page;
    }
    if (open_mode == "text") {
    // Работа с файлом в текстовом режиме
    ofstream foutt(file_name); // Открываем файл для записи в текстовом режиме
    foutt << n << endl; // Записываем n в текстовом режиме, далее переход на новую строку
    for (auto &pos: Books) {
    foutt << pos.Author << endl << pos.Title << endl << pos.Firm << endl;
    // Каждая строка с новой строки
    foutt << pos.year << ' ' << pos.page << endl; // Числа в одну строку через пробелы
    }
    foutt.close(); // Закрываем файл
    } else if (open_mode == "binary") {
    // Работа с файлом в двоичном режиме
    ofstream foutb(file_name, ios::binary); // Открываем файл для записи в двоичном режиме
    foutb.write((char *) &n, sizeof(n)); // Записываем n в двоичном режиме
    for (auto pos: Books) {
    foutb << pos.Author << ends << pos.Title << ends << pos.Firm
    << ends; // После строк вставляем 0, как признак конца
    foutb.write((char *) &pos.year, sizeof(pos.year));
    foutb.write((char *) &pos.page, sizeof(pos.page));
    }
    foutb.close(); // Закрываем файл
    }
    } else if (mode == "read") {
    // Чтение из файла
    if (open_mode == "text") {
    ifstream fint(file_name); // Открываем файл для чтения в текстового режиме
    if (!fint) // Ошибка файл не открыт
    {
    cout << endl << "Error, file not found" << endl;
    system("pause");
    return 1;
    }
    fint >> n; // Читаем n в Текстовом режиме
    Books.resize(n); // Задаем размер массива
    for (auto &pos: Books) {
    fint.ignore(2, '\n'); // Пропускаем 2 символа с кодами 13 и 10 ('\n')
    getline(fint, pos.Author); //
    getline(fint, pos.Title);
    getline(fint, pos.Firm);
    fint >> pos.year;
    fint >> pos.page;
    }
    fint.close(); // Закрываем файл
    } else if (open_mode == "binary") {
    ifstream finb(file_name, ios::binary); // Открываем файл для чтения в двоичном режиме
    if (!finb) // Ошибка файл не открыт
    {
    cout << endl << "Error, file not found" << endl;
    system("pause");
    return 1;
    }
    finb.read((char *) &n, sizeof(n)); // Читаем n в двоичном режиме
    Books.resize(n); // Задаем размер массива
    for (auto &pos: Books) {
    getline(finb, pos.Author, '\0'); // Символ '\0' // Читается из потока
    getline(finb, pos.Title, '\0');
    getline(finb, pos.Firm, '\0');
    finb.read((char *) &pos.year, sizeof(pos.year));
    finb.read((char *) &pos.page, sizeof(pos.page));
    }
    finb.close(); // Закрываем файл
    }
    // Печать книг, прочитанных из файла
    print_books(cout, Books);
    }
    return 0;
    }
    1   2   3   4   5   6   7


    написать администратору сайта