Необходимый материал

Необходимый материал

Сообщение EgorovAD MEPhI » 18 ноя 2013, 08:05

Лекция 7. Символы и строки в языке С++
До сих пор мы работали только с числовыми данными, как целыми, так и действительными. Но, как правило (если речь идет не о сугубо научных расчетах) приходится оперировать с текстовой информацией.

Символьный тип char
Любой текст состоит из символов. Вопрос: что такое символ? Символ – это некоторый значок, изображение. Как и любой значок, в зависимости от особенностей конкретного человек, символ можно написать по-разному. Таким образом и в компьютере, разные символы (в зависимости от шрифта, размера, стиля) могут иметь одно и то же значение. Верно и обратное, буква “A” и “А”, несмотря на то, что выглядят абсолютно одинаково, являются разными буквами, соответственно русского и латинского алфавитов.

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

Логичным шагом является стандартизация обозначений некоторых символов цифровыми константами. Изначально было обговорено, что один символ - это 8 бит информации. Таким образом можно было закодировать 256 различных символов. Этого оказалось вполне достаточно для того, что записать все символы латинского алфавита, цифры, знаки препинания, другие специфические символы. Стандарт, который указывает, какие числовые коды соответствуют каким основным символам называется ASCII. В таблицу ASCII входят символы с кодами от 0 до 127. (таблица 7.1.)
Изображение
Таблица 7.1. ASCII.

При этом символы с кодами, меньшими 32 - это специальные управляющие символы, которые не отображаются на экране. Например, для того, чтобы обозначить конец строки в системе Linux используется один символ с кодом 10, а в системе Windows - два подряд идущих символа с кодами 13 и 10, символы с кодами 48-57 соответствуют начертанию арабских цифр (обратите внимание, символ с кодом 0 - это вовсе не символ, отображающийся на экране, как “0”), символы с кодами 65-90 - заглавные буквы латинского алфавита, а если к их кодам прибавить 32, то получатся строчные буквы латинского алфавита. В промежутках между указанными диапазонами находятся знаки препинания, математические операции и прочие символы.

Важно заметить, в ASCII-таблицы нет русских букв! А также нет букв сотен других национальных алфавитов. Первоначально для отображения букв национальных алфавитов использовали вторую половину возможного значения байта, то есть символы с кодами от 128 до 255. Это приводило к множеству проблем, например, поскольку 128 значений явно недостаточно для того, чтобы отобразить символы всех национальных алфавитов (даже недостаточно для того, чтобы отобразить символы одного алфавита, например, китайской письменности. Поэтому в настоящее время для кодирования символов используется стандарт Unicode, последняя версия 5.2 которого (октябрь, 2009) включает 107361 различный символ. Естественно, для кодирования Unicode-символов недостаточно одного байта на символ, поэтому используются многобайтовые кодировки (для представления одного символа необходимо несколько байт).
Отсюда следуют постоянны ошибки с выводом русского текста на экран. Поэтому, работа с русскими строками не используется в олимпиадах вообще.


В языке C++ для хранения однобайтового символа используется тип данных char. Переменную типа char можно рассматривать двояко: как целое число, занимающее 1 байт и способное принимать значения от -128 до 127 (тип signed char, есть также беззнаковая модификация unsigned char, принимающая значения от 0 до 255) и как один символ текста. Само по себе определение char может оказаться как знаковым, так и беззнаковым, в зависимости от операционной системы и компилятора. Поэтому использовать тип char не рекомендуется, лучше явно указывать будет ли он знаковым (signed) или беззнаковым (unsigned).
EgorovAD MEPhI
Администратор
 
Сообщений: 155
Зарегистрирован: 04 ноя 2011, 11:49

Re: Необходимый материал

Сообщение EgorovAD MEPhI » 18 ноя 2013, 08:08

Работа с char
Как и целые числа, данные типа char можно складывать, вычитать, умножать и даже делить. Но если операции умножения и деления, как правило, бессмысленны, то сложение и вычитание вполне осмысленно. Например, если к символу 'A' прибавить 1, то получится символ 'B', а если вычесть 1, то получится символ '@'. То есть в следующем фрагменте кода на экран будет выведена буква B. Рассмотрим конкретный пример:
Код: выделить все
char c = 'A';
c = c + 1;
cout << c << endl;


В этом примере видно, что переменным типа char можно присваивать значения, равные ASCII кодам символов, если эти символы заключать в кавычки. То есть запись 'A' будет соответствовать символу A, или ASCII коду 65.
Также в этом примере видно, что при выводе на экран переменной типа char мы увидим изображение этого символа. Как же узнать значение ASCII-кода символа? Его не нужно узнавать, сам символ - это и есть ASCII-код. А как его вывести на экран? Очень просто - нужно преобразовать значение величины типа char к значению типа int. Например, вот так:
Код: выделить все
cout << (int) c << endl;


Аналогично, при считывании переменной типа char через поток cout, из потока ввода считывается один символ, переменная получает значение, равное его ASCII-коду. Например, если написать программу, содержащую строчки
Код: выделить все
char c;
cin >> c;

Затем запустить ее, ввести символ A (безо всяких кавычек!), то в переменную c будет записано значение 65 - ASCII-код символа A.

Переменным типа char можно и явно присваивать числовые значения. Например, можно сделать так:
Код: выделить все
#include <iostream>

using namespace std;

int main()
{
    unsigned char c = 'A';
    cout << c << " " << (int) c << endl;

    c = 126;      // char можно присвоить и числовое значение
    cout << c << " " << (int) c << endl;

    return 0;
}


Эта программа выведет две строки: “A 65” и “~ 126”, то есть символы с ASCII-кодами 65 (A) и 126 (~) и сами ASCII-коды.
EgorovAD MEPhI
Администратор
 
Сообщений: 155
Зарегистрирован: 04 ноя 2011, 11:49

Re: Необходимый материал

Сообщение EgorovAD MEPhI » 18 ноя 2013, 08:09

Строки в языке С
Строки в С++ представляются как массивы элементов типа char, заканчивающиеся нуль-терминатором \0 (символом с кодом 0) называются С строками или строками в стиле С.
Символьные строки состоят из набора символьных констант заключённых в двойные кавычки. При объявлении строкового массива необходимо учитывать наличие в конце строки нуль-терминатора, и отводить дополнительный байт под него.
Строка при объявлении может быть инициализирована начальным значением, например, так:
Код: выделить все
char str[10] = "abcdefghf";


Если подсчитать кол-во символов в двойных кавычках после символа равно их окажется 9, а размер строки 10 символов, последнее место отводится под нуль–терминатор, причём компилятор сам добавит его в конец строки.
Код: выделить все
// посимвольная инициализация строки:
char string[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'f', '\0'};
// десятый символ это нуль-терминатор.


При объявлении строки не обязательно указывать её размер, но при этом обязательно нужно её инициализировать начальным значением. Тогда размер строки определится автоматически и в конец строки добавится нуль-терминатор.
Строка может содержать символы, цифры и специальные знаки. В С++ строки заключаются в двойные кавычки. Имя строки является константным указателем на первый символ.
EgorovAD MEPhI
Администратор
 
Сообщений: 155
Зарегистрирован: 04 ноя 2011, 11:49

Re: Необходимый материал

Сообщение EgorovAD MEPhI » 18 ноя 2013, 08:12

Длина строки
Для определения длины строки есть метод size(), применяемый к строке. Он возвращает целое число - количество символов в строке. Его можно использовать так:
Код: выделить все
string str;
cin >> str;
cout << "Вы ввели слово " << str << " в котором " << str.size()
     << " символов" << endl;

Конкатенация строк
Основная операция над строками - сложение: например, при сложении строк "Hello, " и "world!" получится строка "Hello, world!". Такая операция над строками называется конкатенацией.
Для конкатенации строк используется оператор “+”. То есть, так же как и для сложения целых чисел.

Но применить этот оператор можно только к объекту класса string. Если говорить более точно, то хотя бы одно из слагаемых должно быть объектом класса string, второе слагаемое может быть массивом символов. То есть применить его для сложения двух массивов символов не получиться.
Следующий код компилироваться не будет:
Код: выделить все
string str = "asd" + "qwe";


Его можно записать следующим образом:
string str = "asd";
str += “qwe”;


Изменение размера строк
Другая операция - изменение размера строки. Для этого существует метод resize, который применяется к строке. У метода resize есть две формы записи: с одним и с двумя параметрами. Если он вызывается с одним параметром, то этот параметр задает новую длину строки. Например, так:
Код: выделить все
string str = "abcdefg"
str.resize(3);
cout << str << endl; // Будет выведено abc


Второй параметр метода resize задает символ, которым будут заполнены символы в строке, если размер строки увеличивается в результате изменения размера. Например:
Код: выделить все
string str = "abc"
str.resize(6,'d');
cout << str << endl; // Будет выведено abcddd

Если же при увеличении строки с помощью функции resize не указать символ для заполнения, то строка будет заполнена нуль-терминаторами, которые на экран выводиться не будут.
Стоит отметить, что при конкатенации размер строки увеличивается автоматически.
Код: выделить все
То есть, следующий код:
string str = "asd";
cout << "Size:" << str.size() << endl;

str += "qwe";
cout << "Size:" << str.size() << endl;


Выведет на экран:
Size:3
Size:6

Считывание строк
При считывании строк из входного потока считываются все символы, кроме символов–разделителей (пробелов, табуляций и новых строк), которые являются границами между строками. Например, если при выполнении следующей программы
Код: выделить все
string str1, str2, str3; // объявили 3 строки
cin >> str1 >> str2 >> str3;

ввести текст “Mom soap frame” (с произвольным количеством пробелов между словами), то в массив str1 будет записана строка "Mom", в str2 — "soap", в str3 — "frame".
Таким образом, организовать считывание всего файла по словам, можно следующим образом:
Код: выделить все
string str;
while (cin >> str) { // Цикл пока считывание успешно
    ...              // Делаем необходимые действия
}


Если нужно считать строку со всеми пробелами, то необходимо использовать функцию getline следующим образом:
Код: выделить все
string strLine;
getline(cin, strLine);


В данном случае если запустить эту программу и ввести строку "Mom soap frame", то именно это значение и будет присвоено строке strLine. Считать же весь входной поток по строкам можно при помощи следующего кода:
Код: выделить все
string strLine;
while (getline(cin, strLine)) { // Цикл пока считывание успешно
    ...                         // Делаем необходимые действия
}


Стоит отметить, что вместо объекта cin, в функцию getline можно передавать и объект класса fstream , то есть файл, открытый на чтение. И в этом случае считывание будет производиться из открытого файла.
EgorovAD MEPhI
Администратор
 
Сообщений: 155
Зарегистрирован: 04 ноя 2011, 11:49

Re: Необходимый материал

Сообщение EgorovAD MEPhI » 18 ноя 2013, 08:14

Передача строк в библиотечные функции
Многие стандартные функции принимают строки в виде массива символов, а не в виде объекта класса string. В них массив символов обозначается как “char *str”. Ключевой символ – “*”(звёздочка).
Для использования передачи в функции необходимо подключить заголовочный файл
Код: выделить все
#include <cstring>

Для того чтобы передать в такую функцию строку, хранящуюся в объекте класса string, необходимо преобразовать объект класса string в массив символов, для этого существует функция c_str(). Которая возвращает “ссылку” на массив символов.
Пример:
Код: выделить все
string path = "/path/to/file.txt";
fstream fIn(path.c_str());


Методы для работы со строками
• s.append(str) – добавляет в конец строки строку str. Можно писать как s.append(переменная), так и s.append("строка");
• s.assign(str) – присваивает строке s значение строки str. Аналогично записи s = str;
• int i = s.begin()– записывает в i индекс первого элемента строки
• int i = s.end()– аналогично, но последнего
• s.clear() – как следует из названия, отчищает строку. Т.е. удаляет все элементы в ней
• s.compare(str) – сравнивает строку s со строкой str и возвращает 0 в случае совпадение (на самом деле сравнивает коды символов и возвращает из разность)
• s.copy(куда, сколько, начиная с какого) - копирует из строки s в куда (там может быть как строка типа string, так и строка типа char). Последние 2 параметра не обязательные (можно использовать функцию с 1,2 или 3 параметрами)
• bool b = s.empty() – если строка пуста, возвращает true, иначе false
• s.erase(откуда, сколько) удаляет n элементов с заданной позиции
• s.find(str,позиция) – ищет строку str начиная с заданной позиции
• s.insert(позиция,str, начиная, beg, count) - вставляет в строку s начиная с заданной позиции часть строки str начиная с позиции beg и вставляя count символов
• int len = s.length() – записывает в len длинну строки
• s.push_back(symbol) – добавляет в конец строки символ
• s.replace(index, n,str) – берет n первых символов из str и заменяет символы строки s на них, начиная с позиции index
• str = s.substr(n,m) – возвращает m символов начиная с позиции n
• s.swap(str) – меняет содержимое s и str местами.
• s.size()– возвращает число элементов в строке.

Сравнение строк
Строки необходимо сравнивать с помощью специальных методов. Сравнение строк в этих методах происходит в лексикографическом порядке.
Лексикографический порядок — отношение линейного порядка на множестве слов длины n над некоторым упорядоченным алфавитом A. Своё название лексикографический порядок получил по аналогии с сортировкой по алфавиту в словаре.
Слово a предшествует слову b (a<b), если первые m символов слов совпадают, а m+1 символ слова a меньше (относительно отношения порядка, заданного в A) m+1 символа слова b.
Предполагается, что буквы можно сравнивать, сравнивая их номера в алфавите. Тогда лексикографический порядок — это, например, А < АА < ААА < ААБ < ААВ < АБ < Б < … < ЯЯЯ.
EgorovAD MEPhI
Администратор
 
Сообщений: 155
Зарегистрирован: 04 ноя 2011, 11:49


Вернуться в Тема 7. Символы и строки

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0