自定义字符串缺陷

Custom String Deficiency

本文关键字:缺陷 字符串 自定义      更新时间:2023-10-16

所以我目前的问题是当我与修改的字符串值和未修改的字符串值进行比较时,我没有得到true的预期结果,而是false。我已经重载了逻辑比较运算符,但这不是我想做的,这不会帮助解决我的答案,但它确实有效,但是当我在std::map中使用它时,它不起作用。

编辑:我需要知道的是std::map通过迭代在逻辑上比较两个对象。

String.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
enum Pos
{
    BEGINNING,
    ENDING
};
class String
{
public:
    char *chars;
    String();
    String(char *chars);
    String(const char *chars);
    String(unsigned int size);
    unsigned int Length();
    String SubStr(unsigned int start, unsigned int end);
    String SubStr(unsigned int start);
    unsigned int HasStr(const char *chars);
    unsigned int HasStrInv(const char *chars);
    int FindFirst(const char *chars, Pos pos);
    int FindLast(const char *chars, Pos pos);
    std::vector<String> Split(const char *delimeter);
    String operator+(const char *chars);
    String operator=(const char *chars);
    String operator+=(const char *chars);
    bool operator==(const char *chars);
    bool operator==(String str);
    operator char*();
    static bool Equals(const char *a, const char *b);
    static unsigned int Length(const char *chars);
    static String Concate(const char *a, const char *b);
};
String operator+(const char *a, String b);
bool operator==(const char *a, String b);

String.cpp

#include "String.h"
String::String()
    : chars("")
{
}
String::String(char *chars)
{
    this->chars = chars;
}
String::String(const char *chars)
{
    this->chars = const_cast<char *>(chars);
}
String::String(unsigned int size)
{
    chars = new char[size];
}
unsigned int String::Length()
{
    return Length(chars);
}
String String::SubStr(unsigned int start, unsigned int end)
{
    unsigned int size = ((++end) - start) + 1;
    char *buffer = new char[size];
    for (unsigned int i = start; i < end; i++)
    {
        buffer[i - start] = chars[i];
    }
    buffer[size - 1] = '';
    return String(buffer);
}
String String::SubStr(unsigned int start)
{
    unsigned int size = (Length() - start);
    char *buffer = new char[size];
    for (unsigned int i = start; i < Length(); i++)
    {
        buffer[i - start] = chars[i];
    }
    buffer[size] = '';
    return String(buffer);
}
unsigned int String::HasStr(const char * chars)
{
    unsigned int d = 0, count = 0;
    for (unsigned int i = 0; i < strlen(this->chars); ++i)
    {
        if (this->chars[i] == chars[d])
        {
            ++d;
            if (d >= strlen(chars))
            {
                ++count;
                d = 0;
            }
        }
        else
        {
            d = 0;
        }
    }
    return count;
}
unsigned int String::HasStrInv(const char * chars)
{
    bool greater = false;
    unsigned int i, d = 0, start = 0, count = 0;
    for (i = 0; i < Length(); ++i)
    {
        if (this->chars[i] == chars[d])
        {
            d++;
            if (d >= strlen(chars))
            {
                if (greater)
                {
                    greater = false;
                    ++count;
                }
                start = i + 1;
                d = 0;
            }
        }
        else
        {
            greater = true;
            d = 0;
        }
    }
    if (start - 1 < Length() - 1)
    {
        ++count;
    }
    return count;
}
int String::FindFirst(const char * chars, Pos pos)
{
    unsigned int d = 0;
    for (unsigned int i = 0; i < strlen(this->chars); ++i)
    {
        if (this->chars[i] == chars[d])
        {
            ++d;
            if (d >= strlen(chars))
            {
                switch (pos)
                {
                case Pos::BEGINNING:
                    return i - (strlen(chars) - 1);
                    break;
                case Pos::ENDING:
                    return i;
                    break;
                }
            }
        }
        else
        {
            d = 0;
        }
    }
    return -1;
}
int String::FindLast(const char * chars, Pos pos)
{
    unsigned int d = strlen(chars) - 1;
    for (unsigned int i = strlen(this->chars); i > 0; --i)
    {
        if (this->chars[i] == chars[d])
        {
            --d;
            if (d >= strlen(chars))
            {
                switch (pos)
                {
                case Pos::BEGINNING:
                    return i;
                case Pos::ENDING:
                    return i + (strlen(chars) - 1);
                }
            }
        }
        else
        {
            d = strlen(chars) - 1;
        }
    }
    return -1;
}
std::vector<String> String::Split(const char *delimeter)
{
    unsigned int size = HasStrInv(delimeter);
    std::vector<String> buffer(size);
    bool greater = false;
    unsigned int i, d = 0, start = 0, count = 0;
    for (i = 0; i < Length(); ++i)
    {
        if (this->chars[i] == delimeter[d])
        {
            d++;
            if (d >= strlen(delimeter))
            {
                if (greater)
                {
                    greater = false;
                    buffer[count++] = SubStr(start, i - strlen(delimeter));
                }
                start = i + 1;
                d = 0;
            }
        }
        else
        {
            greater = true;
            d = 0;
        }
    }
    if (start - 1 < Length() - 1)
    {
        buffer[count] = SubStr(start, Length() - 1);
    }
    return buffer;
}
String String::operator+(const char *chars)
{
    return Concate(this->chars, chars);
}
String String::operator=(const char *chars)
{
    this->chars = const_cast<char *>(chars);
    return *this;
}
String String::operator+=(const char * chars)
{
    this->chars = Concate(this->chars, chars);
    return *this;
}
bool String::operator==(const char * chars)
{
    return Equals(this->chars, chars);
}
bool String::operator==(String str)
{
    return Equals(chars, str);
}
String::operator char*()
{
    return chars;
}
bool String::Equals(const char *a, const char *b)
{
    if (Length(a) == Length(b))
    {
        for (unsigned int i = 0; i < Length(a); ++i)
        {
            if (a[i] != b[i])
                return false;
        }
        return true;
    }
    return false;
}
unsigned int String::Length(const char * chars)
{
    unsigned int i = 0;
    while (chars[i] != '')
    {
        ++i;
    }
    return i;
}
String String::Concate(const char *a, const char *b)
{
    unsigned int size = strlen(a) + strlen(b) + 1;
    char *buffer = new char[size];
    for (unsigned int i = 0; i < strlen(a); ++i)
    {
        buffer[i] = a[i];
    }
    for (unsigned int i = strlen(a); i < size - 1; ++i)
    {
        buffer[i] = b[i - strlen(a)];
    }
    buffer[size - 1] = '';
    return String(buffer);
}
String operator+(const char *a, String b)
{
    return String::Concate(a, b);
}
bool operator==(const char *a, String b)
{
    return String::Equals(a, b);
}

示例修改

#include <iostream>
#include "String.h"
int main(int argc, char *argv[])
{
    String s = "Textures/SpaceShip.png";
    String a = s.SubStr(s.FindLast("/", Pos::ENDING) + 1);
    if (a.chars == "SpaceShip.png")
    {
        std::cout << "Equals" << std::endl;
    }
    else
    {
        std::cout << "Not Equals" << std::endl;
    }
    return 0;
}

Not Equals

例子Un-Modified

#include <iostream>
#include "String.h"
int main(int argc, char *argv[])
{
    String s = "Textures/SpaceShip.png";
    String a = "Textures/SpaceShip.png";
    if (s.chars == a.chars)
    {
        std::cout << "Equals" << std::endl;
    }
    else
    {
        std::cout << "Not Equals" << std::endl;
    }
    return 0;
}

Equals

TextureManager.cpp

#include "TextureManager.h"
std::map<char *, Texture2D> TextureManager::textures;
Texture2D * TextureManager::GetTexture(String path)
{
    auto it = textures.find(path);
    if (it == textures.end())
        throw new std::exception("LWE: Texture not found. " + path);
    return &it->second;
}
void TextureManager::DeleteTexture(String path)
{
    auto it = textures.find(path);
    if (it == textures.end())
        throw new std::exception("LWE: Texture not found. " + path);
    glDeleteTextures(1, &it->second.id);
    textures.erase(it);
}
void TextureManager::InsertTexture2D_PNG(String filePath)
{
    Texture2D texture;
    std::vector<unsigned char> data;
    FileInfo fi = IOManager::ReadFile(filePath);
    if (decodePNG(data, texture.width, texture.height, (unsigned char *)fi.data, fi.size, true) != 0)
        throw new std::exception("Failed to decode png." + filePath);
    glGenTextures(1, &texture.id);
    glBindTexture(GL_TEXTURE_2D, texture.id);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
    textures.insert(std::make_pair(filePath.SubStr(filePath.FindLast("/", Pos::ENDING) + 1), texture));
}

std::map不使用operator ==,它使用operator <。您需要实现该操作符,以便能够使用您的String类型作为映射的键。

这里是一个例子-注意参数和函数的const -这是std::map所需要的。在本例中,这意味着您还需要将Length更改为const:

bool String::operator < (const String &str) const
{
    unsigned int myLength = Length();
    unsigned int strLength = str.Length();
    for (unsigned int i = 0; i < myLength && i < strLength; i++)
    {
        if (chars[i] < str.chars[i])
            return true;
        else if (chars[i] > str.chars[i])
            return false;
    }
    if (myLength < strLength)
        return true;
    return false;
}

和使用它:

std::map<String, int> myMap;
myMap["abc"]++;
myMap["abc"]++;
myMap["def"]++;
for (auto & entry : myMap)
{
    std::cout << entry.first.chars << ":" << entry.second << std::endl;
}

不能使用(s.c haars == a.c haars)比较两个字符串,它比较两个指针的地址,并且对于两个不同的字符串对象总是返回false。