Обработка строк
В языке C++ существуют два вида строковых переменных. Начнем с того, который достался языку C++ в наследство от C. Этот способ работы со строками гораздо быстрее, но значительно менее удобен.
Объявление переменной
В языке C строка — это просто указатель на первый символ этой строки. Для того, чтобы данную строку можно
было обрабатывать при помощи библиотечных функций, она должна заканчиваться нулевым байтом, т. е. символом
с кодом 0.
Объявить строковую переменную в таком стиле можно двумя способами:
а) как указатель:
char *s;
В этом случае программист сам должен заботиться о выделении памяти под символы, составляющие строку.
Например, можно сделать это так:
s = new char[число_символов_строки+1];
Здесь +1 нужен для хранения завершающего строку нулевого символа. При использовании динамических массивов
нужно заботиться о своевременном их освобождении операцией delete.
Однако, такую переменную можно инициализировать строковой константой:
char *s = "текст_строки";
Такая возможность существует благодаря тому, что в C++ строковая константа — это просто указатель на первый
символ строки, заключенной в кавычки (завершающий нулевой символ добавляется автоматически компилятором).
Однако, обычно строковые константы хранятся в той части памяти, куда нельзя ничего записывать, так что у так
определенной строки нельзя менять входящие в ее состав символы. Если же мы хотим, чтобы содержимое строки
могло меняться, нужно пользоваться массивами (динамическими или обычными).
б) как массив:
char s[максимальное_число_символов+1];
Здесь память выделяется автоматически компилятором, и символы такой строки можно менять, но если этот массив — локальная переменная, то надо быть готовым к тому, что он исчезнет по окончании работы содержащей его функции. В частности, такие строки нельзя возвращать из той функции, в которой они определены (для этого нужно пользоваться динамическими массивами).
Такая строка тоже может быть инициализирована, как традиционным для массивов образом (в этом случае завершающий символ с кодом 0 надо писать явно)
char s[число] = { ’H’, ’e’, ’l’, ’l’, ’o’, ’\0’ };
так и в сокращенной записи (завершающий нулевой символ добавляется автоматически компилятором)
char s[число] = "Hello";
Как и в случае массивов, указанное в квадратных скобках число элементов должно быть достаточным для записи всех символов строки, включая завершающий символ с кодом 0. Если мы хотим, чтобы размер массива совпадал с числом символов той строковой константы, которая в него записывается (включая завершающий 0), то число в квадратных скобках можно опустить:
char s[] = "Hello";
Типы символов
В этом примере будет определен массив из шести символов.
Заголовочный файл cctype содержит набор весьма удобных макроопределений для проверки символа на принадлежность определенному классу.
Например, если c — символьная переменная, то условие isspace(c) будет истинно,
если c — пробельный символ. Таких макроопределений достаточно много, можно упомянуть несколько самых востребованных: isdigit — цифра и isalpha — латинская буква.
Здесь будет уместно следующее замечание: все эти макроопределения в случае, если ответ — ложь, возвращают
0, но если ответ — истина, они возвращают не 1, как можно было бы ожидать, а некоторое ненулевое число. Так что
вариант
if(isspace(c)) ...
будет работать, а вот такой код
if(isspace(c)==true) ...
— скорее всего, нет.
Доступ к отдельному символу
Как и для любого массива, доступ к символу из строки s по индексу (начинается с 0) выглядит как s[индекс].
Операции над строками
Для того, чтобы пользоваться библиотечными функциями для работы со строками, нужно подключить файл
cstring.
а) длина строки s дается функцией strlen(s)
б) к сожалению, строки в стиле C нельзя ни присваивать, ни сравнивать при помощи обычных операций сравнения.
Для копирования строк существует функция strcpy, принимающая два указателя на символы dest и src, и копирующая
строку, на которую указывает src, в область памяти, на которую указывает dest. Завершающий символ с кодом 0 тоже
копируется этой функцией автоматически.
Например, если нужно записать строку "Hello"в массив символов s, нужно написать
strcpy(s, "Hello");
Здесь нужно сделать два замечания. Во-первых, две строки, которыми оперирует strcpy, не должны перекрываться в памяти. Например, такая попытка сдвинуть строку, удалив ее первый символ, незаконна:
strcpy(s, s+1);
Во-вторых, вся ответственность за то, чтобы в строке dest хватило памяти для записи строки src, всецело лежит на программисте. Иногда такие ошибки ловит операционная система, но возможен и худший вариант, когда программа молча выдает неверный ответ. Для надежности в этом плане существует функция strncpy, имеющая дополнительный параметр (он идет последним), определяющий число копируемых символов. Если строка src короче, оставшиеся до указанного числа символы заполняются нулями, но если она длиннее, то завершающий нулевой символ не пишется.
в) для сравнения строк используется функция strcmp. Ее параметрами будут сравниваемые строки, и она возвращает 0, если строки совпадают, отрицательное число, если первая строка меньше, и положительное, если она больше. Так что для проверки равенства двух строк a и b нужно написать
strcmp(a, b)==0
а никак не a==b
По аналогии с strcpy, существует также вариант strncmp, сравнивающий только определенное количество начальных символов.
г) имеется также функция strcat с двумя строками-параметрами, приписывающая к строке, заданной первым параметром, строку, заданную вторым. Как и в случае strcpy, строки-параметры не должны перекрываться, и наличие достаточного количества памяти для приписывания — забота программиста. Имеется и вариант strncat; в отличие от strncpy, нулевой завершающий символ приписывается к результату всегда, и если вторая строка короче указанного числа символов, копируются только символы до завершающего включительно.
д) превращение строки s в целое число дается выражением atoi(s), в вещественное — atof(s). Обе эти функции объявлены в файле cstdlib. К сожалению, для обратного превращения числа в строку отдельных библиотечных функций нет, и нужно пользоваться строковыми потоками.
е) ввод строки s c клавиатуры выполняется вызовом cin»s. При таком способе чтения строки все пробельные символы считаются разделителями, так что строка читается до первого пробела. Кроме того, переполнение строки никак не проверяется. Чтобы оно проверялось, надо написать
cin>>setw(число)>>s
В этом случае число-1 определяет максимальное количество считанных символов (-1 потому, что нужно записать
еще завершающий нулевой символ, так что в качестве параметра должен быть указан размер массива, содержащего
строку). Манипулятор setw объявлен в файле iomanip.
Считать строку до символа перевода строки (в том числе с пробелами) можно при помощи метода getline:
cin.getline(s, размер_массива)
Здесь важно сделать одно замечание: код
int x; char s[100];
cin>>x;
cin.getline(s, 100);
скорее всего, работать не будет. Если после ввода числа пользователь нажимает клавишу «ввод», то после чтения
числа символ перевода строки остается в потоке cin, и метод getline читает пустую строку.
Это можно исправить при
помощи манипулятора ws (пропуск пробельных символов):
int x; char s[100];
cin>>x>>ws;
cin.getline(s, 100);
Правда, при этом будут также пропущены все пробельные символы в начале той строки, которую мы собираемся считывать, а если пользователь введет пустую строку (а еще хуже несколько), начнется хаос.
ж) для выделения подстроки следует использовать функцию strncpy со сдвинутым указателем src. Например, выделить в массив dest подстроку строки src, начиная с символа с индексом 5 из 20 символов, можно так:
strncpy(dest, src+5, 20); dest[20] = 0;
з) найти первое вхождение символа c в строку s можно, написав
strchr(s, c)
Функция strchr возвращает указатель на первое вхождение символа в строку, или nullptr, если символ не входит в строку. Аналогично, найти последнее вхождение можно при помощи функции strrchr.
и) найти указатель на первый символ первого вхождения строки s1 в строку s2 можно при помощи вызова strstr(s2, s1). Этот вызов имеет значение nullptr, если вхождений нет
string (C++)
Кроме простых указателей на символы или массивов символов, в C++ есть также библиотечный класс string для хранения строк. Он медленнее работает, но предоставляет значительно больше удобств для работы со строками. Например, в строках C++ нет явного признака конца строки, как в C, так что символ с кодом 0 вполне может встречаться в строках типа string. Чтобы пользоваться этим типом, нужно включить в свою программу заголовочный файл string:
#include <string>
string — класс с методами и переменными для организации работы со строками в языке программирования C++. Он включён в стандартную библиотеку C++. Название образовано от имени строчного типа данных (англ. string; с англ. — «строка»). В языке C++ и его предшественнике, языке программирования Си, нет встроенной поддержки строкового типа данных, вместо этого используется массив символов. string управляет строками, как и string.h в Си. string использует единственный объект string для организации работы со строками. Являясь частью стандартной библиотеки C++, эти объекты также являются частью стандартного пространства имён — std.
#include <iostream>
#include <string> // в Си: #include <string.h>
int main()
{
std::string str = "Hello, world!";
std::cout << str << std::endl; // в Си: puts(str);
return 0;
}
Строковые и символьные функции
Библиотека функций языков С и C++ включает богатый набор функций обработки строк и символов. Строковые функции работают с символьными массивами, завершающимися нулевыми символами. В языке С для использования строковых функций необходимо включить в начало модуля программы заголовочный файл <string.h>, а для символьных — заголовочный файл <ctype.h>. В языке C++ для работы со строковыми и символьными функциями используются заголовки <cstring> и <cctype.h> соответственно. В этой главе для простоты изложения используются имена С-заголовков.
Поскольку в языках С и C++ при выполнении операций с массивами не предусмотрен автоматический контроль нарушения их границ, вся ответственность за переполнение массивов ложится на плечи программиста. Пренебрежение этими тонкостями может привести программу к аварийному отказу.
В языках С и C++ печатаемыми являются символы, отображаемые на терминале. В ASCII-средах они расположены между пробелом(0x20) и тильдой(OxFE). Управляющие символы имеют значения, лежащие в диапазоне между нулем и Ox1F; к ним также относится символ DEL(Ox7F).
Исторически сложилось так, что аргументами символьных функций являются целые значения, из которых используется только младший байт. Символьные функции автоматически преобразуют свои аргументы в тип unsigned char. Безусловно, вы вольны вызывать эти функции с символьными аргументами, поскольку символы автоматически возводятся в ранг целых в момент вызова функции.
В заголовке <string.h> определен тип size_t, который является результатом применения оператора sizeof и представляет собой разновидность целого без знака.
В версии С99 к некоторым параметрам нескольких функций, первоначально определенных в версии С89, добавлен квалификатор restrict. При рассмотрении каждой такой функции будет приведен ее прототип, используемый в среде С89(а также в среде C++), а параметры с атрибутом restrict будут отмечены в описании этой функции.
Список функций
Проверка на принадлежность
isalnum — Проверка на принадлежность символа к алфавитно-цифровым
isalpha — Проверка на принадлежность символа к буквам
isblank — Проверка пустого символа
iscntrl — Проверка на принадлежность символа к управляющим
isdigit — Проверка на принадлежность символа к цифровым
isgraph — Проверка на принадлежность символа к печатным но не к пробелу
islower — Проверка на принадлежность символа к строчным
isprint — Проверка на принадлежность символа к печатным
ispunct — Проверка на принадлежность символа к знакам пунктуации
isspace — Проверка на принадлежность символа к пробельным
isupper — Проверка на принадлежность символа к прописным
isxdigit — Проверка на принадлежность символа к шестнадцатеричным
Работа с символьными массивами
memchr — Просматривает массив чтобы отыскать первое вхождение символа
memcmp — Сравнивает определённое количество символов в двух массивах
memcpy — Копирует символы из одного массива в другой
memmove — Копирует символы из одного массива в другой с учётом перекрытия массивов
memset — Заполняет определённое количество символов массива заданным
Манипуляции над строками
strcat — Присоединяет копию одной строки к заданной
strchr — Возвращает указатель на первое вхождение младшего байта заданного параметра
strcmp — Сравнивает в лексикографическом порядке две строки
strcoll — Сравнивает одну строку с другой в соответствии с параметром setlocale
strcpy — Копирует содержимое одной строки в другую
strcspn — Возвращает строку в которой отсутствуют заданные символы
strerror — Возвращает указатель на строку содержащую системное сообщение об ошибке
strlen — Возвращает длину строки с завершающим нулевым символом
strncat — Присоединяет определённое количество символов одной строки к другой
strncmp — Лексикографически сравнивает две строки
strncpy — Копирует определённое количество символов в символьный массив
strpbrk — Возвращает указатель на первый символ в строке который совпадает с заданными
strrchr — Возвращает указатель на последнее вхождение младшего байта заданного параметра в строке
strspn — Возвращает индекс первого символа в заданной строке, который не совпадает с любым из символов в другой строке
strstr — Возвращает указатель на первое вхождение одной строки в другую
strtok — Возвращает указатель на следующую лексему в строке
strxfrm — Преобразует определённое количество символов заданной строки чтобы ее можно было использовать функцией strcmp()
Другие функции
tolower — Переводит символ в нижний регистр
toupper — Переводит символ в верхний регистр
Не много примеров string
#include <iostream>
#include <string>
using namespace std;
int main() {
string S;
cout << "Введите строку:";
getline(cin, S);
size_t s = S.find(' ');
size_t e = S.rfind(' ');
string subS1 = S.substr(0, s);
string subS2 = S.substr(e + 1, string::npos);
S.replace(0, subS1.size(), subS2);
e = S.rfind(' ');
S.replace(e + 1, subS2.size(), subS1);
cout << S << endl;
return 0;
}
Рассмотрим пример. Дана строка S1. Эта строка делится пополам. Первая половина строки помещается в строку S2, а вторая – в строку S3. Заменить исходную строку на строку, состоящую из 20 символов '*'. Вывести строки S1, S2 и S3. Изменить строки S1 и S2 так, чтобы первые семь символов строки S2 и последние семь символов строки S3 были заменены на символы строки S1. Вывести модифицированные строки S2 и S3.
#include <iostream>
#include <string>
using namespace std;
int main() {
string S1("The C++ programming language has support for string handling, "
"mostly implemented in its standard library."
);
auto first = S1.cbegin();
auto last = S1.cend();
// Используем итераторы
string S2(first, last - S1.size() / 2);
string S3(first + S1.size() / 2, last);
cout << "S1 => " << S1 << endl;
S1.assign(20, '*');
cout << "S2 => " << S2 << "\n"
<< "S3 => " << S3 << "\n"
<< "S1 => " << S1 << endl;
// Используем диапазоны
S2.replace(0, 7, S1);
S3.replace(S3.size() - 7, 7, S1);
cout << "S2 => " << S2 << "\n"
<< "S3 => " << S3 << endl;
return 0;
}
Подробно о классе STRING
#include <string>
Не путайте с подключением Си-совместимой библиотеки для работы со строками char *:
#include <string.h>
или
#include <cstring>
Для работы со строками также нужно подключить стандартный namespace:
using namespace std;
В противном случае придётся везде указывать описатель класса std::string вместо string.
Ниже приводится пример программы, работающей со string (в старых си-совместимых компиляторах не работает!):
#include <iostream>
#include <string>
#include <malloc.h>
using namespace std;
int main () {
string s = "Test";
s.insert (1,"!");
cout << s.c_str() << endl;
string *s2 = new string("Hello");
s2->erase(s2->end());
cout << s2->c_str();
cin.get(); return 0;
}
Основные возможности, которыми обладает класс string:
инициализация массивом символов (строкой встроенного типа) или другим объектом типа string. Встроенный тип не обладает второй возможностью;
копирование одной строки в другую. Для встроенного типа приходится использовать функцию strcpy();
доступ к отдельным символам строки для чтения и записи. Во встроенном массиве для этого применяется операция взятия индекса или косвенная адресация с помощью указателя;
сравнение двух строк на равенство. Для встроенного типа используются функции семейства strcmp();
конкатенация (сцепление) двух строк, дающая результат либо как третью строку, либо вместо одной из исходных. Для встроенного типа применяется функция strcat(), однако чтобы получить результат в новой строке, необходимо последовательно задействовать функции strcpy() и strcat(), а также позаботиться о выделении памяти;
встроенные средства определения длины строки (функции-члены класса size() и length()). Узнать длину строки встроенного типа можно только вычислением с помощью функции strlen();
возможность узнать, пуста ли строка.
Рассмотрим эти базовые возможности более подробно.
Инициализация строк при описании и длина строки (не включая завершающий нуль-терминатор):
string st( "Моя строка\n" );
cout << "Длина " << st << ": " << st.size()
<< " символов, включая символ новой строки\n";
Строка может быть задана и пустой:
string st2;
Для проверки того, пуста ли строка, можно сравнить ее длину с 0:
if ( ! st.size() ) // пустая
или применить метод empty(), возвращающий true для пустой строки и false для непустой:
if ( st.empty() ) // пустая
Третья форма создания строки инициализирует объект типа string другим объектом того же типа:
string st3( st );
Строка st3 инициализируется строкой st. Как мы можем убедиться, что эти строки совпадают? Воспользуемся оператором сравнения (==):
if ( st == st3 ) // инициализация сработала
Как скопировать одну строку в другую? С помощью обычной операции присваивания:
st2 = st3; // копируем st3 в st2
Для сцепления строк используется операция сложения (+) или операция сложения с присваиванием (+=). Пусть даны две строки:
string s1( "hello, " );
string s2( "world\n" );
Мы можем получить третью строку, состоящую из конкатенации первых двух, таким образом:
string s3 = s1 + s2;
Если же мы хотим добавить s2 в конец s1, мы должны написать:
s1 += s2;
Операция сложения может сцеплять объекты класса string не только между собой, но и со строками встроенного типа. Можно переписать пример, приведенный выше, так, чтобы специальные символы и знаки препинания представлялись встроенным типом char *, а значимые слова – объектами класса string:
const char *pc = ", ";
string s1( "hello" );
string s2( "world" );
string s3 = s1 + pc + s2 + "\n";
cout << endl << s3;
Подобные выражения работают потому, что компилятор "знает", как автоматически преобразовывать объекты встроенного типа в объекты класса string. Возможно и простое присваивание встроенной строки объекту string:
string s1;
const char *pc = "a character array";
s1 = pc; // правильно
Обратное преобразование при этом не работает. Попытка выполнить следующую инициализацию строки встроенного типа вызовет ошибку компиляции:
char *str = s1; // ошибка компиляции
Чтобы осуществить такое преобразование, необходимо явно вызвать функцию-член с названием c_str() ("строка Си"):
const char *str = s1.c_str();
Функция c_str() возвращает указатель на символьный массив, содержащий строку объекта string в том виде, в каком она находилась бы во встроенном строковом типе. Ключевое слово const здесь предотвращает "опасную" в современных визуальных средах возможность непосредственной модификации содержимого объекта через указатель.
К отдельным символам объекта типа string, как и встроенного типа, можно обращаться с помощью операции взятия индекса. Вот, например, фрагмент кода, заменяющего все точки символами подчеркивания:
string str( "www.disney.com" );
int size = str.size();
for ( int i = 0; i < size; i++ )
if ( str[i] == '.' ) str[ i ] = '_';
cout << str;
Но лучше читать документацию по C++ и пользоваться его возможностями. Например, предыдущее действие мы могли бы выполнить вызовом одной-единственной функции replace():
replace( str.begin(), str.end(), '.', '_' );
Правда, здесь использован не метод replace класса string, а одноимённый алгоритм:
#include <algorithm>
Поскольку объект string ведет себя как контейнер, к нему могут применяться и другие алгоритмы. Это позволяет решать задачи, не решаемые напрямую функциями класса string.
Ниже приводится краткое описание основных операторов и функций класса string, ссылки в таблице ведут к русскоязычным описаниям в интернете. Более полный список возможностей класса string можно получить, например, в Википедии или на сайте cplusplus.com.
Задание символов в строке
operator=
присваивает значения строке
assign
назначает символы строке
Доступ к отдельным символам
at
получение указанного символа с проверкой выхода индекса за границы
operator[]
получение указанного символа
front
получение первого символа
back
получение последнего символа
data
возвращает указатель на первый символ строки
c_str
возвращает немодифицируемый массив символов С, содержащий символы строки
Проверка на вместимость строки
empty
проверяет, является ли строка пустой
size
length
возвращает количество символов в строке
max_size
возвращает максимальное количество символов
reserve
резервирует место под хранение
Операции над строкой
clear
очищает содержимое строки
insert
вставка символов
erase
удаление символов
push_back
добавление символа в конец строки
pop_back
удаляет последний символ
append
добавляет символы в конец строки
operator+=
добавляет символы в конец строки
compare
сравнивает две строки
replace
заменяет каждое вхождение указанного символа
substr
возвращает подстроку
copy
копирует символы
resize
изменяет количество хранимых символов
swap
обменивает содержимое
Поиск в строке
find
поиск символов в строке
rfind
поиск последнего вхождения подстроки
find_first_of
поиск первого вхождения символов
find_first_not_of
найти первое вхождение отсутствия символов
find_last_of
найти последнее вхождение символов
find_last_not_of
найти последнее вхождение отсутствия символов
Следует обратить внимание, что у любой функции класса string может быть несколько перегрузок - разновидностей с одинаковыми именами, отличающихся между собой списками и типами аргументов.
В качестве недостатков класса string можно отметить следующее:
отсутствие в классе встроенных средств для разбора строк по набору разделителей (аналога функции strtok для строк char *);
возможное замедление быстродействия по отношению к char * при сложной обработке данных.
Ниже приведён код для разбора введённой с клавиатуры строки string на слова. Можно доработать этот код, исключив знаки препинания, стоящие последними символами строк vecstr[i], а также слова, не содержащие ни одного алфавитно-цифрового символа.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main() {
cout << "Enter the string: ";
string str;
getline(cin, str);
vector <string> vecstr;
string word;
stringstream s(str);
while (s >> word) vecstr.push_back(word);
int vsize = vecstr.size();
for (int i = 0; i < vsize; i++)
cout << vecstr[i] << endl;
cin.get();
return 0;
}
Пример своего класса STRING Что такое Class OOP C++ Читайте в разделе -> Выбор темы <-
#ifndef STRING_H
#define STRING_H
#include <iostream>
namespace STD
{
int StrLen(char*);
void StrCpy(char*, char*);
bool StrCmp(char*, char*);
class String
{
public:
String(char* _str = "");
String(const String&);
~String();
String& operator=(const String&);
friend String operator+(const String&, const String&);
String& operator+=(const String&);
friend bool operator==(const String&, const String&);
friend bool operator!=(const String&, const String&);
friend bool operator>(const String&, const String&);
friend bool operator>=(const String&, const String&);
friend bool operator<(const String&, const String&);
friend bool operator<=(const String&, const String&);
const char& operator[](int) const;
char& operator[](int);
friend std::ostream& operator<<(std::ostream&, const String&);
friend std::istream& operator>>(std::istream&, String&);
private:
char* str;
};
String::String(char* _str)
{
str = new char[StrLen(_str)+1];
StrCpy(str, _str);
}
String::String(const String& rhs)
{
str = new char[StrLen(rhs.str)+1];
StrCpy(str, rhs.str);
}
String::~String()
{
delete str;
}
// ---
String& String::operator=(const String& rhs)
{
if (this != &rhs)
{
delete[] this->str;
this->str = new char[StrLen(rhs.str)+1];
StrCpy(this->str, rhs.str);
}
return *this;
}
String& String::operator+=(const String& rhs)
{
int sz = StrLen(this->str) + StrLen(rhs.str);
char* ts = new char[sz+1];
for (int i = 0; i < StrLen(this->str); i++)
ts[i] = this->str[i];
for (int ii = StrLen(this->str), j = 0; ii <= sz; ii++, j++)
ts[ii] = rhs.str[j];
delete this->str;
this->str = ts;
return *this;
}
String operator+(const String& lhs, const String& rhs)
{
String ts = lhs;
return ts += rhs;
}
// --
bool operator==(const String& lhs, const String& rhs)
{
return StrCmp(lhs.str, rhs.str);
}
bool operator!=(const String& lhs, const String& rhs)
{
return !(StrCmp(lhs.str, rhs.str));
}
bool operator>(const String& lhs, const String& rhs)
{
return (StrLen(lhs.str) > StrLen(rhs.str)) ? true : false;
}
bool operator>=(const String& lhs, const String& rhs)
{
return (StrLen(lhs.str) >= StrLen(rhs.str)) ? true : false;
}
bool operator<(const String& lhs, const String& rhs)
{
return (StrLen(lhs.str) < StrLen(rhs.str)) ? true : false;
}
bool operator<=(const String& lhs, const String& rhs)
{
return (StrLen(lhs.str) <= StrLen(rhs.str)) ? true : false;
}
// ---
const char& String::operator[](int i) const
{
//std::cerr << "Index out of range. \n";
return (i >= 0 && i < StrLen(this->str)) ? this->str[i] : 0;
}
char& String::operator[](int i)
{
static char DUMMY; DUMMY = '';
//std::cerr << "Index out of range. \n";
return (i >= 0 && i < StrLen(this->str)) ? this->str[i] : DUMMY;
}
// ---
std::ostream& operator<<(std::ostream& os, const String& obj)
{
return os << obj.str;
}
std::istream& operator>>(std::istream& is, String& obj)
{
char BUFF[2048];
is.getline(BUFF, sizeof BUFF);
obj = BUFF;
return is;
}
// ---
int StrLen(char* _str)
{
int size = 0;
for (; _str[size] != 0; size++);
return size;
}
void StrCpy(char* in_str, char* src_str)
{
for (int i = 0; i < StrLen(in_str); i++)
in_str[i] = src_str[i];
}
bool StrCmp(char* str_f, char* str_s)
{
int i = 0;
for (; str_f[i] == str_s[i] && i < StrLen(str_f); i++);
return (i == StrLen(str_f)) ? true : false;
}
}
#endif
Таблица ASCII