我的C ++中的字符串连接有什么问题?

时间:2014-10-09 13:19:15

标签: c++

我正在通过为嵌入式项目创建一个String类来学习C ++,而我的String类有一个问题'串联。

这是我的主要方法和输出

#include <iostream>
#include "string.hpp"

using namespace std;

int main() {
    String s1("hello "), s2("world");
    String s3 = s1 + s2;
    cout << "s1=" << s1 << endl;
    cout << "s2=" << s2 << endl;
    cout << "s3=" << s3 << endl;
    return 0;
}

s1=hello 
s2=world
s3=hello 

而不是打印出&#34; hello world&#34;,它只打印&#34;你好&#34;

这是我的string.hpp类:

#pragma once
#include <cstring>
#include <iostream>

class String {
public:
    String() : c_str(NULL), len(0)
    {

    }

    String(const String& str) : c_str(new char[str.len]), len(str.len)
    {
        strncpy(c_str, str.c_str, len);
        c_str[len] = '\0';
    }

    String(const char* str) : String(str, strlen(str))
    {
        strncpy(c_str, str, len);
        c_str[len] = '\0';
    }

    String(const char* str, const int n) : len(n), c_str(new char[n+1])
    {
        strncpy(c_str, str, len);
    }

    ~String()
    {
        delete[] c_str;
    }

    const char* get_c_str()
    {
        return c_str;
    }

    bool contains(const String &cmd, const size_t pos)
    {
        return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
    }

    size_t length()
    {
        return len;
    }

    friend std::ostream& operator<<(std::ostream& os, const String obj)
    {
        os << obj.c_str;
        return os;
    }

    friend void swap(String& s1, String& s2)
    {
        using std::swap;
        swap(s1.c_str, s2.c_str);
        swap(s1.len, s2.len);
    }

    bool operator==(const String& str)
    {
        return strncmp(c_str, str.c_str, len) == 0;
    }

    char operator[](const size_t i)
    {
        return c_str[i];
    }

    String& operator=(const String& src)
    {
        String tmp(src);
        swap(*this, tmp);
        return *this;
    }

    String operator+(const String& rhs)
    {
        const size_t new_len = len + rhs.len;
        char* new_c_arr = new char[new_len+1];

        strcpy(new_c_arr, c_str);
        strcat(new_c_arr, rhs.c_str);
        printf("new_c_arr=%s\n", new_c_arr);
        return String(new_c_arr, len);
    }

    String operator+(const char* rhs)
    {
        const size_t new_len = len + strlen(rhs) + 1;
        char* new_c_arr = new char[new_len];
        strcpy(new_c_arr, c_str);
        strcat(new_c_arr, rhs);
        return String(new_c_arr, new_len);
    }

private:
    char* c_str;
    int len;
};

我读到了#3;大3&#34;在SO上寻找类似的问题而不确定是否因为这个问题。

2 个答案:

答案 0 :(得分:0)

这是方法String operator+(const String& rhs)中的问题:

return String(new_c_arr, len);

您需要更改为:

return String(new_c_arr, new_len+1);

您正在初始化返回的String,其长度仅等于第一部分。不是整个串联的字符串。

看到另一个操作员没问题。

顺便说一下,您在char[]operator+中创建了大量新constructor

operator+的情况下,您在每次调用中创建一个新的char[]并传递给string的构造函数(而不是删除之后),并且在构造函数中创建一个新的char[]要存储destructor中删除的字符串,char[]中创建的新operators会泄露。

答案 1 :(得分:0)

此代码以多种方式被破坏。

#pragma once

实际包含警卫比#pragma once更便携。

    String() : c_str(NULL), len(0)
    {

    }

您的默认构造函数使c_str为null;你的其他功能永远不会检查这种情况。请记住,即使是空C字符串也只有一个字符。

    String(const String& str) : c_str(new char[str.len]), len(str.len)
    {
        strncpy(c_str, str.c_str, len);
        c_str[len] = '\0';
    }

您只为str.len分配了c_str个字符,但您正在访问c_str[len]

    String(const char* str) : String(str, strlen(str))
    {
        strncpy(c_str, str, len);
        c_str[len] = '\0';
    }

您委派的构造函数已经执行了一个副本。你为什么再次在这里打strncpy

    String(const char* str, const int n) : len(n), c_str(new char[n+1])
    {
        strncpy(c_str, str, len);
    }

在这里你没有确保你的字符串是以null结尾的。

    const char* get_c_str()
    {
        return c_str;
    }

应标记为const

    bool contains(const String &cmd, const size_t pos)
    {
        return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
    }

同上。而且你没有检查pos是否在范围内。

    size_t length()
    {
        return len;
    }

const

    friend std::ostream& operator<<(std::ostream& os, const String obj)
    {
        os << obj.c_str;
        return os;
    }

obj应该通过const引用传递,而不是通过值传递。

    bool operator==(const String& str)
    {
        return strncmp(c_str, str.c_str, len) == 0;
    }
再次

const,逻辑甚至不正确。按照这个逻辑,"something" == "something else",因为您只是比较第一个len个字符。

    char operator[](const size_t i)
    {
        return c_str[i];
    }

如果要返回副本,则应为const。如果要允许用户修改存储在字符串中的字符,则应返回char &。 (更好的是,有两个单独的重载,一个const和一个非const。)

    String operator+(const String& rhs)
    {
        const size_t new_len = len + rhs.len;
        char* new_c_arr = new char[new_len+1];

        strcpy(new_c_arr, c_str);
        strcat(new_c_arr, rhs.c_str);
        printf("new_c_arr=%s\n", new_c_arr);
        return String(new_c_arr, len);
    }

您正在使用错误的长度构建新字符串,并且还会泄漏new_c_arr。这个函数应该是const(实际上应该用operator+=实现,而你没有。)

    String operator+(const char* rhs)
    {
        const size_t new_len = len + strlen(rhs) + 1;
        char* new_c_arr = new char[new_len];
        strcpy(new_c_arr, c_str);
        strcat(new_c_arr, rhs);
        return String(new_c_arr, new_len);
    }

再次泄漏new_c_arr;此外,new_len此处包含空终止符,而另一个operator+中的版本则不包括空终止符。获取长度的构造函数似乎不包含null终止符作为长度的一部分。