我正在尝试编写一个函数,该函数将从给定的开始和结束索引返回一个子字符串。这是我写的代码,但是当我运行它时,它给了我错误。我使用 gtest 来运行它而不是 main()。
template <typename S>
S substring(S string_, int Istart, int Iend)
{
S substr = string_[Istart];
for(int i=(Istart+1); i<Iend; i++)
{
substr += string_[i];
}
return substr;
}
这是我得到的错误:
In file included from test.cpp:2:0:
lab2.cpp: In instantiation of ‘S substring(S, int, int) [with S = const char*]’:
test.cpp:56:1: required from here
lab2.cpp:91:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
S substr = string_[Istart];
~~~~~~~^
我的测试代码是这样的:
TEST(subStr, T1){
string str="he";
EXPECT_EQ(str,substring("hello", 0, 2));
}
TEST(subStr, T2){
string str="urge";
EXPECT_EQ(str,substring("hamburger", 4, 8));
}
答案 0 :(得分:4)
使用给定的调用上下文,这个:
EXPECT_EQ(str,substring("hello", 0, 2));
利用
的扩展substring<const char*>
因此结果代码变为:
const char* substring(const char* string_, int Istart, int Iend)
{
const char* substr = string_[Istart];
for(int i=(Istart+1); i<Iend; i++)
{
substr += string_[i];
}
return substr;
}
显然这行不通。 const char* substr = string_[Istart];
正在从 const char *
初始化 char
。在我看来,你有两种选择,但只有一种是远程现实的。由于 EXPECT_EQ
测试等效性,因此无论如何都无法使用指针路由。您需要至少在该测试的一侧有一个可比较的std::string
保证,而唯一的方法是保证同时仍然提供您富有表现力的论点是这样的:
template<class S>
std::string substring(S s, int Istart, int Iend)
{
return std::string(s).substr(Istart, Iend - Istart);
}
这会将与 std::string
兼容的任何内容作为源参数。结果始终是 std::string
,然后可以将其用于与各种事物进行比较,包括 char[N]
、const char *
,当然还有 std::string
。
它仍然有一个很大的警告,必须订购 Istart
和 Iend
。消除这种脆弱性正是 substr
的标准库 std::string
成员不采用 begin,end; 的原因。它需要一个开始,长度。尽管如此,这很容易成为做你想做的事情的最简单的方法。(尽管单行性质表明这样的事情非常有用)。
示例
我没有 GoogleTest,但一个简单的断言宏将演示针对与 std::string
的不同比较进行的测试:
#include <iostream>
#include <string>
#include <cassert>
template<class S>
std::string substring(S s, int Istart, int Iend)
{
return std::string(s).substr(Istart, Iend - Istart);
}
int main()
{
const char *kvalptr = "welcome";
std::string kvalstr = kvalptr;
auto res = substring("abdwelcomedef", 3, 10);
// test that both lhs prospects test against our result
assert(kvalptr == res);
assert(kvalstr == res);
// output res and one of the prospects.
std::cout << res << '\n' << kvalptr << '\n';
}
输出
welcome
welcome
答案 1 :(得分:0)
假设预期类型为 string
。 +=
类型存在 string
运算符。
一个简单的解决方法是替换
S substr = string_[Istart];
与
S substr;
substr += string_[Istart];
这不适用于 const char*
类型
以下适用于 string
和 const char*
。
#include <exception>
#include <iostream>
#include <functional>
#include <string>
#include <type_traits>
template <typename S>
S substring(S string_, int Istart, int Iend)
{
if constexpr (std::is_same_v<S, std::string>) {
if(Istart < Iend){
return string_.substr(Istart, Iend-Istart);
}
}
else if constexpr (std::is_same_v<S, const char*>)
{
if(Istart < Iend){
std::string temp = std::string(string_);
return (temp.substr(Istart, Iend-Istart)).c_str();
}
}
else throw;
}