Трудности со строковым объявлением / ссылочными параметрами (c ++)

На прошлой неделе я получил домашнее задание, чтобы написать функцию: функция получает string и char Значение и следует разделить строку на две части, до и после первого появления существующего символа.

Код работал, но мой учитель сказал мне сделать это снова, потому что это не очень хорошо написанный код. Но я не понимаю, как сделать это лучше. Я до сих пор понимаю, что определение двух строк с пробелами не очень хорошо, но в противном случае я выхожу за пределы исключений. Поскольку ввод строки изменяется, размер строки меняется каждый раз.

#include <iostream>
#include <string>
using namespace std;

void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
int counter = 0;

for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.at(i) = text.at(i);
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.at(counter) = text.at(i);
}
else {
sec_part.at(counter) = text.at(i);
counter++;
}
}
}

int main() {
string text;
string part1="                            ";
string part2="                            ";
char search_char;

cout << "Please enter text? ";
getline(cin, text);

cout << "Please enter a char: ? ";
cin >> search_char;

divide(search_char,text,aprt1,part2);
cout << "First string: " << part1 <<endl;
cout << "Second string: " << part2 << endl;

system("PAUSE");
return 0;
}

2

Решение

Я хотел бы предложить вам, научиться использовать стандартные функции с ++. Есть много полезных функций, которые могут помочь вам в программировании.

void divide(const std::string& text, char search, std::string& first_part, std::string& sec_part)
{
std::string::const_iterator pos = std::find(text.begin(), text.end(), search);

first_part.append(text, 0, pos - text.begin());
sec_part.append(text, pos - text.begin());
}

int main()
{
std::string text = "thisisfirst";
char search = 'f';

std::string first;
std::string second;

divide(text, search, first, second);
}

Здесь я использовал std::find что вы можете прочитать об этом из Вот а также Iterators,

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

1

Другие решения

Почему твой учитель прав?

Тот факт, что вам нужно инициализировать строки назначения с пустым пространством, ужасен:

  • Если входная строка длиннее, вы выйдете из связанных ошибок.
  • Если короче, вы получили неправильный ответ, потому что в ИТ и программировании, "It works " это не то же самое, что "It works".

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

Альтернатива 1: ваш код работает

Просто очистите строки назначения в начале. Затем повторите, как вы, но используйте += или же push_back() добавить символы в конце строки.

void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
first_part.clear();   // make destinations strings empty
sec_part.clear();

for (int i = 0; i < text.size(); i++) {
char c = text.at(i);
if (firstc && c != search) {
first_part += c;
}
else if (firstc && c == search) {
firstc = false;
sec_part += c;
}
else {
sec_part += c;
}
}
}

Я использовал временный c вместо text.at(i) или же text\[i\], во избежание многократной индексации Но это на самом деле не требуется: в настоящее время оптимизирующие компиляторы должны генерировать эквивалентный код, какой бы вариант вы здесь не использовали.

Альтернатива 2: использовать функции-члены строки

Эта альтернатива использует find() функции, а затем строит строку от начала до этой позиции, а другую из этой позиции. Существует особый случай, когда персонаж не был найден.

void divide(char search, string text, string& first_part, string& sec_part)
{
auto pos = text.find(search);
first_part = string(text, 0, pos);
if (pos== string::npos)
sec_part.clear();
else sec_part = string(text, pos,  string::npos);
}
1

Как вы сами понимаете эти декларации

string part1="                            ";
string part2="                            ";

не имеет смысла, потому что введенная строка в объекте text может существенно превышать обе инициализированные строки. В этом случае используется строковый метод at может привести к возникновению исключения или строки будут иметь завершающие пробелы.

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

Учтите, что параметр text должен быть объявлен как постоянная ссылка.

Также вместо использования циклов лучше использовать методы класса std::string такой как например find,

Функция может выглядеть следующим образом

#include <iostream>
#include <string>

void divide(const std::string &text, char search, std::string &first_part, std::string &sec_part)
{
std::string::size_type pos = text.find(search);

first_part = text.substr(0, pos);

if (pos == std::string::npos)
{
sec_part.clear();
}
else
{
sec_part = text.substr(pos);
}
}

int main()
{
std::string text("Hello World");
std::string first_part;
std::string sec_part;

divide(text, ' ', first_part, sec_part);

std::cout << "\"" << text << "\"\n";
std::cout << "\"" << first_part << "\"\n";
std::cout << "\"" << sec_part << "\"\n";
}

Выход программы

"Hello World""Hello"" World"

Как видите, разделительный символ включен во вторую строку, хотя я думаю, что, возможно, было бы лучше исключить его из обеих строк.

Альтернативный и, на мой взгляд, более понятный подход может выглядеть следующим образом

#include <iostream>
#include <string>
#include <utility>

std::pair<std::string, std::string> divide(const std::string &s, char c)
{
std::string::size_type pos = s.find(c);

return { s.substr(0, pos), pos == std::string::npos ? "" : s.substr(pos) };
}

int main()
{
std::string text("Hello World");

auto p = divide(text, ' ');

std::cout << "\"" << text << "\"\n";
std::cout << "\"" << p.first << "\"\n";
std::cout << "\"" << p.second << "\"\n";
}
1

Ваш код будет работать только до тех пор, пока символ находится внутри part1.length (). Вам нужно что-то похожее на это:

void string_split_once(const char s, const string & text, string & first, string & second) {
first.clear();
second.clear();
std::size_t pos = str.find(s);
if (pos != string::npos) {
first  = text.substr(0, pos);
second = text.substr(pos);
}

}

1

Самая большая проблема, которую я вижу, заключается в том, что вы используете at где вы должны использовать push_back, Увидеть станд :: basic_string :: push_back. at предназначен для доступа существующий персонаж читать или изменять его. push_back добавляет новый символ в строку.

divide может выглядеть так:

void divide(char search, string text, string& first_part,
string& sec_part)
{
bool firstc = true;

for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.push_back(text.at(i));
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.push_back(text.at(i));
}
else {
sec_part.push_back(text.at(i));
}
}
}

Поскольку вы не обрабатываете исключения, рассмотрите возможность использования text[i] скорее, чем text.at(i),

0
По вопросам рекламы [email protected]