不使用std::string构建字符串

4

我正在处理一个项目,我们不允许使用<string>库 - 我们只能使用字符串作为字符指针,并且必须为它们编写自己的函数(如strcpy、strlen等)。我正在尝试构建一个RentalCar类,其头文件如下:

#ifndef RENTALCAR_H
#define RENTALCAR_H
class RentalCar {
 public:
  RentalCar();
  RentalCar(char* make, char* model);
  char* getMake() const;
  char* getModel() const;
  void setMake(char* make = "");
  void setModel(char* model = "");
 private:
  char m_make[256];
  char m_model[256];
};
#endif

我的源文件包含以下内容:
#include <iostream>
#include "RentalCar.h"
using namespace std;

RentalCar::RentalCar() {
    setYear();
    setMake();
    setModel();
    setPrice();
    setAvailable();
}

RentalCar::RentalCar(int year, char* make, char* model, float price, 
bool available) {
    setYear(year);
    setMake(make);
    setModel(model);
    setPrice(price);
    setAvailable(available);
}

char* RentalCar::getMake() const{
    return m_make;
}

char* RentalCar::getModel() const{
    return m_model;
}

void RentalCar::setMake(char* make) {
    myStringCopy(m_make, make);
}

void RentalCar::setModel(char* model) {
    myStringCopy(m_model, model);
}


char* myStringCopy(char* destination, const char* source) {
    int index = 0;
    while(*(source + index) != '\0') {
        *(destination + index) = *(source + index);
        index++;
    }
    *(destination + index) = '\0';
    return destination;
}

我的问题是,在我的getMake和getModel方法中,我遇到了以下错误:
cannot initialize return object of type 'char *'
  with an lvalue of type 'char const[256]'

我不确定如何构造默认字符串,而不是文字 - 这就是为什么我认为我会得到这个错误的原因。

我还有一个问题是,在设置setMake()和setModel()函数中的字符串时,我需要使用myStringCopy()函数,那么我应该将其作为类中的一个函数包含进去,还是有其他方法可以访问它?我也需要在我的实际项目文件中使用它,但在那里和RentalCar.cpp中都包含它感觉很冗余。

值得一提的是,我们不允许以任何方式使用数组索引来处理字符串 - 除了初始化新字符串。

任何帮助都将不胜感激!谢谢!


10
为了解决这个问题,我会编写自己的字符串类。它不需要像 std::string 一样复杂,但封装字符串管理和比较会使使用它的代码更加容易编写。 - NathanOliver
8
那真是太糟糕了。很遗憾许多所谓教授C++的课程并没有真正教授C++。 - NathanOliver
3
@BRetnik说:"这些数据必须以char[]的形式存储,而不是使用String对象。" 那么,如果你在创建String类时做了更多的工作,就会被扣分吗?你正在学习如何轻松创建缓冲区溢出,这种不安全的代码应该是一个好的C ++课程不应该教授的东西。我相信在这门课程之后,许多学生现在会使用Java、Python或C#,并永远放弃C++。 - PaulMcKenzie
3
鉴于当前社会的情况,我很惊讶没有很多教师说:“这样教学生真的很糟糕”,至少应该引发同行之间的讨论。您如何解释C ++教师沉默不语的现象?除非有教授“糟糕代码”的合理原因,并且稍后将给您提供良好编写的代码进行比较,否则您正在接受垃圾教学。 - PaulMcKenzie
1
@MikeBorkland 确实,但是C++已经标准化20年了,因此std::string从那时起就可用。这已经是一代人的时间了。你能想象一个电视维修课程教如何更换真空管吗? - PaulMcKenzie
显示剩余10条评论
2个回答

3
char* getMake() const;
char* getModel() const;

即使类是不可变的,您仍然可以返回指向可变值的指针。函数声明中的后缀const意味着该函数在整个类被声明为const时必须正常工作,这意味着所有成员都带有const关键字。

const char* getMake() const { return m_make; }
const char* getModel() const { return m_model; }
char* getMake() { return m_make; } 
char* getModel(){ return m_model; }

应该可以正常工作。使用带有 const 的类将获取不可变值,但非 const 的类则不会。尽管如此,返回非 const 指针会破坏封装性。因此,我会这样做:

const char* getMake() const { return m_make; }
const char* getModel() const { return m_model; }

只需这样做即可。无论是可变版本还是不可变版本的类都将从您的get函数中获取不可变值。这可能是期望的结果。

* mutable 说嗨,然后溜到一个角落里死去了。


1

KitsuneYMG回答了你的编译问题。我想进一步谈谈你的代码。

首先,这段代码更简单。

char* myStringCopy(char* destination, const char* source) {
    char * retVal = destination;
    do {
        *(destination++) = *(source++);
    } while ( *(source++) != 0 );
    return retVal;
}

但是如果您想使用自己的代码,这样更容易理解:

char* myStringCopy(char* destination, const char* source) {
    int index = 0;
    while(source[index] != '\0') {
        destination[index] = source[index];
        index++;
    }
    destination[index] = '\0';
    return destination;
}

但这是一种可爱的方式来稍微转变一下:

char* myStringCopy(char* destination, const char* source) {
    int index = 0;
    do {
        destination[index] = source[index];
    } while (source[index++]);

    return destination;
}

接下来,如果你想成为一名真正的程序员,这一点非常重要。定长缓冲区是一个非常糟糕的想法,特别是如果你不检查输入字符串的长度。如果你的数据包括256个字符或更多的字符串,那么你的256个字节将无法容纳字符串加上0字节,你就会遇到数据损坏的问题。

这是在依赖固定长度缓冲区的代码中非常常见的问题。它被称为缓冲区溢出,并且是黑客攻击软件的最大手段之一。这是巨大的安全问题。

如果你打算使用固定长度缓冲区而不是学习如何使用new[]和delete[],那么你需要检查输入到你的setter中的长度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接