Сохранение массива char в классе и его возврат - PullRequest
1 голос
/ 29 октября 2009

Мне нужно сохранить массив символов внутри класса, а затем вернуть его. Я должен признать, что я немного запутался в указателях и перепробовал все, что мог придумать, но не смог заставить его работать. Вот что у меня есть:

#include <iostream>
using namespace std;

class Test {
public:
    void setName(char *name);
    char getName();
private:
    char m_name[30];
};

void Test::setName(char *name) {
    strcpy(m_name, name);
}

char Test::getName() {
    return *m_name;
}

void main() {

    Test foobar;
    char name[] = "Testing";
    foobar.setName(name);
    cout << foobar.getName();
}

Конечно, я ожидаю, что setName () будет хранить строку "Testing" внутри класса, а getName () должна вернуть "Testing". Но вместо этого я получаю только первую букву Т. Что я делаю не так?

Полагаю, мне следует использовать строки std, но сначала я бы хотел понять, почему это не работает. Насколько я знаю, это должно работать и с массивами символов?

Ответы [ 5 ]

6 голосов
/ 29 октября 2009

Просто верните указатель:

const char* Test::getName() const
{
    return m_name;
}

и добавьте конструктор для class Test, который завершит инкапсулированный массив нулем:

Test::Test()
{
    m_name[0] = 0;
}

чтобы вы не спрашивали о неприятностях, если кто-то создает экземпляр class Test и не вызывает setName() в экземпляре.

1 голос
/ 29 октября 2009

Если у вас есть указатель, p, оператор разыменования указателя * "следует" за указателем, поэтому выражение *p вычисляет любой объект, на который указывает указатель.

Во многих ситуациях имя массива, такое как m_name, может вести себя как указатель. Таким образом, *m_name соответствует первому char в массиве, так как это тип, имя массива которого, когда интерпретируется как указатель, указывает на.

Поскольку строки в C представлены в виде указателей на символы, вы не должны разыменовывать указатель, а возвращать его в целости.

Многие предлагали использовать strncpy() для записи входной строки в ваш массив, так как он выполняет (вроде) проверку границ. Однако, это не оптимально, его семантика нечетна, и копирование строки в ограниченный буфер на самом деле не то, для чего она была разработана. Лучше выяснить, есть ли в вашей среде различные функции snprintf(), и использовать их следующим образом:

snprintf(m_name, sizeof m_name, "%s", name);
1 голос
/ 29 октября 2009

В Test::getName() вы просто возвращаете один символ (первый символ). Вместо этого вы должны вернуть адрес первого символа, с которого начинается строка, т.е. изменить тип возвращаемого значения на char*, а оператор возврата на return m_name;

0 голосов
/ 29 октября 2009

Если вы хотите, чтобы это был C ++, просто не используйте указатели на символы, если только у вас нет для этого особой причины!

Переключитесь с указателя на символ в std :: string и посмотрите, решит ли это вашу проблему:

#include <iostream>
#include <string>
using namespace std;

class Test {
public:
    void setName(std::string name);
    std::string getName();
private:
    std::string m_name;
};

void Test::setName(std::string name) {
    m_name = name;
}

std::string Test::getName() {
    return m_name;
}

void main() { 
    Test foobar;
    foobar.setName("Testing");
    cout << foobar.getName();
}

Для бонусных баллов укажите тип параметра в setName как const std :: string &.

0 голосов
/ 29 октября 2009

И безопаснее использовать strncpy(), чем strcpy() в void Test::setName()

...