上周我做了一个写函数的作业:该函数得到一个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;
}
我建议您学习使用c++标准函数。有很多实用函数可以帮助你进行编程。
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
限定它,这将表明它是一个输入参数而不是输出。
为什么你的老师是对的
事实上,你需要用空格初始化你的目的字符串是可怕的:
- 如果输入字符串较长,则会出现越界错误
- 如果它更短,您就会得到错误的答案,因为在it和编程中,
"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);
}
根据您自己的理解,这些声明
string part1=" ";
string part2=" ";
因为在对象CCD_ 14中输入的字符串基本上可以超过两个初始化的字符串。在这种情况下,使用字符串方法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";
}
只有在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);
}
}
我看到的最大问题是,在应该使用push_back
的地方使用at
。请参见std::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)
。