0 / 0 / 0 Регистрация: 24.01.2020 Сообщений: 4 |
|
1 |
|
Найти союзы в строке27.10.2021, 19:01. Показов 615. Ответов 4
Помогите пожалуйста с решением на С++.
0 |
5109 / 4548 / 854 Регистрация: 07.10.2015 Сообщений: 9,461 |
|
27.10.2021, 20:48 |
2 |
moreng, покажите свой код
0 |
0 / 0 / 0 Регистрация: 24.01.2020 Сообщений: 4 |
|
27.10.2021, 20:55 [ТС] |
3 |
не работает.docx
0 |
5109 / 4548 / 854 Регистрация: 07.10.2015 Сообщений: 9,461 |
|
27.10.2021, 20:56 |
4 |
moreng, скопируйте прямо сюда!
0 |
moreng 0 / 0 / 0 Регистрация: 24.01.2020 Сообщений: 4 |
||||
27.10.2021, 21:00 [ТС] |
5 |
|||
0 |
В переменную s
из файла считываются строки. Как из этих строк извлечь и записать в другую строчную переменную ,например, все словосочетания, которые содержат: «user: (какое-то имя),». Имя состоит из одного слова, словосочетание ограничивается запятой ,
.
Код:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string s;
ifstream file("file1");
int count = 1;
while (getline(file, s)) {
cout << "String " << "#" << count << ": " << s << endl;
count++;
}
file.close();
system("pause");
return 0;
}
задан 3 июн 2018 в 7:09
3
Немного изменений в цикле, и получим решение:
while (getline(file, s, ',')) {
size_t pos = s.find("user");
if (pos == string::npos)
continue;
s.erase(s.begin(), s.begin() + pos);
cout << "String " << "#" << count << ": " << s << endl;
count++;
}
если конечно после всех имен точно есть символ ограничитель ‘,’. Иначе код немного станет больше или используется другой альгоритм
ответ дан 3 июн 2018 в 8:00
AR HovsepyanAR Hovsepyan
15.8k3 золотых знака13 серебряных знаков30 бронзовых знаков
1
I was trying to remove conjunctions and punctuations from a txt file. Punctuations are removed successfully but some conjunctions remained. Here is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string words = File.ReadAllText(@"C:Users...Desktopdata_protection_law.txt").ToLower(new CultureInfo("en-US", false));
string[] punctuation = { ".", "!", "?", "–", "-", "-", "/", "_", ",", ";", ":", "(", ")", "[", "]", "“", "”", """, "1", "2", "3", "4", "5", "6", "7", "8", "9" };
string[] con_art = { "the", "a", "an", "for", "and", "or", "nor", "but", "yet", "so", "of", "to", "in", "are", "is", "on", "be", "by", "we", "he", "that", "he", "that", "because", "as", "it", "about", "were", "i", "our", "they", "with", "these", "there", "then", "them" };
foreach (string s in punctuation)
{
words = words.Replace(s, "");
}
foreach (string s in con_art)
{
words = words.Replace(" " + s + " ", " ");
}
richTextBox1.Text = words;
}
}
I printed the words in richTextBox just to be sure. When I checked the original text, I found that some conjunctions were deleted but not all.
Here is the proof of the remaining conjunctions
Original Text File
I’m going crazy, I’ve been trying to find the mistake myself for days, but I couldn’t find it.
So where is my mistake in this code?
Btw I’m just a beginner so don’t be angry if I made a big mistake
Вступление
Строки — это объекты, которые представляют последовательности символов. Стандартный класс string
обеспечивает простую, безопасную и универсальную альтернативу использованию явных массивов char
при работе с текстом и другими последовательностями символов. string
класс C ++ является частью пространства имен std
и стандартизован в 1998 году.
Синтаксис
-
// Пустое объявление строки
std :: string s;
-
// Построение из const char * (c-string)
std :: string s («Hello»);
std :: string s = «Hello»;
-
// Построение с использованием конструктора копирования
std :: string s1 («Hello»);
std :: string s2 (s1);
-
// Построение из подстроки
std :: string s1 («Hello»);
std :: string s2 (s1, 0, 4); // Копировать 4 символа из позиции 0 из s1 в s2
-
// Построение из буфера символов
std :: string s1 («Hello World»);
std :: string s2 (s1, 5); // Скопируем первые 5 символов s1 в s2 -
// Создаем конструктор заполнения (только char)
std :: string s (5, ‘a’); // s содержит aaaaa
-
// Конструкция с использованием конструктора диапазонов и итератора
std :: string s1 («Hello World»);
std :: string s2 (s1.begin (), s1.begin () + 5); // Скопируем первые 5 символов s1 в s2
замечания
Прежде чем использовать std::string
, вы должны включить string
заголовка, так как она включает в себя функции / операторы / перегрузки, которые не включают другие заголовки (например, iostream
).
Использование конструктора const char * с nullptr приводит к неопределенному поведению.
std::string oops(nullptr);
std::cout << oops << "n";
Метод at
std::out_of_range
если index >= size()
.
Поведение operator[]
немного сложнее, во всех случаях оно имеет неопределенное поведение, если index > size()
, но когда index == size()
:
C ++ 11
- В строке non-const поведение не определено ;
- В строке
CharT()
ссылка на символ со значениемCharT()
( нулевой символ).
C ++ 11
-
CharT()
ссылка на символ со значениемCharT()
( нулевой символ). - Изменение этой ссылки — неопределенное поведение .
Начиная с C ++ 14 вместо использования "foo"
рекомендуется использовать "foo"s
, так как s
— это определяемый пользователем буквенный суффикс , который преобразует const char*
"foo"
в std::string
"foo"
,
Примечание: Вы должны использовать пространство имен std::string_literals
или std::literals
, чтобы получить буквенные s
.
расщепляющий
Используйте std::string::substr
чтобы разделить строку. Существует два варианта этой функции-члена.
Первый принимает начальную позицию, из которой должна начинаться возвращаемая подстрока. Начальная позиция должна быть действительной в диапазоне (0, str.length()]
:
std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(11); // "bar and world!"
Второй занимает начальную позицию и общую длину новой подстроки. Независимо от длины , подстрока никогда не пройдет мимо конца строки источника:
std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(15, 3); // "and"
Обратите внимание, что вы также можете вызывать substr
без аргументов, в этом случае возвращается точная копия строки
std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(); // "Hello foo, bar and world!"
Сменная замена
Заменить по положению
Чтобы заменить часть std::string
вы можете использовать метод replace
из std::string
.
replace
есть много полезных перегрузок:
//Define string
std::string str = "Hello foo, bar and world!";
std::string alternate = "Hello foobar";
//1)
str.replace(6, 3, "bar"); //"Hello bar, bar and world!"
//2)
str.replace(str.begin() + 6, str.end(), "nobody!"); //"Hello nobody!"
//3)
str.replace(19, 5, alternate, 6, 6); //"Hello foo, bar and foobar!"
C ++ 14
//4)
str.replace(19, 5, alternate, 6); //"Hello foo, bar and foobar!"
//5)
str.replace(str.begin(), str.begin() + 5, str.begin() + 6, str.begin() + 9);
//"foo foo, bar and world!"
//6)
str.replace(0, 5, 3, 'z'); //"zzz foo, bar and world!"
//7)
str.replace(str.begin() + 6, str.begin() + 9, 3, 'x'); //"Hello xxx, bar and world!"
C ++ 11
//8)
str.replace(str.begin(), str.begin() + 5, { 'x', 'y', 'z' }); //"xyz foo, bar and world!"
Заменить вхождения строки другой строкой
Заменить только первое вхождение replace
с with
в str
:
std::string replaceString(std::string str,
const std::string& replace,
const std::string& with){
std::size_t pos = str.find(replace);
if (pos != std::string::npos)
str.replace(pos, replace.length(), with);
return str;
}
Заменить все случаи replace
с with
на str
:
std::string replaceStringAll(std::string str,
const std::string& replace,
const std::string& with) {
if(!replace.empty()) {
std::size_t pos = 0;
while ((pos = str.find(replace, pos)) != std::string::npos) {
str.replace(pos, replace.length(), with);
pos += with.length();
}
}
return str;
}
конкатенация
Вы можете объединить std::string
s с помощью перегруженных операторов +
и +=
. Использование оператора +
:
std::string hello = "Hello";
std::string world = "world";
std::string helloworld = hello + world; // "Helloworld"
Используя оператор +=
:
std::string hello = "Hello";
std::string world = "world";
hello += world; // "Helloworld"
Вы также можете добавить строки C, включая строковые литералы:
std::string hello = "Hello";
std::string world = "world";
const char *comma = ", ";
std::string newhelloworld = hello + comma + world + "!"; // "Hello, world!"
Вы также можете использовать push_back()
для возврата отдельных char
:
std::string s = "a, b, ";
s.push_back('c'); // "a, b, c"
Существует также append()
, что в значительной степени напоминает +=
:
std::string app = "test and ";
app.append("test"); // "test and test"
Доступ к персонажу
Существует несколько способов извлечения символов из std::string
и каждый из них отличается от других.
std::string str("Hello world!");
Оператор [] (п)
Возвращает ссылку на символ с индексом n.
std::string::operator[]
не проверяется границами и не генерирует исключение. Вызывающий отвечает за утверждение, что индекс находится в пределах строки:
char c = str[6]; // 'w'
в (п)
Возвращает ссылку на символ с индексом n.
std::string::at
is bounds checked и будет std::out_of_range
если индекс не находится в пределах строки:
char c = str.at(7); // 'o'
C ++ 11
Примечание. Оба эти примера приведут к неопределенному поведению, если строка пуста.
фронт()
Возвращает ссылку на первый символ:
char c = str.front(); // 'H'
назад ()
Возвращает ссылку на последний символ:
char c = str.back(); // '!'
токенизировать
Перечислены от наименее дорогостоящих до самых дорогих во время выполнения:
-
str::strtok
— самый дешевый стандарт, предоставляемый метод токенизации, он также позволяет изменять разделитель между токенами, но он несет 3 трудности с современным C ++:-
std::strtok
нельзя использовать одновременно для несколькихstrings
(хотя некоторые реализации расширяются для поддержки этого, например:strtok_s
) - По той же причине
std::strtok
не может использоваться одновременно для нескольких потоков (это может быть определено как реализация, например: реализация Visual Studio является потокобезопасной ) - Вызов
std::strtok
изменяетstd::string
он работает, поэтому он не может использоваться дляconst string
s,const char*
s или literal string, чтобы токенизировать любой из них с помощьюstd::strtok
или работать сstd::string
, содержимое которого необходимо сохранить, нужно будет скопировать его, затем копировать можно
Как правило, любая из этих опционных затрат будет скрыта в стоимости распределения токенов, но если требуется самый дешевый алгоритм, и трудности
std::strtok
не могут быть преодолены, рассмотрите решение с ручным сжатием. -
// String to tokenize
std::string str{ "The quick brown fox" };
// Vector to store tokens
vector<std::string> tokens;
for (auto i = strtok(&str[0], " "); i != NULL; i = strtok(NULL, " "))
tokens.push_back(i);
Живой пример
-
std::istream_iterator
использует оператор извлечения потока итеративно. Если входнаяstd::string
ограничена пробелом, то она может расширяться по опцииstd::strtok
, устраняя ее трудности, позволяя встроенную токенизацию, тем самым поддерживая генерациюconst vector<string>
и добавляя поддержку нескольких Обозначение белого пробела:
// String to tokenize
const std::string str("The quick tbrown nfox");
std::istringstream is(str);
// Vector to store tokens
const std::vector<std::string> tokens = std::vector<std::string>(
std::istream_iterator<std::string>(is),
std::istream_iterator<std::string>());
Живой пример
-
std::regex_token_iterator
используетstd::regex
для итеративного tokenize. Он обеспечивает более гибкое определение разделителя. Например, не разделенные запятыми и пробелы:
C ++ 11
// String to tokenize
const std::string str{ "The ,qu\,ick ,tbrown, fox" };
const std::regex re{ "\s*((?:[^\\,]|\\.)*?)\s*(?:,|$)" };
// Vector to store tokens
const std::vector<std::string> tokens{
std::sregex_token_iterator(str.begin(), str.end(), re, 1),
std::sregex_token_iterator()
};
Живой пример
Для regex_token_iterator
дополнительной информации см. Пример regex_token_iterator
.
Преобразование в (const) char *
Чтобы получить const char*
доступ к данным std::string
вы можете использовать функцию члена c_str()
. Имейте в виду, что указатель действителен только до тех пор, пока объект std::string
находится в пределах области действия и остается неизменным, это означает, что на объект могут быть вызваны только методы const
.
C ++ 17
Функция члена data()
может использоваться для получения модифицируемого char*
, который может использоваться для управления данными объекта std::string
.
C ++ 11
Модифицируемый char*
также можно получить, взяв адрес первого символа: &s[0]
. Внутри C ++ 11 гарантируется, что это приведет к созданию корректной строки с нулевым завершением. Заметим, что &s[0]
корректно сформирован, даже если s
пуст, а &s.front()
не определено, если s
пусто.
C ++ 11
std::string str("This is a string.");
const char* cstr = str.c_str(); // cstr points to: "This is a string."
const char* data = str.data(); // data points to: "This is a string."
std::string str("This is a string.");
// Copy the contents of str to untie lifetime from the std::string object
std::unique_ptr<char []> cstr = std::make_unique<char[]>(str.size() + 1);
// Alternative to the line above (no exception safety):
// char* cstr_unsafe = new char[str.size() + 1];
std::copy(str.data(), str.data() + str.size(), cstr);
cstr[str.size()] = ''; // A null-terminator needs to be added
// delete[] cstr_unsafe;
std::cout << cstr.get();
Поиск символа (ов) в строке
Чтобы найти символ или другую строку, вы можете использовать std::string::find
. Он возвращает позицию первого символа первого совпадения. Если совпадений не найдено, функция возвращает std::string::npos
std::string str = "Curiosity killed the cat";
auto it = str.find("cat");
if (it != std::string::npos)
std::cout << "Found at position: " << it << 'n';
else
std::cout << "Not found!n";
Найдено в позиции: 21
Возможности поиска дополнительно расширяются следующими функциями:
find_first_of // Find first occurrence of characters
find_first_not_of // Find first absence of characters
find_last_of // Find last occurrence of characters
find_last_not_of // Find last absence of characters
Эти функции позволяют вам искать символы с конца строки, а также находить отрицательный случай (т. Е. Символы, которые не находятся в строке). Вот пример:
std::string str = "dog dog cat cat";
std::cout << "Found at position: " << str.find_last_of("gzx") << 'n';
Найдено в позиции: 6
Примечание. Помните, что вышеупомянутые функции не выполняют поиск подстрок, а скорее для символов, содержащихся в строке поиска. В этом случае последнее вхождение 'g'
было найдено в позиции 6
(другие символы не были найдены).
Обрезка символов при запуске / окончании
Этот пример требует заголовков <algorithm>
, <locale>
и <utility>
.
C ++ 11
Чтобы обрезать последовательность или строку, необходимо удалить все ведущие и конечные элементы (или символы), соответствующие определенному предикату. Сначала мы обрезаем конечные элементы, потому что они не связаны с перемещением каких-либо элементов, а затем обрезают ведущие элементы. Обратите внимание, что приведенные ниже обобщения работают для всех типов std::basic_string
(например, std::string
и std::wstring
), а также для контейнеров последовательностей (например, std::vector
и std::list
).
template <typename Sequence, // any basic_string, vector, list etc.
typename Pred> // a predicate on the element (character) type
Sequence& trim(Sequence& seq, Pred pred) {
return trim_start(trim_end(seq, pred), pred);
}
Обрезка конечных элементов включает поиск последнего элемента, не соответствующего предикату, и стирание оттуда:
template <typename Sequence, typename Pred>
Sequence& trim_end(Sequence& seq, Pred pred) {
auto last = std::find_if_not(seq.rbegin(),
seq.rend(),
pred);
seq.erase(last.base(), seq.end());
return seq;
}
Обрезка ведущих элементов включает в себя поиск первого элемента, не соответствующего предикату, и стирание до него:
template <typename Sequence, typename Pred>
Sequence& trim_start(Sequence& seq, Pred pred) {
auto first = std::find_if_not(seq.begin(),
seq.end(),
pred);
seq.erase(seq.begin(), first);
return seq;
}
Чтобы специализировать выше для обрезки пробелов в std::string
мы можем использовать функцию std::isspace()
как предикат:
std::string& trim(std::string& str, const std::locale& loc = std::locale()) {
return trim(str, [&loc](const char c){ return std::isspace(c, loc); });
}
std::string& trim_start(std::string& str, const std::locale& loc = std::locale()) {
return trim_start(str, [&loc](const char c){ return std::isspace(c, loc); });
}
std::string& trim_end(std::string& str, const std::locale& loc = std::locale()) {
return trim_end(str, [&loc](const char c){ return std::isspace(c, loc); });
}
Аналогично, мы можем использовать функцию std::iswspace()
для std::wstring
и т. Д.
Если вы хотите создать новую последовательность, которая является обрезанной копией, вы можете использовать отдельную функцию:
template <typename Sequence, typename Pred>
Sequence trim_copy(Sequence seq, Pred pred) { // NOTE: passing seq by value
trim(seq, pred);
return seq;
}
Лексикографическое сравнение
Две std::string
s можно сравнить лексикографически с помощью операторов ==
!=
, <
, <=
, >
И >=
:
std::string str1 = "Foo";
std::string str2 = "Bar";
assert(!(str1 < str2));
assert(str > str2);
assert(!(str1 <= str2));
assert(str1 >= str2);
assert(!(str1 == str2));
assert(str1 != str2);
Все эти функции используют метод std::string::compare()
для выполнения сравнения и возвращают для удобства логические значения. Работа этих функций может быть интерпретирована следующим образом, независимо от фактической реализации:
-
оператор
==
:Если
str1.length() == str2.length()
и каждая пара символов совпадают, то возвращаетtrue
, иначе возвращаетfalse
. -
оператор
!=
:Если
str1.length() != str2.length()
или одна пара символов не соответствует, возвращаетtrue
, в противном случае возвращаетfalse
. -
оператор
<
или оператор>
:Находит первую пару символов, сравнивает их, а затем возвращает логический результат.
-
оператор
<=
или оператор>=
:Находит первую пару символов, сравнивает их, а затем возвращает логический результат.
Примечание . Пара символьная пара означает соответствующие символы в обеих строках одинаковых позиций. Для лучшего понимания, если две строки примера — str1
и str2
, а их длины — n
и m
соответственно, тогда пары символов обеих строк означают каждую пару str1[i]
и str2[i]
где i = 0, 1, 2 str2[i]
.., max (n, m) . Если для любого i, где соответствующий символ не существует, т. Е. Когда i больше или равно n
или m
, он будет считаться самым низким значением.
Ниже приведен пример использования <
:
std::string str1 = "Barr";
std::string str2 = "Bar";
assert(str2 < str1);
Эти шаги заключаются в следующем:
- Сравните первые символы,
'B' == 'B'
— двигаться дальше. - Сравните второй символ,
'a' == 'a'
— двигаться дальше. - Сравните третьи символы,
'r' == 'r'
— перейдите. - Диапазон
str2
теперь исчерпан, а вstr1
все еще есть символы. Таким образом,str2 < str1
.
Преобразование в std :: wstring
В C ++ последовательности символов представлены специализированием std::basic_string
с нативным типом символов. Две основные коллекции, определенные стандартной библиотекой, — std::string
и std::wstring
:
-
std::string
построена с элементами типаchar
-
std::wstring
построена с элементами типаwchar_t
Чтобы преобразовать между двумя типами, используйте wstring_convert
:
#include <string>
#include <codecvt>
#include <locale>
std::string input_str = "this is a -string-, which is a sequence based on the -char- type.";
std::wstring input_wstr = L"this is a -wide- string, which is based on the -wchar_t- type.";
// conversion
std::wstring str_turned_to_wstr = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(input_str);
std::string wstr_turned_to_str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(input_wstr);
Чтобы улучшить удобство использования и / или читаемость, вы можете определить функции для выполнения преобразования:
#include <string>
#include <codecvt>
#include <locale>
using convert_t = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_t, wchar_t> strconverter;
std::string to_string(std::wstring wstr)
{
return strconverter.to_bytes(wstr);
}
std::wstring to_wstring(std::string str)
{
return strconverter.from_bytes(str);
}
Использование образца:
std::wstring a_wide_string = to_wstring("Hello World!");
Это, безусловно, более std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("Hello World!")
чем std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("Hello World!")
.
Обратите внимание: char
и wchar_t
не подразумевают кодировку и не указывают размер в байтах. Например, wchar_t
обычно реализуется как 2-байтовый тип данных и обычно содержит кодированные данные UTF-16 под Windows (или UCS-2 в версиях до Windows 2000) и как 4-байтовый тип данных, закодированный с использованием UTF-32 в Linux. Это контрастирует с более новыми типами char16_t
и char32_t
, которые были введены в C ++ 11 и гарантированно будут достаточно большими, чтобы содержать любой символ UTF16 или UTF32 (или, точнее, кодовую точку ) соответственно.
Использование класса std :: string_view
C ++ 17
В C ++ 17 представлен std::string_view
, который является просто не принадлежащим ему диапазоном const char
s, реализуемым как пара указателей или указатель и длина. Это отличный тип параметров для функций, которые требуют немодифицируемых строковых данных. До C ++ 17 для этого было три варианта:
void foo(std::string const& s); // pre-C++17, single argument, could incur
// allocation if caller's data was not in a string
// (e.g. string literal or vector<char> )
void foo(const char* s, size_t len); // pre-C++17, two arguments, have to pass them
// both everywhere
void foo(const char* s); // pre-C++17, single argument, but need to call
// strlen()
template <class StringT>
void foo(StringT const& s); // pre-C++17, caller can pass arbitrary char data
// provider, but now foo() has to live in a header
Все это можно заменить на:
void foo(std::string_view s); // post-C++17, single argument, tighter coupling
// zero copies regardless of how caller is storing
// the data
Обратите внимание, что std::string_view
не может изменять свои базовые данные .
string_view
полезен, когда вы хотите избежать ненужных копий.
Он предлагает полезное подмножество функций, которые выполняет std::string
, хотя некоторые из функций ведут себя по-разному:
std::string str = "lllloooonnnngggg sssstttrrriiinnnggg"; //A really long string
//Bad way - 'string::substr' returns a new string (expensive if the string is long)
std::cout << str.substr(15, 10) << 'n';
//Good way - No copies are created!
std::string_view view = str;
// string_view::substr returns a new string_view
std::cout << view.substr(15, 10) << 'n';
Пересечение каждого символа
C ++ 11
std::string
поддерживает итераторы, поэтому вы можете использовать цикл, основанный на диапазоне, для повторения каждого символа:
std::string str = "Hello World!";
for (auto c : str)
std::cout << c;
Вы можете использовать «традиционные» for
цикла в цикле через каждый символ:
std::string str = "Hello World!";
for (std::size_t i = 0; i < str.length(); ++i)
std::cout << str[i];
Преобразование в целые числа / типы с плавающей запятой
std::string
содержащая число, может быть преобразована в целочисленный тип или тип с плавающей точкой, используя функции преобразования.
Обратите внимание: все эти функции перестают анализировать входную строку, как только они сталкиваются с нечисловым символом, поэтому "123abc"
будет преобразован в 123
.
Семейство функций std::ato*
преобразует строки C-стиля (массивы символов) в типы с целыми или с плавающей запятой:
std::string ten = "10";
double num1 = std::atof(ten.c_str());
int num2 = std::atoi(ten.c_str());
long num3 = std::atol(ten.c_str());
C ++ 11
long long num4 = std::atoll(ten.c_str());
Однако использование этих функций не рекомендуется, потому что они возвращают 0
если они не могут проанализировать строку. Это плохо, потому что 0
также может быть допустимым результатом, если, например, входная строка была «0», поэтому невозможно определить, действительно ли было выполнено преобразование.
Новое семейство функций std::sto*
преобразует std::string
s в типы с целыми числами или с плавающей точкой и генерирует исключения, если они не могут проанализировать их ввод. Вы должны использовать эти функции, если это возможно :
C ++ 11
std::string ten = "10";
int num1 = std::stoi(ten);
long num2 = std::stol(ten);
long long num3 = std::stoll(ten);
float num4 = std::stof(ten);
double num5 = std::stod(ten);
long double num6 = std::stold(ten);
Кроме того, эти функции также обрабатывают восьмеричные и шестнадцатеричные строки, в отличие от семейства std::ato*
. Второй параметр — это указатель на первый неотвернутый символ во входной строке (здесь не проиллюстрирован), а третий параметр — база для использования. 0
— автоматическое обнаружение восьмеричного (начиная с 0
) и шестнадцатеричного (начиная с 0x
или 0X
), и любое другое значение является базой для использования
std::string ten = "10";
std::string ten_octal = "12";
std::string ten_hex = "0xA";
int num1 = std::stoi(ten, 0, 2); // Returns 2
int num2 = std::stoi(ten_octal, 0, 8); // Returns 10
long num3 = std::stol(ten_hex, 0, 16); // Returns 10
long num4 = std::stol(ten_hex); // Returns 0
long num5 = std::stol(ten_hex, 0, 0); // Returns 10 as it detects the leading 0x
Преобразование между кодировками символов
Преобразование между кодировками легко с C ++ 11, и большинство компиляторов могут справиться с ним кросс-платформенным способом с помощью <codecvt>
и <locale>
.
#include <iostream>
#include <codecvt>
#include <locale>
#include <string>
using namespace std;
int main() {
// converts between wstring and utf8 string
wstring_convert<codecvt_utf8_utf16<wchar_t>> wchar_to_utf8;
// converts between u16string and utf8 string
wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> utf16_to_utf8;
wstring wstr = L"foobar";
string utf8str = wchar_to_utf8.to_bytes(wstr);
wstring wstr2 = wchar_to_utf8.from_bytes(utf8str);
wcout << wstr << endl;
cout << utf8str << endl;
wcout << wstr2 << endl;
u16string u16str = u"foobar";
string utf8str2 = utf16_to_utf8.to_bytes(u16str);
u16string u16str2 = utf16_to_utf8.from_bytes(utf8str2);
return 0;
}
Имейте в виду, что Visual Studio 2015 обеспечивает поддержку для этих преобразований, но ошибка в их реализации библиотеки требует использования другого шаблона для wstring_convert
при работе с char16_t
:
using utf16_char = unsigned short;
wstring_convert<codecvt_utf8_utf16<utf16_char>, utf16_char> conv_utf8_utf16;
void strings::utf16_to_utf8(const std::u16string& utf16, std::string& utf8)
{
std::basic_string<utf16_char> tmp;
tmp.resize(utf16.length());
std::copy(utf16.begin(), utf16.end(), tmp.begin());
utf8 = conv_utf8_utf16.to_bytes(tmp);
}
void strings::utf8_to_utf16(const std::string& utf8, std::u16string& utf16)
{
std::basic_string<utf16_char> tmp = conv_utf8_utf16.from_bytes(utf8);
utf16.clear();
utf16.resize(tmp.length());
std::copy(tmp.begin(), tmp.end(), utf16.begin());
}
Проверка, является ли строка префиксом другого
C ++ 14
В C ++ 14 это легко сделать с помощью std::mismatch
которая возвращает первую несоответствующую пару из двух диапазонов:
std::string prefix = "foo";
std::string string = "foobar";
bool isPrefix = std::mismatch(prefix.begin(), prefix.end(),
string.begin(), string.end()).first == prefix.end();
Следует отметить , что диапазон-и с половиной версия mismatch()
существовала до С ++ 14, но это небезопасно в случае, когда вторая строка является короче из двух.
C ++ 14
Мы все еще можем использовать версию std::mismatch()
в диапазоне от половины до половины, но нам нужно сначала проверить, что первая строка не превосходит вторую:
bool isPrefix = prefix.size() <= string.size() &&
std::mismatch(prefix.begin(), prefix.end(),
string.begin(), string.end()).first == prefix.end();
C ++ 17
С std::string_view
мы можем написать прямое сравнение, которое мы хотим, не беспокоясь о накладных std::string_view
или создании копий:
bool isPrefix(std::string_view prefix, std::string_view full)
{
return prefix == full.substr(0, prefix.size());
}
Преобразование в std :: string
std::ostringstream
можно использовать для преобразования любого потокового типа в строковое представление, вставив объект в объект std::ostringstream
(с оператором вставки потока <<
) и затем преобразуя весь std::ostringstream
в std::string
.
Например, для int
:
#include <sstream>
int main()
{
int val = 4;
std::ostringstream str;
str << val;
std::string converted = str.str();
return 0;
}
Написав свою собственную функцию преобразования, просто:
template<class T>
std::string toString(const T& x)
{
std::ostringstream ss;
ss << x;
return ss.str();
}
работает, но не подходит для критического кода производительности.
Определяемые пользователем классы могут при необходимости реализовать оператор вставки потока:
std::ostream operator<<( std::ostream& out, const A& a )
{
// write a string representation of a to out
return out;
}
C ++ 11
Помимо потоков, начиная с C ++ 11, вы также можете использовать std::to_string
(и std::to_wstring
), которая перегружена для всех основных типов и возвращает строковое представление ее параметра.
std::string s = to_string(0x12f3); // after this the string s contains "4851"
Символ – элементарная единица, некоторый набор которых несет определенный смысл. В языке программирования С++ предусмотрено использование символьных констант. Символьная константа – это целочисленное значение (типа int
) представленное в виде символа, заключённого в одинарные кавычки, например 'a'
. В таблице ASCII представлены символы и их целочисленные значения.
// объявления символьной переменной char symbol = 'a'; // где symbol – имя переменной типа char // char – тип данных для хранения символов
Строки в С++ представляются как массивы элементов типа char
, заканчивающиеся нуль-терминатором называются С строками или строками в стиле С.
— символ нуль-терминатора.
Символьные строки состоят из набора символьных констант заключённых в двойные кавычки. При объявлении строкового массива необходимо учитывать наличие в конце строки нуль-терминатора, и отводить дополнительный байт под него.
// пример объявления строки char string[10]; // где string – имя строковой переменной // 10 – размер массива, то есть в данной строке может поместиться 9 символов , последнее место отводится под нуль-терминатор.
Строка при объявлении может быть инициализирована начальным значением, например, так:
char string[10] = "abcdefghf";
Если подсчитать кол-во символов в двойных кавычках после символа равно их окажется 9, а размер строки 10 символов, последнее место отводится под нуль–терминатор, причём компилятор сам добавит его в конец строки.
// посимвольная инициализация строки: char string[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'f', ''}; // десятый символ это нуль-терминатор.
При объявлении строки не обязательно указывать её размер, но при этом обязательно нужно её инициализировать начальным значением. Тогда размер строки определится автоматически и в конец строки добавится нуль-терминатор.
//инициализация строки без указания размера char string[] = "abcdefghf"; //всё то же самое только размер не указываем.
Строка может содержать символы, цифры и специальные знаки. В С++ строки заключаются в двойные кавычки. Имя строки является константным указателем на первый символ. Разработаем программу, с использованием строк.
- MVS
- Code::Blocks
- Dev-C++
- QtCreator
// symbols.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { char string[] = "this is string - "; // объявление и инициализация строки cout << "Enter the string: "; char in_string[500]; // строковый массив для ввода gets(in_string); // функция gets() считывает все введённые символы с пробелами до тех пор, пока не будет нажата клавиша Enter cout << string << in_string << endl; // вывод строкового значения system("pause"); return 0; }
// symbols.cpp: определяет точку входа для консольного приложения. #include <iostream> #include <cstdio> using namespace std; int main(int argc, char* argv[]) { char string[] = "this is string - "; // объявление и инициализация строки cout << "Enter the string: "; char in_string[500]; // строковый массив для ввода gets(in_string); // функция gets() считывает все введённые символы с пробелами до тех пор, пока не будет нажата клавиша Enter cout << string << in_string << endl; // вывод строкового значения return 0; }
В строке 12 с помощью функции gets()
считаются все введённые символы с пробелами до тех пор, пока во вводимом потоке не встретится код клавиши enter
. Если использовать операцию cin
то из всего введённого считается последовательность символов до первого пробела (см. Рисунок 1).
CppStudio.com
Enter the string: CppStudio.com this is string - CppStudio.com Для продолжения нажмите любую клавишу . . .
Рисунок 1 — Символы и строки
Функция | Пояснение |
---|---|
strlen(имя_строки) | определяет длину указанной строки, без учёта нуль-символа |
Копирование строк | |
strcpy(s1,s2) | выполняет побайтное копирование символов из строки s2 в строку s1 |
strncpy(s1,s2, n) | выполняет побайтное копирование n символов из строки s2 в строку s1 . возвращает значения s1 |
Конкатенация строк | |
strcat(s1,s2) | объединяет строку s2 со строкой s1 . Результат сохраняется в s1 |
strncat(s1,s2,n) | объединяет n символов строки s2 со строкой s1 . Результат сохраняется в s1 |
Сравнение строк | |
strcmp(s1,s2) | сравнивает строку s1 со строкой s2 и возвращает результат типа int : 0 –если строки эквивалентны, >0 – если s1<s2, <0 — если s1>s2 С учётом регистра |
strncmp(s1,s2,n) | сравнивает n символов строки s1 со строкой s2 и возвращает результат типа int : 0 –если строки эквивалентны, >0 – если s1<s2, <0 — если s1>s2 С учётом регистра |
stricmp(s1,s2) | сравнивает строку s1 со строкой s2 и возвращает результат типа int : 0 –если строки эквивалентны, >0 – если s1<s2, <0 — если s1>s2 Без учёта регистра |
strnicmp(s1,s2,n) | сравнивает n символов строки s1 со строкой s2 и возвращает результат типа int : 0 –если строки эквивалентны, >0 – если s1<s2, <0 — если s1>s2 Без учёта регистра |
Обработка символов | |
isalnum(c) | возвращает значение true , если с является буквой или цифрой, и false в других случаях |
isalpha(c) | возвращает значение true , если с является буквой, и false в других случаях |
isdigit(c) | возвращает значение true , если с является цифрой, и false в других случаях |
islower(c) | возвращает значение true , если с является буквой нижнего регистра, и false в других случаях |
isupper(c) | возвращает значение true , если с является буквой верхнего регистра, и false в других случаях |
isspace(c) | возвращает значение true , если с является пробелом, и false в других случаях |
toupper(c) | если символ с , является символом нижнего регистра, то функция возвращает преобразованный символ с в верхнем регистре, иначе символ возвращается без изменений. |
Функции поиска | |
strchr(s,c) | поиск первого вхождения символа с в строке s . В случае удачного поиска возвращает указатель на место первого вхождения символа с . Если символ не найден, то возвращается ноль. |
strcspn(s1,s2) | определяет длину начального сегмента строки s1 , содержащего те символы, которые не входят в строку s2 |
strspn(s1,s2) | возвращает длину начального сегмента строки s1 , содержащего только те символы, которые входят в строку s2 |
strprbk(s1,s2) | Возвращает указатель первого вхождения любого символа строки s2 в строке s1 |
Функции преобразования | |
atof(s1) | преобразует строку s1 в тип double |
atoi(s1) | преобразует строку s1 в тип int |
atol(s1) | преобразует строку s1 в тип long int |
Функции стандартной библиотеки ввода/вывода <stdio> |
|
getchar(с) | считывает символ с со стандартного потока ввода, возвращает символ в формате int |
gets(s) | считывает поток символов со стандартного устройства ввода в строку s до тех пор, пока не будет нажата клавиша ENTER |
Разработаем несколько программ, используя функции для работы со строками и символами.
Копирование строк
- MVS
- Code::Blocks
- Dev-C++
- QtCreator
// str_cpy.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { char s2[27] = "Counter-Strike 1.6 forever"; // инициализация строки s2 char s1[27]; // резервируем строку для функции strcpy() cout << "strcpy(s1,s2) = " << strcpy(s1,s2) << endl; // содержимое строки s2 скопировалось в строку s1, возвращается указатель на s1 cout << "s1= " << s1 << endl; // вывод содержимого строки s1 char s3[7]; // резервируем строку для следующей функции cout << strncpy(s3, s2, 7) << endl; // копируем 7 символов из строки s2 в строку s3 system("pause"); return 0; }
// str_cpy.cpp: определяет точку входа для консольного приложения. #include <iostream> #include <cstring> using namespace std; int main(int argc, char* argv[]) { char s2[27] = "Counter-Strike 1.6 forever"; // инициализация строки s2 char s1[27]; // резервируем строку для функции strcpy() cout << "strcpy(s1,s2) = " << strcpy(s1,s2) << endl; // содержимое строки s2 скопировалось в строку s1, возвращается указатель на s1 cout << "s1= " << s1 << endl; // вывод содержимого строки s1 char s3[7]; // резервируем строку для следующей функции cout << strncpy(s3, s2, 7) << endl; // копируем 7 символов из строки s2 в строку s3 return 0; }
В строках 9, 10 создаём строковые массивы на 27 символов, словосочетание "Counter-Strike 1.6 forever"
содержит 26 символов, последнее место в массиве займет нуль-символ. В строке 11 функция strcpy(s1,s2)
копирует значение строки s2
в строку s1
и возвращает указатель на строку s1
. Если строка s1
будет меньше строки s2
, то скопируется то количество символов, которое вместится в строку s2
. Строка 10 всего лишь показывает, что в строке s1
содержится скопированное значение. В строке 14 функция strncpy(s3, s2, sizeof(s3))
выполняет копирование 7 символов строки s2
в строку s3
(см. Рисунок 2).
CppStudio.com
strcpy(s1,s2) = Counter-Strike 1.6 forever s1= Counter-Strike 1.6 forever CounterCounter-Strike 1.6 forever Для продолжения нажмите любую клавишу . . .
Рисунок 2 — Символы и строки
Конкатенация строк
Использование функций strcat()
и strncat()
, для объединения строк, то есть для их конкатенации.
- MVS
- Code::Blocks
- Dev-C++
- QtCreator
// str_cat.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { char s1[30] = "I am "; char s2[] = "programmer on the C++!!!!"; cout << strcat(s1,s2) << endl; // объединяем строки s1 и s2, результат сохраняется в строке s1 char s3[23] = "I am a good "; cout << strncat(s3,s2,10) << "!!!" << endl; // объединяем 10 символов строки s2 со строкой s3 system("pause"); return 0; }
// str_cat.cpp: определяет точку входа для консольного приложения. #include <iostream> #include <cstring> using namespace std; int main(int argc, char* argv[]) { char s1[30] = "I am "; char s2[] = "programmer on the C++!!!!"; cout << strcat(s1,s2) << endl; // объединяем строки s1 и s2, результат сохраняется в строке s1 char s3[23] = "I am a good "; cout << strncat(s3,s2,10) << "!!!" << endl; // объединяем 10 символов строки s2 со строкой s3 return 0; }
В строке 11 функция strcat(s1,s2)
объединяет строки s1
и s2
, результат сохраняется в строке s1
. По этому при объявлении строки s1
её размер установлен на 30 символов. В строке 13 функция strncat(s3,s2,10)
объединяет 10 символов из строки s2
(как раз помещается слово programmer
) со строкой s3
, результат сохраняется в строке s3. И по этому размер строки s3
также задан фиксировано (см. Рисунок 3).
CppStudio.com
I am programmer on the C++!!!! I am a good programmer!!! Для продолжения нажмите любую клавишу . . .
Рисунок 3 — Символы и строки
Сравнение строк
Рассмотрим работу функции strcmp()
, остальные функции используются аналогично, так что каждую рассматривать не будем.
- MVS
- Code::Blocks
- Dev-C++
- QtCreator
// str_cmp.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> #include <iomanip> using namespace std; int main(int argc, char* argv[]) { char s1[] = "www.cppstudio.com"; char s2[] = "http://www.cppstudio.com"; cout << " s1 == s1 -> " << setw(2) << strcmp(s1,s1) << endl; // строка s1 = s1 cout << " s1 < s2 -> " << setw(2) << strcmp(s1,s2) << endl; // строка s1 < s2 cout << " s2 > s1 -> " << setw(2) << strcmp(s2,s1) << endl; // строка s2 > s1 system("pause"); return 0; }
// str_cmp.cpp: определяет точку входа для консольного приложения. #include <iostream> #include <iomanip> #include <cstring> using namespace std; int main(int argc, char* argv[]) { char s1[] = "www.cppstudio.com"; char s2[] = "http://www.cppstudio.com"; cout << " s1 == s1 -> " << setw(2) << strcmp(s1,s1) << endl; // строка s1 = s1 cout << " s1 < s2 -> " << setw(2) << strcmp(s1,s2) << endl; // строка s1 < s2 cout << " s2 > s1 -> " << setw(2) << strcmp(s2,s1) << endl; // строка s2 > s1 return 0; }
В строках 12, 13, 14 функция strcmp()
выполняет сравнение строк, в различном порядке, таким образом были рассмотрены все возможные варианты работы данной функции. В первом случае строку s1
сравнивали с самой собой соответственно и результат равен 0. Во втором случае строка s1
оказалась меньше строки s2
поэтому результат равен 1. В третьем случае строка s1
по-прежнему меньше строки s2
, но мы поменяли эти строки местами, таким образом, порядок параметров функции изменился и результат стал равен -1 (см. Рисунок 4).
CppStudio.com
s1 == s1 -> 0 s1 < s2 -> 1 s2 > s1 -> -1 Для продолжения нажмите любую клавишу . . .
Рисунок 4 — Символы и строки
Обработка символов
Функции из данной группы умеют различать, к какому типу знаков относятся те или иные символы, например буквы, цифры, специальные знаки.
- MVS
- Code::Blocks
- Dev-C++
- QtCreator
// issss.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { char symbol = 'd'; // буква char digit = '9'; // цифра char space = ' '; // пробел char character = '#'; // знак // функция isalnum() проверяет является ли её аргумент буквой или цифрой cout << symbol << " - it is digit or alpha?: "; isalnum(symbol) ? cout << "truen": cout << "falsen"; // функция isalpha() проверяет является ли её аргумент буквой cout << symbol << " - it is alpha?: "; isalpha(symbol) ? cout << "truen": cout << "falsen"; // функция isdigit() проверяет является ли её аргумент цифрой cout << digit << " - it is digit?: "; isdigit(digit) ? cout << "truen": cout << "falsen"; // функция isspace() проверяет является ли её аргумент пробелом cout << space << " - it is space?: "; isspace(space) ? cout << "truen": cout << "falsen"; // функция islower() проверяет является ли её аргумент буквой нижнего регистра cout << symbol << " - it is lower alpha?: "; islower(symbol) ? cout << "truen": cout << "falsen"; // функция isupper() проверяет является ли её аргумент буквой верхнего регистра cout << symbol << " - it is upper alpha?: "; isupper(symbol) ? cout << "truen": cout << "falsen"; system("pause"); return 0; }
// issss.cpp: определяет точку входа для консольного приложения. #include <iostream> using namespace std; int main(int argc, char* argv[]) { char symbol = 'd'; // буква char digit = '9'; // цифра char space = ' '; // пробел char character = '#'; // знак // функция isalnum() проверяет является ли её аргумент буквой или цифрой cout << symbol << " - it is digit or alpha?: "; isalnum(symbol) ? cout << "truen": cout << "falsen"; // функция isalpha() проверяет является ли её аргумент буквой cout << symbol << " - it is alpha?: "; isalpha(symbol) ? cout << "truen": cout << "falsen"; // функция isdigit() проверяет является ли её аргумент цифрой cout << digit << " - it is digit?: "; isdigit(digit) ? cout << "truen": cout << "falsen"; // функция isspace() проверяет является ли её аргумент пробелом cout << space << " - it is space?: "; isspace(space) ? cout << "truen": cout << "falsen"; // функция islower() проверяет является ли её аргумент буквой нижнего регистра cout << symbol << " - it is lower alpha?: "; islower(symbol) ? cout << "truen": cout << "falsen"; // функция isupper() проверяет является ли её аргумент буквой верхнего регистра cout << symbol << " - it is upper alpha?: "; isupper(symbol) ? cout << "truen": cout << "falsen"; return 0; }
В данной программе по использованию функций вопросов возникать не должно. Функции сами по себе возвращают целочисленное значение, положительное – true
, отрицательное или ноль – false
. В формировании результата работы функций участвовал тернарный оператор, то есть выводилось сообщение true или false без всяких числовых значений (см. Рисунок 5).
CppStudio.com
d - it is digit or alpha?: true d - it is alpha?: true 9 - it is digit?: true - it is space?: true d - it is lower alpha?: true d - it is upper alpha?: false Для продолжения нажмите любую клавишу . . .
Рисунок 5 — Символы и строки
Итак, мы рассмотрели больше половины функций, из тех, что есть в таблице. Остальные функции используются аналогично, так что по ним примеры программ разбирать не будем.