构造没有std :: string的字符串

时间:2019-02-13 14:06:41

标签: c++ c-strings

我正在一个项目中,根本不允许使用<string>库-我们只能将字符串用作字符指针,并且必须为其编写自己的函数(strcpy,受惊等)。我正在尝试使用以下头文件构造一个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中包含它都感到多余了

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

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

2 个答案:

答案 0 :(得分: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 :(得分: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 [],则需要对设置器的输入进行长度检查。