自定义字符串缺陷

时间:2015-05-25 23:36:38

标签: c++ string char comparison

所以我的问题是当我与修改后的字符串值进行比较,以及未修改的字符串值时,我没有得到 true 的预期结果,而是即可。我已经重载了逻辑比较运算符,但这不是我想要做的,这无助于解决我的答案,但它确实有效,但是当我在 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] = '\0';
    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] = '\0';
    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] != '\0')
    {
        ++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] = '\0';
    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

未经修改的示例

#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));
}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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;
}