Как найти союзы в строке в с

0 / 0 / 0

Регистрация: 24.01.2020

Сообщений: 4

1

Найти союзы в строке

27.10.2021, 19:01. Показов 615. Ответов 4


Студворк — интернет-сервис помощи студентам

Помогите пожалуйста с решением на С++.
Нужно ввести строку и найти в ней союзы(хотя бы 2 для примера) и вывести их. У меня не получается если союз первый в строке
Заранее спасибо.



0



Эксперт CЭксперт С++

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



Эксперт CЭксперт С++

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <cstdlib>
#include <string>
#include <windows.h>
using namespace std;
int main()
{   
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    int i, c, c1; 
    string a;
    string a1;
    getline(cin, a);
    for (i = 0;;i++)
    {
        c = 0; c1 = 0;
        if ((a[i] == ' ') || (a[i] == '')) 
        {
            if (((a[i - 3] == 'и') && (a[i - 2] == 'л') && (a[i - 1] == 'и'))
                || ((a[i - 1] == 'и'))
                || ((a[i - 3] == 'ч') && (a[i - 2] == 'т') && (a[i - 1] == 'о'))
                || ((a[i - 2] == 'н') && (a[i - 1] == 'о'))
                || ((a[i - 1] == 'и'))
                || ((a[i - 5] == 'к') && (a[i - 4] == 'о') && (a[i - 3] == 'г') && (a[i - 2] == 'д') && (a[i - 1] == 'а'))
                || ((a[i - 4] == 'е') && (a[i - 3] == 'с') && (a[i - 2] == 'л') && (a[i - 1] == 'и')));
            {
                for (int j = i - 1;(a[j] != ' ') || (j != 0);j--) 
                {
                    c++;
                    if ((a[j - 1] == ' ') || (j == 0))
                    {
                        c1 = j;
                        break;
                    }
                }
                a1 = a.substr(c1, c);    
                cout << a1 << 'n';
            }
        }
        if (a[i] == '') break;
    }
    system("pause");
    return 0;
}



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

Mykola Lazarenko's user avatar

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 Hovsepyan's user avatar

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

  1. В строке non-const поведение не определено ;
  2. В строке CharT() ссылка на символ со значением CharT() ( нулевой символ).

C ++ 11

  1. CharT() ссылка на символ со значением CharT() ( нулевой символ).
  2. Изменение этой ссылки — неопределенное поведение .

Начиная с 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(); // '!'

токенизировать

Перечислены от наименее дорогостоящих до самых дорогих во время выполнения:

  1. 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);

Живой пример

  1. 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>());

Живой пример

  1. 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);

Эти шаги заключаются в следующем:

  1. Сравните первые символы, 'B' == 'B' — двигаться дальше.
  2. Сравните второй символ, 'a' == 'a' — двигаться дальше.
  3. Сравните третьи символы, 'r' == 'r' — перейдите.
  4. Диапазон 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_stringstd::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 — Символы и строки

Таблица 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 — Символы и строки

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

Понравилась статья? Поделить с друзьями:
  • Как перевести найти общий язык
  • Как найти сайт как похудеть
  • Как найти свою кошку если она сбежала
  • Как через командную строку найти точки восстановления
  • Как найти электропроводку в панельном доме