- •Институт математики, экономики и механики кафедра математического обеспечения компьютерных систем в. С. Макогон, и. Н. Лисицына
- •Оглавление
- •Введение
- •Основныетипы данных, операции и выражения
- •Описание переменных.
- •Операции , выражения и операторы.
- •3. Операторы управления программой. Базовые управляющие структуры.
- •Операторы ветвления Условный оператор if
- •Оператор - переключатель
- •Операторы повторения (цикла).
- •4. Программирование алгоритмов линейной структуры.
- •5. Программирование разветвляющихся алгоритмов (оператор if).
- •6. Программирование разветвляющихся алгоритмов (оператор switch)
- •Оператор for
- •Цикл с постусловием do -while
- •8. Итерационные циклы
- •Задачи для самостоятельного решения
- •9. Программирование алгоритмов с использованием функций
- •Основные понятия численного решения уравнений
- •10. Программирование алгоритмов с использованием массивов
- •11. Символьные переменные и строки. Обработка строк.
- •Другие средства ввода-вывода символов и строк
- •Массивы строк
- •12. Указатели
- •Массивы указателей
- •2. Описание метода трапеций
- •3. Программный комплекс
- •13. Структуры
- •Указатели на структуры
- •14. Файлы. Потоковый ввод-вывод
- •Функции для работы с файлами
- •Открытие файловых потоков
- •Закрытие файловых потоков
- •Удаление файлов
- •Переименование файлов
- •Реинициализация
- •Функции для ввода-вывода по символам
- •1 Вариант) содержит только буквы исходной строки
- •2 Вариант) перевернута по отношению к исходной
- •Двоичные (бинарные) файлы. Блочно-ориентированный ввод-вывод.
11. Символьные переменные и строки. Обработка строк.
Строка представляет собой массив символов, завершающийся так называемым нуль-символом — символом с кодом 0 (’\0’). По положению нуль-символа определяется реальная длина строки. Например, определение переменной-строки из 79 символов выглядит так:
char s1[80];
Строки можно при их определении инициализировать строковыми константами (см. раздел “ Основные типы данных, операции и выражения ”); при этом нуль-символ в конце строки формируется автоматически:
char s1[80] = “Здесь был Вася” ;
либо даже так:
char s1[] = “Здесь был Вася” ;
В последнем случае компилятор сам выделит память, достаточную для размещения строки с завершающим нулём. Если инициализирующая строка короче, чем указанный размер строки, то оставшиеся элементы строки инициализируются символом ‘\0’.
Определить в программе константу-строку MSG можно одним из следующих способов:
#define MSG “Умом Россию не понять”
или
const char MSG[ ] = “Умом Россию не понять”;
Имя переменной-строки (без квадратных скобок) отождествляется в программе с ее адресом. Поэтому операции присваивания и сравнения для строк c завершающим нуль-символом в С/С++ недопустимы. Нельзя, например, использовать такую последовательность предписаний:
char str[80];
…
str = “ Здесь был Вася ” ;
Для присваивания переменной строкового литерала можно использовать подходящую стандартную функцию библиотеки языка:
strcpy(str, “ Здесь был Вася ”);
Библиотека стандартных функций имеет в своем составе множество полезных функций для работы со строками, в том числе: для вычисления реальной длины строки (strlen()); сцепления строк ( strcat(), strncat()); сравнения строк (strcmp(), strncmp()); поиска вхождения символа в строку (strchr()); поиска подстроки в строке (strstr()) и др. Эти функции описаны в заголовочном файле <string.h> (<cstring>). Более подробно синтаксис каждой из них легко выяснить с помощью справочной системы Интегрированной среды разработки.
Дадим краткое описание важнейших функций
Функция strlen(s1)возвращает длину строки, указанной аргументом s1.
Функция strcpy(s1, s2)копирует содержимое строки s2 в строку s1. Строка s1 должна быть достаточно протяженной, чтобы в неё можно было поместить строку s2. В противном случае возможно аварийное завершение программы.
Функция strcat(s1, s2)присоединяет строку s2 в конец строки s1, при этом строка s2 не изменяется. Обе строки должны завершаться нулевым символом. Результирующая строка s1 также будет завершаться нулевым символом. Строка s1 должна быть достаточно большой, чтобы в нее поместилось, кроме ее исходного содержимого, содержимое строки s2.
Функция strcmp(s1, s2)сравнивает строку s2 со строкой s1 и возвращает значение 0, если они равны. Если строка s1 лексикографически (т.е. в соответствии с алфавитным порядком) больше строки s2, возвращается положительное число; если строка s1 лексикографически меньше строки s2, возвращается отрицательное число. Точнее говоря, функция возвращает разность кодов первой пары несовпавших символов.
В стандартной библиотеке имеются полезные функции преобразования строк в числа (разумеется, если это возможно):
atof() – преобразует заданную строку в double; atoi() – преобразует строку в int; atol() – в long. Если строку нельзя преобразовать в число, возвращается 0. Обратные преобразования можно осуществить с помощью библиотечной функции sprintf().
В языке C++ существует и другой тип представления строк . Он заключается в применении объектов класса string, который является частью библиотеки классов C++.
Таким образом, класс string — не встроенный тип. Он подразумевает объектно-ориентированный подход к обработке строк, обеспечивает удобные для пользователя операции и методы: ввод и вывод строк , присваивание, сравнение, конкатенацию строк, поиск подстроки и др. Важно отметить, что строки типа string защищены от выхода информации за их границы (длина строки изменяется динамически в соответствии с потребностями). Однако тип string проигрывает массивам символов в эффективности и используется не так широко, как строки с завершающим нулем. В дальнейшем мы рассматриваем в основном строки с завершающим нулем.
Покажем для сравнения важнейшие операции для работы со строками, используя параллельно оба метода.
// Программа отлажена вVisual Studio 2008
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int main()
{ char c1[80], c2[80],c3[80]; //строки с 0-символом
string s1, s2, s3; //объекты класса string
//Присваивание строк
strcpy_s(c1,"Стиль языка С");
strcpy_s(c2, c1);
s1="Стиль языка С++";
s2=s1;
//Сцепление строк
strcpy_s(c3,"1 - ");
strcat_s(c3, c2); cout<<c3<<endl;
s1="2 - ";
s3=s1 + s2; cout<<s3<<endl;
return 0;
}
Результат выполнения программы:
1 – Стиль языка С
2 – Стиль языка С++
Ввод – вывод строк.
Для ввода‑вывода строк естественно пытаться использовать известные нам объекты cin и cout языка C++, а также функции языка С (scanf(), printf(), gets(), puts() и др.)
В отличие от массивов, строки вводятся и выдаются на экран не поэлементно, а целиком, что присуще простым переменным:
char s1[80]; cout << “Как тебя зовут?”;
cin >> S1; cout << “Привет” << S1;
Следует иметь в виду, что если количество вводимых символов превышает длину строки, определённую при её описании, то поведение программы непредсказуемо.
Рассмотрим примеры.
Задача 106. Программа запрашивает имя пользователя и после ответа приветствует его по имени. Используется стиль C++.
#include <iostream.h>
#include <conio.h>
void main()
{
char S1[80];
cout<<"Как тебя зовут? ";
cin>>S1;
cout<<"Привет, "<<S1<<”!”;
getch();
}
Задача 107. Программа запрашивает имя пользователя и после ответа приветствует его по имени. Используется стиль C.
#include <conio.h>
#include <stdio.h>
void main()
{
char S1[80];
printf("Как тебя зовут? ");
scanf("%s", S1);
printf("Привет, %s\n! ", S1);
getch();
}
Протестируйте две приведенные выше программы. Сначала введите имя, состоящее из одного слова. Обе программы корректно обрабатывают введённую строку и выдают правильные результаты. Введите теперь имя, состоящее из двух слов (например, Наполеон Бонапарт). Во втором случае в приветствии выводится только первое слово! Это вызвано тем, что ввод строки средствами cin и scanf() осуществляется до первого пробельного символа (т.е. пробела, знака табуляции и символа перевода строки ‘\n’).
Рассмотрим ещё один пример.
Задача 108.Программа запрашивает имя пользователя и его любимый напиток, а после ответа приветствует его по имени. Используется стильC++.
// Программа отлажена вVisual Studio 2008
#include <iostream>
#include <string.h>
#include <conio.h>
using namespace std;
int main()
{
char name[25],drink[25];
// Устанавливаем локализацию для выходного потока
wcout.imbue( locale( "rus_rus.866" ) );
// Выводим строку на русском !
wcout<<L"Как Вас зовут? ";
cin>>name;
wcout <<L"Ваш любимый напиток? "; cin>>drink;
wcout<<L"Привет, "<<name<<'\n';
wcout<<L"Да, "<<drink<<L" - чудесный напиток"<<endl;
_getch(); return 0;
}
Чтобы помочь вам разобраться в том, что делает эта программа, приведём результаты её работы (полужирным курсивом выделен текст, вводимый пользователем):
Как Вас зовут? Бонапарт Наполеон
Ваш любимый напиток? Привет, Бонапарт
Да, Наполеон - чудесный напиток
Таким образом, текст, введённый после пробельного символа, не игнорируется! Он сохраняется в специальном буфере ввода‑вывода и извлекается оттуда при вызове очередной функции ввода данных. Этим и объясняется, что вводить по оператору
сin >> drink;
ничего не понадобилось: фраза “Наполеон” была извлечена из буфера.
Применение функции scanf() вместо cin приводит к аналогичным результатам. Протестируйте следующую задачу самостоятельно.
Задача 109. Программа запрашивает имя пользователя и его любимый напиток, а после ответа приветствует его по имени. Используется стиль C.
#include <stdio.h>
#include <conio.h>
void main()
{
char name[15],drink[12];
printf("Как Вас зовут? "); scanf("%s",name);
printf("Ваш любимый напиток? "); scanf("%s",drink);
printf("Привет, %s\n",name);
printf("Да, %s - чудесный напиток\n",drink);
getch();
}
В дальнейшем для ввода строк будем в основном использовать функцию gets(S1) (S1 — имя вводимой строки), которая лишена указанного выше недостатка. Эта функция вводит все символы входного потока, в том числе и пробелы, пока не будет нажата клавиша Enter. Код клавиши Enter преобразуется в нуль-символ и все введенные символы заполняют строковую переменную S1. Но и эта функция не безгрешна: если количество вводимых символов превышает длину строки S1, определённую при её описании, то, скорее всего, программа завершится аварийно.
Что же касается вывода строк, то можно с одинаковым успехом применять метод cout, функции printf(), puts():
cout << “Привет, ” << name << endl;
printf (“Привет, %s\n”, name );
puts(“Привет,”); puts(name);
Следует иметь в виду, что функция printf() менее удобна, чем puts(), но более гибкая. В частности, printf(), в отличие от puts(), не выводит автоматически каждую строку текста с новой строки экрана. С другой строки, функция puts() выводит за одно обращение к ней только одну строку символов, а printf() может легко объединить несколько выводимых строк в одну:
сhar name[20], S1[] = “Привет,”;
printf( Как тебя зовут?); gets(name);
printf(“%s %s\n” , S1, name);
Задача 110.Программа запрашивает имя пользователя и его любимый напиток, а после ответа приветствует его по имени. Используются функцииgets(),puts() и printf() для ввода-вывода. Теперь программа работает корректно.
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
int main()
{
char name[15],drink[12];
puts("Как Вас зовут? "); gets(name);
puts("Ваш любимый напиток? "); gets(drink);
printf("Привет, %s\n",name);
printf("Да, %s - чудесный напиток\n",drink);
_getch(); return 0;
}