Форум программистов, компьютерный форум CyberForum.ru

[STL] Работа со std::string - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 48, средняя оценка - 4.90
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
24.08.2012, 17:47     [STL] Работа со std::string #1
Привет, форум.

Подскажите, как можно грамотно скопировать "слово" из строки, с указанием начала и конца позиций.
Например:
C++
1
2
string str = "My name is Vendetta";
string str name;
нужно грамотно, методом STL, скопировать буквы с 12 по 19. То-есть, слово Vendetta присвоить к name.
Заранее спасибо, может чуть позже ещё будут вопросы на эту тему.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
25.08.2012, 18:07  [ТС]     [STL] Работа со std::string #21
Как так?
Указатель же возвращается до выхода из предела видимости, точнее с этим и выходит.

а почему тогда вот так работает?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
string GetSomething()
{
    vector<string> somes;
    somes.push_back("something");
 
    vector<string>::iterator it = somes.begin();
    return it->c_str();
}
 
int main()
{
    string some = GetSomethig();
    cout << GetSomethig() << endl;
    cin.get(); // pause
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
MrCold
851 / 749 / 71
Регистрация: 11.01.2012
Сообщений: 1,942
25.08.2012, 18:11     [STL] Работа со std::string #22
...Или так
C++
1
2
3
4
5
6
7
int main()
{
char *str = new char[100];
    strcpy ( str, GetSomething());
    string some ( str );
    cout << some;
}
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
25.08.2012, 18:17     [STL] Работа со std::string #23
Указатель же возвращается до выхода из предела видимости, точнее с этим и выходит.
Указатель да. То, на что он указывает, — нет. Возвращается копия указателя.

а почему тогда вот так работает?
Потому что вы возвращаете std::string. с_str() возвращает const char*, он неявно вызывает конструктор std::string, который снимает копию с той строки. Получается, что из функции возвращается копия этой строки, а оригинал точно так же уничтожается.
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
25.08.2012, 18:19  [ТС]     [STL] Работа со std::string #24
Объясните конкретно пожалуйста, почему:

ошибка
C++
1
2
3
4
5
6
7
8
9
10
11
const char* GetSomething()
{
    string str = "something";
    return str.c_str();
}
 
int main()
{
    cout << GetSomethig() << endl;
    cin.get(); // pause
}
не ошибка
C++
1
2
3
4
5
6
7
8
9
10
11
string GetSomething()
{
    string str = "something";
    return str.c_str(); // или retrun str;
}
 
int main()
{
    cout << GetSomethig() << endl;
    cin.get(); // pause
}
Добавлено через 54 секунды
~OhMyGodSoLong~, сейчас подумаю
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
25.08.2012, 18:21     [STL] Работа со std::string #25
Потому что
C++
1
2
3
4
5
string GetSomething()
{
    string str = "something";
    return str.c_str();
}
Фактически значит
C++
1
2
3
4
5
string GetSomething()
{
    string str = "something";
    return string(str.c_str());
}
Возвращается копия этой строки. Она сохраняется при выходе, оригинал — нет.

А в случае
C++
1
2
3
4
5
const char* GetSomething()
{
    string str = "something";
    return str.c_str();
}
возвращается копия указателя на массив char, который хранится в локальной переменной str. Эта локальная переменная вместе с массивом умирает при выходе из функции. А указатель на неё остаётся, но он указывает уже чёрти куда.
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
25.08.2012, 18:27  [ТС]     [STL] Работа со std::string #26
всё равно недопонял. Как так, в обоих случаях же возвращается экземпляр str.
Объясните пожалуйста ещё конкретнее.
Эх жаль не знаю ассемблер.

Добавлено через 22 секунды
думаю думаю,
не читая запостил пост.

Добавлено через 1 минуту
всё понял, в случаи с const char* указатель будет указывать на некуда, ведь объекта уже нет.
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
27.08.2012, 14:49  [ТС]     [STL] Работа со std::string #27
Не в тему, но и новый топик ради такого мини вопроса создавать не решил.
Можно ли более грамотно(STL) реализовать сам алгоритм замены числа?:
C++
1
2
3
4
5
6
7
8
9
int changes[10][2] = { {10, 1523}, {11, 4123}, {12, 125}, {13, 5531}, {14, 5316}, {15, 4423}, {16, 6123}, {17, 6341}, {18, 6259}, {19, 5241} };
 
int num;
cin >> num;
 
for(int i = 0; i < 10; ++i)
    for(int j = 0; j < 10; ++j)
        if(num[i] == num[j][0]
            num[i] = changes[j][1];
novi4ok
549 / 502 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
27.08.2012, 14:56     [STL] Работа со std::string #28
Цитата Сообщение от vendeme Посмотреть сообщение
Благодарю, просто интересно методы опытных, как решают некоторые задачи.
Ещё вопрос про find. find возвращает начальную позицию найденного слова, а как узнать конечную позицию?
прибавить длину слова
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
27.08.2012, 15:59     [STL] Работа со std::string #29
Цитата Сообщение от vendeme Посмотреть сообщение
Не в тему, но и новый топик ради такого мини вопроса создавать не решил.
Можно ли более грамотно(STL) реализовать сам алгоритм замены числа?
Сделайте std::map<int, int>, хранящий нужные вам замены:
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
#include <map>
#include <iostream>
 
void print(int array[], size_t size)
{
  for (size_t i = 0; i < size; ++i) {
    std::cout << array[i] << " ";
  }
  std::cout << std::endl;
}
 
void subst(const std::map<int, int> &func, int array[], size_t size)
{
  for (size_t i = 0; i < size; ++i) {
    auto found = func.find(array[i]);
    if (!(found == func.end())) {
      array[i] = found->second;
    }
  }
}
 
int main()
{
  int array[11] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
  std::map<int, int> changes = { {10, 1523},
                                 {11, 4123},
                                 {12, 125 },
                                 {13, 5531},
                                 {14, 5316},
                                 {15, 4423},
                                 {16, 6123},
                                 {17, 6341},
                                 {18, 6259},
                                 {19, 5241} };
  print(array, 11);
  subst(changes, array, 11);
  print(array, 11);
}
Вариант для STL-нутых на всю голову.
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
45
46
47
48
#include <map>
#include <iostream>
#include <algorithm>
 
template <class T>
struct Printer {
  void operator()(const T &element)
  {
    std::cout << element << " ";
  }
};
 
template <class T>
class Substitutor {
  const std::map<T, T> &theMap;
public:
  Substitutor(const std::map<T,T> &theMap_) : theMap(theMap_) {}
  
  void operator()(T &element)
  {
    auto found = theMap.find(element);
    if (!(found == theMap.end())) {
      element = found->second;
    }
  }
};
 
int main()
{
  int array[11] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
  std::map<int, int> changes = { {10, 1523},
                                 {11, 4123},
                                 {12, 125 },
                                 {13, 5531},
                                 {14, 5316},
                                 {15, 4423},
                                 {16, 6123},
                                 {17, 6341},
                                 {18, 6259},
                                 {19, 5241} };
  std::for_each(array, array + 11, Printer<int>());
  std::cout << std::endl;
  
  std::for_each(array, array + 11, Substitutor<int>(changes));
  
  std::for_each(array, array + 11, Printer<int>());
  std::cout << std::endl;
}

И для утят
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
#include <map>
#include <iostream>
#include <algorithm>
 
int main()
{
  int array[11] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
  std::map<int, int> changes = { {10, 1523},
                                 {11, 4123},
                                 {12, 125 },
                                 {13, 5531},
                                 {14, 5316},
                                 {15, 4423},
                                 {16, 6123},
                                 {17, 6341},
                                 {18, 6259},
                                 {19, 5241} };
  std::for_each(array, array + 11, [] (int value) { std::cout << value << " "; });
  std::cout << std::endl;
  
  std::for_each(array, array + 11, [&] (int &value) {
                                     auto found = changes.find(value);
                                     if (!(found == changes.end())) {
                                       value = found->second;
                                     }
                                   });
  
  std::for_each(array, array + 11, [] (int value) { std::cout << value << " "; });
  std::cout << std::endl;
}
vendeme
27.08.2012, 16:44  [ТС]
  #30

Не по теме:

Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Вариант для STL-нутых на всю голову.
смеялись всем форумом

ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
27.08.2012, 19:25     [STL] Работа со std::string #31
~OhMyGodSoLong~, Почему в варианте для stl-нутых используется for_each? Алгоритмы надо под задачу выбирать, а не всегда for_each пользоваться.

http://liveworkspace.org/code/6d41ab...61b3309317c755

А для утят вариант... Опять же алгоритмы берутся не по делу. Если уж С++11 тогда так.

http://liveworkspace.org/code/1d9bc2...d78ebdb1018315
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
05.09.2012, 05:20  [ТС]     [STL] Работа со std::string #32
Ещё вопрос
как с алгоритмом STL заменить найденные слова на другое слово в строке.
голова к ночью совсем не работает.
C++
1
2
3
4
5
6
7
8
9
10
string str = "Hell0 wOrd!";
string replaceable = "0O";
 
// нужно это решить STL алгоритмом
for(size_t i = 0; i < str.size(); ++i)
    for(size_t j = 0; j < replaceable.size(); ++j)
        if(str[i] = replaceable[j])
            str[i] = "o";
 
// str будет возвращать "Hello word"
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
05.09.2012, 07:14     [STL] Работа со std::string #33
vendeme, Распарсить предложение на слова - заменить вхождения конкретного слова. boost::split + std::replace.
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
05.09.2012, 07:33  [ТС]     [STL] Работа со std::string #34
Цитата Сообщение от vendeme Посмотреть сообщение
с алгоритмом STL
Цитата Сообщение от ForEveR Посмотреть сообщение
boost::split
невнимательность, нет?
ну можно и с strtok, но всё равно мне кажется поиск с разделением на слова не лучшая идея.
По буквенный перебор с циклом мне кажется более быстрый вариант, хоть и громоздкий.
Или нет?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
05.09.2012, 08:46     [STL] Работа со std::string #35
vendeme, Нет, не невнимательность. boost::split написать самому довольно просто, элементарно пишется через std::stringstream. А вам производительность критична или что?

Добавлено через 12 минут
А что в данном случае значит "слова"? Так-то, если вхождения просто - достаточно std::string::find + std::string::replace.
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
05.09.2012, 20:30  [ТС]     [STL] Работа со std::string #36
Цитата Сообщение от ForEveR Посмотреть сообщение
А вам производительность критична или что?
производительность ооочень, очень критична.

А какой самый быстрый метод поиска если дано:
контейнер map[char, string], размер ~50.
контейнер string, размер < 255
нужно найти в string символы map->second и заменить их символом map->first

Ну или другой контейнер в качестве двумерного массива.

Добавлено через 11 часов 12 минут
bump!
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
05.09.2012, 21:29     [STL] Работа со std::string #37
Цитата Сообщение от vendeme Посмотреть сообщение
производительность ооочень, очень критична.
Ну раз только единичные символы, то так:
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
#include <iostream>
#include <map>
#include <string>
#include <climits>
 
int main()
{
  std::map<std::string, char> subst = {
    {"0123456789", 'N'},
    {"abcdefABCDEF", 'X'},
    {".!,:;-\"'?", 'P'}
  };
  
  // разворачиваем map в одномерный массив
  char subst_[CHAR_MAX] = {0};
  for (auto couple : subst) {
    for (char c : couple.first) {
      subst_[static_cast<size_t>(c)] = couple.second;
    }
  }
  
  // делаем замену по subst_
  std::string src = "ab8ca4ic!;';1!1asjdkabx9be1p7bai";
  std::cout << src << std::endl;
  for (auto c = src.begin(); c != src.end(); ++c) {
    if (subst_[static_cast<size_t>(*c)] != '\0') {
      *c = subst_[static_cast<size_t>(*c)];
    }
  }
  std::cout << src << std::endl;
}
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
05.09.2012, 21:39  [ТС]     [STL] Работа со std::string #38
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Ну раз только единичные символы, то так:
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
#include <iostream>
#include <map>
#include <string>
#include <climits>
 
int main()
{
  std::map<std::string, char> subst = {
    {"0123456789", 'N'},
    {"abcdefABCDEF", 'X'},
    {".!,:;-\"'?", 'P'}
  };
  
  // разворачиваем map в одномерный массив
  char subst_[CHAR_MAX] = {0};
  for (auto couple : subst) {
    for (char c : couple.first) {
      subst_[static_cast<size_t>(c)] = couple.second;
    }
  }
  
  // делаем замену по subst_
  std::string src = "ab8ca4ic!;';1!1asjdkabx9be1p7bai";
  std::cout << src << std::endl;
  for (auto c = src.begin(); c != src.end(); ++c) {
    if (subst_[static_cast<size_t>(*c)] != '\0') {
      *c = subst_[static_cast<size_t>(*c)];
    }
  }
  std::cout << src << std::endl;
}
1) Среда разработки разная, по этому, C++11 не вариант. Переделайте пожалуйста на старый стандарт.
2) Почему ключ string а не char?
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
05.09.2012, 21:53     [STL] Работа со std::string #39
Цитата Сообщение от vendeme Посмотреть сообщение
1) Среда разработки разная, по этому, C++11 не вариант. Переделайте пожалуйста на старый стандарт.
2) Почему ключ string а не char?
1)
тыц
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
#include <iostream>
#include <map>
#include <string>
#include <climits>
 
int main()
{
  std::map<std::string, char> subst;
  subst["0123456789"] = 'N';
  subst["abcdefABCDEF"] = 'X';
  subst[".!,:;-\"'?"] = 'P';
  
  // разворачиваем map в одномерный массив
  char subst_[CHAR_MAX] = {0};
  for (std::map<std::string, char>::const_iterator couple = subst.begin();
       couple != subst.end();
       ++couple)
  {
    for (std::string::const_iterator c = (*couple).first.begin();
         c != (*couple).first.end();
         ++c)
    {
      subst_[static_cast<size_t>(*c)] = (*couple).second;
    }
  }
  
  // делаем замену по subst_
  std::string src = "ab8ca4ic!;';1!1asjdkabx9be1p7bai";
  std::cout << src << std::endl;
  for (std::string::iterator c = src.begin();
       c != src.end();
       ++c)
  {
    if (subst_[static_cast<size_t>(*c)] != '\0') {
      *c = subst_[static_cast<size_t>(*c)];
    }
  }
  std::cout << src << std::endl;
}

2) Потому что это логично :\ Ключ — то, по чему производится поиск. Для замены символов на один символ надо же искать один из символов, а не целевой символ. Благо, варианту с разворотом в одномерный массив по барабану, что там ключ.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.09.2012, 22:04     [STL] Работа со std::string
Еще ссылки по теме:

Работа с классом std::string C++
C++ Как привести std::wstring к std::string?
C++ Error C2664: std::vector<_Ty>::push: невозможно преобразовать параметр 1 из 'double' в 'const std::string &'

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
vendeme
 Аватар для vendeme
-32 / 3 / 3
Регистрация: 22.06.2011
Сообщений: 88
05.09.2012, 22:04  [ТС]     [STL] Работа со std::string #40
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
2) Потому что это логично :\ Ключ — то, по чему производится поиск. Для замены символов на один символ надо же искать один из символов, а не целевой символ. Благо, варианту с разворотом в одномерный массив по барабану, что там ключ.
Разве?

C++
1
2
3
4
map<char, string> maps;
maps['a'] = "A";
map<char, string>::iterator it = maps.find('a');
cout << boolalpha << (it != maps.end()) << endl;
Вот здесь я получаю по ключу 'a'. Разве не так логично?
Yandex
Объявления
05.09.2012, 22:04     [STL] Работа со std::string
Ответ Создать тему
Опции темы

Текущее время: 11:32. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru