include

advertisement
Введение в программирование
на языке C++
Строки и файлы
Заикин Олег Сергеевич
sat.isa.ru/pdsat/files/teaching/
zaikin.icc@gmail.com
Низкоуровневые строки
типа char*
Строка как массив
Строка – символьный одномерный массив, который
завершается нулевым символом '\0'.
Объявляя массив str, предназначенный для хранения
10-символьной строки, следует использовать 11 char
char str[11]; // резервируется место для '\0'
Строковый литерал – список символов, заключенный
в двойные кавычки.
"Hello" // в памяти
H
e
l
l
"" – нулевая строка, состоит только из '\0'
o
\0
Считывание строк
Объявляется статический массив символов
достаточной длины.
Например
char str[100];
Вариант 1. Использовать поток ввода >>
cin >> str; // считает только первое слово (до пробела)
Если пользователь вводит строку "Hello world", то str
присваивается значение “Hello”
Считывание строк
Вариант 2. Использовать функцию gets(). Функция
считает все символы (включая пробелы) до нажатия
Enter.
Пример.
char str[100];
cout << "Введите строку" << endl;
gets(str);
cout << "Вот Ваша строка " << str << endl;
Функции обработки строк
strlen(s) длина строки
Пример
str[12] = "Hello world";
int len = strlen(str); // len присваивается значение 11
strcpy(to, from) копирует из строки from в строку to.
Строка to должна иметь размер
не меньше, чем у строки from.
Пример
char str[100];
char str2[12] = "Hello world";
strcpy(str, str2); // У строки str теперь тоже значение
// "Hello world";
Функции обработки строк
strcmp(s1,s2)
сравнивает строки (в лексикографическом
порядке).
Если s1 < s2, возвращает отрицательное
значение. Если равны, возвращает 0. Если s1 >
s2, возвращает положительное значение.
strcat(s1,s2)
присоединяет строку s2 к строке s1.
Массивы строк
Массив строк – специальная форма двумерного
массива символов.
Пример
char text[100][80]; // массив из 100 строк длины 80
for (int i = 0; i < 100; i++) // считывание строк
{
gets(text[i]); // считывание очередной строки
if ( !text[i][0] ) break; // выход по пустой строке
}
Высокоуровневые строки
типа string
Требования к типу string

копирование одной строки в другую. Для
char* приходится использовать функцию
strcpy();

сравнение двух строк на равенство. Для
char* используется функция strcmp();

конкатенация
двух
строк,
получая
результат либо как третью строку, либо
вместо одной из исходных. Для char*
применяется функция strcat();

защита от выхода информации за их
границы.
Тип string
Для использования типа string необходимо
подключить к программе заголовочный файл
string
#include <string>
Пример объявления двух строк:
string str1, str2;
По умолчанию объявляется пустая строка.
Можно объявлять со значением:
string str1(“abc”);
Операции
=
==
!=
+
<
>
<<
>>
присваивание
равенство
неравенство
конкатенация
меньше
больше
вывод
ввод
Операции
К элементам строки можно обращаться как к
элементам одномерного массива
string str1("He"), str2(" llo");
str1 += str2; // теперь == Hello
if (str1 != str2)
cout << str1[1] << str1[3];
Вывод: el
Операции
Переменной типа string можно присваивать
char* или char[]
char *chptr1 = "string1";
string str1 = chptr2;
char chptr2[] = “string2";
string str2 = chptr2;
Найдите ошибки
char ch = "The long and winding road";
char ch = "T";
char ch = ‘Ta’;
int a = 5;
int ival = &a;
int ival = &ch;
char *pc = &ival;
char *pc = &ch;
string st( &ch );
pc = 0;
pc = '0';
st = pc;
st = &ival;
Функции для работы с string
s.clear()
– удаляет все элементы в строке
s.copy(to, count, beg) - копирует из строки s в to
(string, или char*) count символов начиная с символа
beg. Последние 2 параметра не обязательны.
s.erase(from, count) удаляет count элементов с
заданной позиции from
s.find(str,pos) - ищет строку str начиная с индекса pos
s.insert(pos, str) - начиная с символа с индексом pos
вставляет в строку s строку str
Функции для работы с string
int
len=s.length() - записывает в len длину строки
s.push_back(symbol) - добавляет в конец строки
символ
s.replace(index,
n, str) - берет n первых символов из
str и заменяет символы строки s на них, начиная с
позиции index
str=s.substr(n,m)
позиции n
- возвращает m символов начиная с
s.swap(str)
меняет содержимое s и str местами.
s.size() - возвращает число элементов в строке.
max_size() - максимально возможная длина строки
capacity()
- объем памяти, занимаемый строкой
Пример
#include <string>
#include <iostream>
using namespace std;
int main (){
string s1("прекрасная королева"), s2("ле"),
s3("корова");
cout << "s3= " << s3.insert(4, s2) << endl;
cout << "s3= " << s3.insert(7, "к") << endl;
s1.erase(0,3);
cout << "s1= " << s1.erase(12,2) << endl;
cout << "s1= " << s1.replace(0,3, s3, 4,2) << endl;
}
Какие значения будут выведены?
Пример
#include <string>
#include <iostream>
using namespace std;
int main (){
string s1("прекрасная королева"), s2("ле"), s3("корова");
cout << "s3= " << s3.insert(4, s2) << endl;
cout << "s3= " << s3.insert(7, "к") << endl;
s1.erase(0,3);
cout << "s1= " << s1.erase(12,2) << endl;
cout << "s1= " << s1.replace(0,3, s3, 4,2) << endl;
}
s3= королева
s3= королевка
s1= красная корова
s1= лесная корова
Пример использования find()
char GetColumn() {
string goodChar
= "ABCDEFGH";
char symb;
cout << "Введите обозначение колонки: ";
for(;;) {
cin >> symb;
if (-1 == goodChar.find(symb)) {
cout << "Ошибка. Введите корректный символ:\n";
continue;
}
return symb;
}
}
Задание
Даны две семантически эквивалентные программы.
Первая использует char*, вторая – тип string.
Что эти программы делают?
Отличаются ли они по скорости?
// ***** Реализация с использованием C-строк *****
#include <iostream>
#include <cstring>
int main() {
int errors = 0;
const char *pc = "a very long literal string";
for ( int ix = 0; ix < 1000000; ++ix ) {
int len = strlen( pc );
char *pc2 = new char[ len + 1 ];
strcpy( pc2, pc );
if ( strcmp( pc2, pc ))
++errors;
delete [] pc2;
}
cout << "C-строки: “ << errors << " ошибок.\n";
}
// ***** Реализация с использованием класса string *****
#include <iostream>
#include <string>
int main() {
int errors = 0;
string str( "a very long literal string" );
for ( int ix = 0; ix < 1000000; ++ix ) {
int len = str.size();
string str2 = str;
if ( str != str2 )
++errors;
}
cout << "класс string: "<< errors << " ошибок.\n;
}
Строковые потоки

Строковые
потоки
позволяют
считывать
и
записывать информацию из областей оперативной
памяти так же, как из файла, с консоли или на
дисплей
istringstream
ostringstream
stringstream
Эти классы определяются в заголовочном файле
<sstream>
 Участки памяти, с которыми выполняются операции
чтения и извлечения, по стандарту определяются
как строки С++ (класс string).
 Строковые
потоки
могут
применяться
для
преобразования данных, а также для обмена
информацией между модулями программы.

Строковые потоки. Пример 1
#include <string>
#include <sstream>
…
string str;
stringstream sstream;
int arr_len, val;
int *arr; // массив целых чисел
… // заполнение массива arr
for (int i = 0; i < arr_len; i++)
sstream << arr[i] << “ ”;
sstream << endl;
cout << sstream.str(); // вывод строки потока
sstream.clear(); sstream.str(“”); // очистка строкового потока
Строковые потоки. Пример 2
#include <string>
#include <sstream>
…
string str;
stringstream sstream;
int val;
sstream.clear(); sstream.str(“”); // очистка строкового потока
str = “45”;
sstream << str;
sstream >> val; // преобразование из string в int
Строковые потоки. Пример 2
int strtoint( string str )
{
stringstream sstream;
sstream << str;
int val;
sstream >> val;
return val;
}
ФАЙЛОВЫЕ ПОТОКИ
Файловые потоки
В программах на C++ при работе с текстовыми
файлами в потоковом режиме необходимо
подключать библиотеку fstream.
Поток ifstream служит для работы с файлами в
режиме чтения.
Поток ofstream служит для работы с файлами в
режиме записи.
Поток fstream служит для работы с файлами в
режиме, как чтения, так и записи.
Работают операторы ввода >> и вывода <<.
Функции для файлов
open(filename, mode);
filename – полное имя файла на диске;
mode – режим работы с открываемым файлом.
os::eof() - проверка, достигнут ли конец файла
(end of file). Истина, если достигнут конец файла.
clear() – очистить для последующего использования,
использовать перед close()
close() – закрыть файл после использования
getline(file, string) – считывает строку из файла
file имеет тип ifstream или fstream
string имеет тип char* или string
Открытие и закрытие файла
Виды mode:
ios::in
открыть файл в режиме чтения данных, этот режим
является режимом по умолчанию для потоков ifstream
ios::out
открыть файл в режиме записи данных, этот режим
является режимом по умолчанию для потоков ofstream
ios::app
открыть файл в режиме записи данных в конец файла
ios::ate
передвинуться в конец уже открытого файла
ios::trunc очистить файл, это же происходит в режиме ios::out
Чтение из файла
#include <fstream>
…
ifstream infile;
int a; int arr[10];
infile.open( “filename.txt”, ios :: in);
// проверка открыт ли файл
if (!infile) {
cout << "Файл не открыт\n";
return 1;
}
infile >> a; // Чтение из файла числа
k = 0;
while (!infile.eof())
infile >> arr[k++]; // чтение из файла чисел в массив
infile.clear(); infile.close();
Чтение слов в статический массив
ifstream infile;
char text[10][100]; // максимум 10 строк
infile.open( “filename.txt”, ios :: in);
k = 0;
while (!infile.eof())
infile >> text[k++]; // чтение слова в массив строк
infile.close();
Чтение слов в динамический массив
ifstream infile;
char **text; // динамический массив строк
infile.open( “filename.txt”, ios :: in);
k = 0;
char str[100];
while (!infile.eof()) {
infile >> str; // чтение слова в массив строк
k++;
}
infile.clear(); infile.close(); // закрываем файл
// k в итоге – количество слов
text = new char*[k]; // массив из k строк
for ( int i = 0; i < k; i++ )
text[i] = new char[100];
// теперь можно снова открыть файл и считать слова
Чтение строк из файла
ifstream infile;
char str[100];
infile.open( “filename.txt”, ios :: in );
while ( infile.getline(str, 100) ) // пока считываются строки
cout << str; // вывести строку
// также можно записать строку в массив
infile.close();
Запись в файл
После открытия файла в режиме записи, в него можно
писать с помощью <<
Пример
double a = 3.5;
int b = 4;
ofile.open( “filename.txt”, ios_base :: out);
ofile << “first value ” << a << “ second value ” << b;
ofile.close();
В файле:
first value 3.5 second value 4
Файлы и строки
При считывании строк из файла для простейших
операций не нужен массив слов.
fstream file;
string str;
// считываем слова из файла
while ( !file.eof )
file << str;
Файлы и строки
Пример. Нужно считать строку из файла, к каждому
слову добавить символ ‘!’ и вывести результат в
консоль
fstream file;
string str;
while ( !file.eof ) {
file << str; // считываем слово в строку
cout << str << “! ”;
}
// Что в программе не совсем так?
Файлы и строки
Пример. Нужно считать строку из файла, к
каждому слову добавить символ ‘!’ и
записать результат в этот же файл.
Как измениться программа?
Файлы и строки
fstream file;
string str, sum_str;
while ( !file.eof ) {
file << str; // считываем слово в строку
sum_str += str + “! ”;
}
sum_str.erase( sum_str.size()-1, 1 );
file >> endl >> sum_str;
Файлы и строки
Можно использовать указатель типа string как
динамический массив строк.
string *str_arr;
int str_size;
… // получить str_size
str_arr = new string[str_size];
Download