为什么通过带有文字编号的引用调用会出现"无匹配函数"错误?

Why a "no matching function" error for call by reference with literal number?

本文关键字:无匹配 错误 函数 调用 引用 文字 编号 为什么      更新时间:2023-10-16

问题要求创建一个程序,要求用户输入一些文本,并且该文本将被星号包围,具体取决于屏幕的宽度,例如,如果用户输入"Hello world",则输出应为:

****************
* Hello World! *
****************

我尝试创建函数,但由于显示的最小代码的编译器错误而卡住了。

问:为什么它告诉我no matching functionwithin_width(text, 80)

我拥有的一些代码如下:

#include <iostream>
#include <string>
void display_header (std::string &header) {
std::string text;
header = text;
}
bool within_width (std::string& text, unsigned short int& max_width) {

}
int main() {
std::string text;
std::cout << "Please enter header text: ";
std::getline(std::cin, text);
if (within_width(text, 80)) {
// call the display_header function and pass in the text
// inputted by the user
} else {
std::cout << text;
}
return 0;
}

函数的声明

bool within_width (std::string& text, unsigned short int& max_width)

要求一个无符号的短 int变量,因为它有一个引用参数,请参阅第二个&

为了满足它,您需要将值 80 放入一个变量中,并将该变量作为参数。

unsigned short int MyWidth=80;
if (within_width(text, MyWidth))

或者(但我假设您不被允许(您可以使用按值参数调用

bool within_width (std::string& text, unsigned short int max_width)

然后你可以如图所示打电话。

我不会在这里给出完整的答案,只是一些线索。

  • display_header()函数和within_width()函数需要知道参数中给出的字符串,但不能修改它;因此这个参数的类型应该是const std::string &(缺少const(。
  • within_width()函数的第二个参数只是一个整数,它将与字符串的长度进行比较;你不需要通过引用(或至少const(传递它,而是通过值传递它。在这里,(非const(引用阻止传递文字常量80
    (这似乎是版后问题的主要关注点(
  • 你需要一步一步地推理。
    1. 所有这些都取决于字符串的大小(12表示Hello World!(;这些信息可以通过size(text)(或text.size()
      ((https://en.cppreference.com/w/cpp/iterator/size(
      (https://en.cppreference.com/w/cpp/string/basic_string/size(获得。
    2. 这个大小必须与max_width进行比较
    3. 显示带有header的行将需要另外 4 个字符,因为*将附加前缀并附加*字符。
    4. 因此,周围的两条线也将具有长度size(header)+4
    5. 为了创建这样一个由*组成的字符串,你可以使用一个构造函数std::string取两个参数:字符数和要重复的字符。
      (https://en.cppreference.com/w/cpp/string/basic_string/basic_string(
    6. 正确的顺序将所有这些发送给std::cout

编辑: 只是注意到这个答案可能远远超出了你被赋予的任务范围(只是填写了你老师提供的一些骨架(。

我仍然会把它留在这里,以说明 任意输入可以做什么。也许你想比你被问到的更进一步的实验......

bool within_width(...)

很简单:string.length() <= max– 稍等片刻,您需要在输出的开头和结尾考虑星号和空格,因此:max - 4

但是你可以做得更好,你可以拆分字符串,最好在单词边界。不过,这有点困难,更困难:

std::vector<std::string> lines;
// we'll be starting with an initially empty line:
auto lineBegin = text.begin();
auto lineEnd = text.begin();
for(auto i = text.begin(); i != text.end(); ++)
// stop condition empty: we'll stop from inside the loop...
{
// ok, we need to find next whitespace...
// we might try using text.find_first_of("..."), but then we
// need to know any whitespace characters ourselves, so I personally
// would rather iterate manually and use isspace function to determine;
// advantage: we can do other checks at the same time, too
auto distance = std::distance(lineBegin, i);
if(std::distance(lineBegin, i) > maxLineLength)
{
if(lineEnd == lineBegin)
{
// OK, now we have a problem: the word itself is too long
// decide yourself, do you want to cut the word somewhere in the
// middle (you even might implement syllable division...)
// or just refuse to print (i. e. throw an exception you catch
// elsewhere) - decide yourself...
}
else
{
lines.emplace_back(lineBegin, lineEnd);
lineBegin = lineEnd; // start next line...
}
}
// OK, now handle current character appropriately
// note: no else: we need to handle the character in ANY case,
// if we terminated the previous line or not
if(std::isspace(static_cast<unsigned char>(*i)))
{
lineEnd = i;
}
// otherwise, we're inside a word and just go on
}
// last line hasn't been added!
lines.emplace_back(lineBegin, lineEnd);

现在,您可以计算包含的所有字符串的最大长度。最好:在向向量添加新行时正确执行此操作,这样就不需要单独的循环了......

您可能已经注意到,我没有删除字符串末尾的空格,因此您无需添加自己的空格,可能与最后一个字符串分开(因此您可以添加lines.back() += ' ';(。

到目前为止,丑陋的部分是我留下了多个后续空格。最好是在分成几行之前删除,但请注意,您需要至少留下一行。所以:

auto end = text.begin();
bool isInWord = false; // will remove leading whitespace, if there is
for(auto c : text)
{
if(std::isspace(static_cast<unsigned char>(c)))
{
if(isInWord)
{
*end++ = ' '; // add a single space
isInWord = false;
}
}
else
{
*end++ = c;
isInWord = true;
}
}

这会将所有单词移到字符串的开头,但我们尚未删除字符串的剩余部分:

text.erase(end, text.end());

很好,其余的很简单:

  • 迭代最大长度,在每个循环中打印一个星号
  • 遍历向量中的所有字符串:
    std::cout << "* " << line << "*n";
  • 重复初始循环以打印星号的第二行

最后:您引入了 80 个字符的固定行限制。如果控制台更大,您就不会使用整个可用宽度,这可能是可以接受的,如果它更小,您将在错误的位置折断线。

您现在可以(但这是可选的(尝试检测控制台的宽度 - 之前已经问过,所以我不会更深入地介绍。

最后说明:上面介绍的代码未经测试,所以不能保证没有错误!