连接字符串时出现意外问题

Unexpected problems concatenating strings

本文关键字:意外 问题 字符串 连接      更新时间:2023-10-16

我正在尝试使用 + 连接字符串,但有一些奇怪的事情正在发生。这是我为一个班级项目准备的"成绩"课程:

#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Grade {
    private:
        string className;
        string student;
        string letter;
    public:
        Grade(string c, string s, string l) : className(c), student(s), letter(l) {}
        string getLetterGrade() const { return letter; }
        string getClassName() const { return className; }
        string getStudent() const { return student; }
        void setLetterGrade(string l) { letter = l; return;}
        void setClassName(string c) { className = c; return;}
        void setStudnet(string s) { student = s; return;}
        string toString() const { string output = "hello"+student; return output; }
};

显然,toString() 方法目前不是我想要的。如果我像上面一样运行 toString(),我会像预期的那样得到"hello529173860"。但是,如果我将行更改为:

string toString() const { string output = student+"hello"; return output; }

然后输出为"Hello3860"。这不仅仅是将 hello 字符串放在前面,而是在此过程中替换学生字符串中的字符......不知何故?

此外,如果我尝试使用:

string toString() const { string output = "hello"+" world"; return output; }

我收到一个错误:

Grade.h: In member function ‘std::string Grade::toString() const’:
Grade.h:29:53: error: invalid operands of types ‘const char [6]’ and ‘const char [7]’ to binary ‘operator+’
   string toString() const { string output = "hello"+" world"; return output; }
                                                     ^

我真的不知所措...特别是因为我在程序的早期已经完成了字符串连接而没有问题。我想要的是输出如下内容:

"学生+[一些空格]+

字母+[一些空格]+班级名称"

可以将

std::string添加到任何内容(另一个std::string,双引号字符串文字char)并提供直观的结果,但是如果您尝试将双引号字符串文字添加到另一个字符串文字或char那么它将不会"工作":

  • 添加到char或其他整数值的字符串文字将经历标准转换为const char*,然后添加到指针的任何数字都将沿着该字符数的文字移动:如果偏移量不在字符串文字内,那么如果您取消引用(使用)生成的指针,您将获得未定义的行为,

  • 两个
  • 字符串文本无法添加,即使在衰减到两个指针之后也是如此,因此会出现编译时错误。

有时您需要显式构造一个std::string以便与其他值的连接可以根据需要工作:例如 my_string = std::string("hello ") + my_const_char_ptr + 'n' .

例子:

std::string s = "Hello";
s + " World"; // ok
"Hello " + s; // ok
"Hello " + "World"; // NOT ok - two string literals
s += " World"; // ok
s += " Goodbye " + "World"; // NOT ok - "+" evaluated before "+="
s += std::string(" Goodbye ") + "World"; // OK - right-hand-side no longer two literals
                                         // BUT may be slower than two "s +="

常量字符串 "hello""world" 只不过是 const char* 类型的编译时常量。就像你不能添加两个int指针一样:

int *p1, *p2;
p1+p1; // Error

不能添加两个(const) char*对象。这违反了 C/C++ 语言规则。如果必须连接两个 const-char-指针,则可以将它们放在一起:

"hello"  "world"

如果您将它们与宏一起使用,则此技术主要有用。例如:

// Over simplified
#define ONE(_x) _x
#define TWO(_x) _X
ONE("This is") TWO(" concatenation")

如果要添加两个(或更多)运行时 C 字符串,则必须使用strXXX函数(如 strcat ),或者更好地使用 std::string

字符数组没有运算符 +。所以很明显这段代码

string toString() const { string output = "hello"+" world"; return output; }

无效。

在此表达式"hello"+" world"中使用了两个字符串文本,其类型分别为 const char[6]const char[7] 。运算符 + 不是为数组定义的。

你可以写

string toString() const { return string( "hello" ) + " world"; }

在这种情况下,使用运算符 + 重载用于类std::string。局部变量input的声明是多余的。因此,您甚至可以通过以下方式简化功能

string toString() const { return "hello world"; }