Сохранение массива char в классе и его возврат
Вопрос
Мне нужно сохранить массив char внутри класса, а затем вернуть его. Я должен признать, что я немного запутался в указателях и перепробовал все, что мог придумать, но не смог заставить его работать. Вот что у меня есть:
#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 () будет хранить строку " Тестирование " внутри класса getName () должна возвращать «Тестирование». Но вместо этого я получаю только первую букву Т. Что я делаю не так?
Полагаю, мне следует использовать строки std, но сначала я бы хотел понять, почему это не работает. Насколько я знаю, это должно работать и с массивами символов?
Решение
Просто верните указатель:
const char* Test::getName() const
{
return m_name;
}
и добавьте конструктор для class Test
, который завершит инкапсулированный массив нулем:
Test::Test()
{
m_name[0] = 0;
}
чтобы не возникало проблем, если кто-то создает экземпляр class Test
и не вызывает setName ()
для экземпляра.
Другие советы
В Test :: getName ()
вы просто возвращаете один символ (первый символ). Вместо этого вы должны вернуть адрес первого символа, с которого начинается строка, т.е. изменить тип возвращаемого значения на char *
, а оператор возврата - return m_name;
Если у вас есть указатель, p
, оператор разыменования указателя *
" следует " указатель, поэтому выражение * p
оценивает любой объект, на который указывает указатель.
Во многих ситуациях имя массива, например m_name
, может вести себя как указатель. Таким образом, * m_name
соответствует первому char
в массиве, поскольку это тип, имя массива которого, когда интерпретируется как указатель, указывает на.
Поскольку строки в C представлены в виде указателей на символы, вы не должны разыменовывать указатель, а возвращать его в целости.
Многие предлагали использовать strncpy ()
для записи входной строки в ваш массив, так как она выполняет (вроде) проверку границ. Однако, это не оптимально, его семантика нечетна, и копирование строки в ограниченный буфер на самом деле не то, для чего она была разработана. Лучше выяснить, есть ли в вашей среде различные функции snprintf ()
, и использовать их следующим образом:
snprintf(m_name, sizeof m_name, "%s", name);
И безопаснее использовать strncpy ()
, чем strcpy ()
в void Test :: setName ()
Если вы хотите, чтобы это был 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 & amp;.