实验3:作业魔改版

目前问题:某处存在data越界问题,delete[]时会发生HEAP CORRUPTION DETECTED错误
main
lensfrex 3 years ago
parent e22d05f823
commit 847ec0fb15
Signed by: lensfrex
GPG Key ID: 0F69A0A2FBEE98A0
  1. 6
      work20220407/CMakeLists.txt
  2. 26
      work20220407/main.cpp
  3. 232
      work20220407/string/String.cpp
  4. 71
      work20220407/string/String.h

@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.21)
project(work20220407)
set(CMAKE_CXX_STANDARD 14)
add_executable(work20220407 main.cpp string/String.cpp string/String.h)

@ -0,0 +1,26 @@
#include <iostream>
#include "string/String.h"
using namespace std;
int main() {
String s1("Help!"),s2("Good!"),s3(s2),s4,s5;
cout<<"s1="<<s1<<endl;
s3="Hello!";
cout<<"s3="<<s3<<endl;
s3=s2;
cout<<"s3="<<s3<<endl;
s3+=s2;
cout<<"s3="<<s3<<endl;
cin>>s4;
cout<<"s4="<<s4<<endl;
cout<<"s4length="<<s4.Length()<<endl;
/*s5=s3+s4;
cout<<"s5="<<s5<<endl;
s5[0]='g';
cout<<"s5="<<s5<<endl;
cout<<"strlen(s5)="<<s5.Length()<<endl;*/
cout<<boolalpha<<(s3 == s1)<<endl;
}

@ -0,0 +1,232 @@
//
// Created by lenfrex on 2022/4/4.
//
#include <cstring>
#include <algorithm>
#include "String.h"
/**
*
*/
String::String(int size) : length(0), allocSize(size) {
data = new char[size]();
}
/**
* 64
*/
String::String() : String(64) {}
/**
*
*/
String::String(const char *source) : String(source, (int) strlen(source)) {}
/**
*
*/
String::String(const char *source, int length) : String(length + 1) {
strncpy(data, source, length);
data[length] = '\0';
this->length = length;
}
String::~String() {
delete[] data;
data = nullptr;
}
String::String(const String &source) : String(source.data, source.length) {}
/**
* equals函数
* @param source
* @return
*/
bool String::operator==(const String &source) const {
return equals(source.data, source.length);
}
bool String::operator==(const char *source) const {
return equals(source, (int) strlen(source));
}
/**
* Java中String类的equal()
* data是否为nullptrnull则truefalse
* false
* true
*
*/
bool String::equals(const char *source, int sourceLength) const {
// 首先判断两CString对象data成员是否为空指针
if (source == nullptr || this->data == nullptr) {
return source == nullptr && this->data == nullptr;
}
// 字符串长度不等,字符串肯定是不等
if (length != sourceLength) {
return false;
} else {
// 长度相等且data指向相同肯定等
if (source == this->data) {
return true;
}
}
// 以上情况都不符合时才进行逐字比较
// 能执行到此处两者长度肯定相等,因此访问数组不会越界
for (int i = 0; i < length; ++i) {
if (data[i] != source[i]) {
return false;
}
}
return true;
}
String &String::operator=(const String &source) {
if (this == &source) {
return *this;
}
copyData(source.data, source.length);
return *this;
}
String &String::operator=(const char *source) {
copyData(source, (int) strlen(source));
return *this;
}
void String::copyData(const char *source, int sourceLength) {
// 等号右侧空指针的话直接data赋为空指针
if (source == nullptr) {
delete[] data;
this->data = nullptr;
length = 0;
allocSize = 0;
}
// 如果源字符串长度超过了本对象已分配的字符数组大小则重新分配长度合适的字符数组
if (allocSize < sourceLength) {
allocSize = sourceLength + 1;
delete[] data;
data = new char[allocSize];
}
strcpy(data, source);
length = sourceLength;
}
String &String::operator+=(const String &source) {
addString(source.data, source.length);
return *this;
}
String &String::operator+=(const char *source) {
addString(source, (int) strlen(source));
return *this;
}
void String::addString(const char *source, int sourceLength) {
// nullptr不做处理
if (source == nullptr) {
return;
}
// 本对象nullptr的话就直接新分配
if (data == nullptr) {
allocSize = sourceLength + 2 + 1;
this->data = new char[allocSize]();
length = sourceLength;
} else {
length = (int) strlen(data);
}
// 如果拼接后字符长度超过已分配的内存大小,则重新分配data内存大小
if (allocSize < (length + sourceLength + 2)) {
// 保存拼接前的原数据,以便重新分配足够的内存
char *old = new char[length + 1]();
strcpy(old, data);
// 重新分配内存,防止拼接后溢出,2为两个横杠大小
length += sourceLength + 2;
allocSize = length + 1;
delete[] data;
this->data = new char[allocSize]();
strcpy(data, old);
}
strcat(data, source);
}
/**
*
*/
bool String::operator>(const String &compareString) const {
// 首先判断两CString对象data成员是否为空指针,空直接返回false
if (compareString.data == nullptr || this->data == nullptr) {
return false;
}
// 两对象data成员首指向相同则对比谁长
if (compareString.data == this->data) {
return length > compareString.length;
}
// 以上情况都不符合时才进行比较
return strcoll(this->data, compareString.data) > 0;
}
std::ostream &operator<<(std::ostream &outputStream, const String &source) {
return outputStream << source.data;
}
std::istream &operator>>(std::istream &inputStream, String &source) {
// 使用istream.get(char*, int)可以限制读入的长度,防止输入超长的字符串导致溢出,但是空格也会被读入
// 手动分割太麻烦,因此只好先用这种方法了
inputStream >> source.data;
source.length = (int) strlen(source.data);
return inputStream;
}
char String::operator[](int i) {
return (i < length && i >= 0) ? data[i] : '\0';
}
/**
*
*/
String &String::operator+(const char *source) {
int sourceLength = (int) strlen(source);
String target(this->length + sourceLength + 1);
target = this->data;
target += source;
return target;
}
String &String::operator+(const String &source) {
String target(this->length + source.length);
target = this->data;
target += source;
return target;
}
int String::Length() const {
return length;
}

@ -0,0 +1,71 @@
//
// Created by lenfrex on 2022/4/4.
//
#ifndef WORK20220401_STRING_H
#define WORK20220401_STRING_H
#include <iostream>
#include <string>
#include "utility"
using namespace std::rel_ops;
class String {
private:
// 字符数组做字符串
char *data = nullptr;
// 字符串实际长度
int length = 0;
// 已分配的字符数量
int allocSize = 0;
void copyData(const char *source, int sourceLength);
bool equals(const char *source, int sourceLength) const;
void addString(const char *source, int sourceLength);
public:
explicit String(int size);
String(const char *data, int length);
explicit String(const char *source);
String(const String &source);
String();
~String();
bool operator==(const String &source) const;
bool operator==(const char *source) const;
bool operator>(const String &compareString) const;
String &operator+=(const String &source);
String &operator+=(const char *source);
String &operator=(const String &source);
String &operator=(const char *source);
String &operator+(const char *source);
String &operator+(const String &source);
friend std::ostream &operator<<(std::ostream &outputStream, const String &source);
friend std::istream &operator>>(std::istream &outputStream, String &source);
char operator[](int i);
int Length() const;
};
#endif //WORK20220401_STRING_H
Loading…
Cancel
Save