Хобрук: Ваш путь к мастерству в программировании

Классы C++, Объектно-ориентированное программирование

У меня есть очень простой класс с именем человека, который приведен ниже, у меня проблема только с двумя функциями, то есть функцией setstring() и функцией setname(), я вызываю функцию setstring() из функции setname. Единственная проблема, когда в основной функции я пишу
Object.setname(“Zia”);
Результат в порядке, как показано на экране вывода. Теперь, когда я пишу
Object.setname("Zia ur Rahman");
Ничего не отображается, так как вы видите экран вывода.

Я знаю, что проблема заключается в том, что я передаю указатель имени в функцию setstring(), но я не понимаю, пожалуйста, объясните подробно, что здесь происходит.

#include<iostream.h>
class person
{
char* name;
public:
person();
void setname(const char*);
void setstring(const char*, char*);
void print()const;
};
person::person()
{
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
}
void person::setstring(const char* s, char*p)
{
if(s!=NULL)
{
delete[] p;
p=new char[strlen(s)];
strcpy(p,s);
p[strlen(s)]='\0';
}
}
void person::setname(const char* n)
{
setstring(n, name);//passing data member name
}
void person::print()const
{
cout<<"Name: "<<name<<endl;
}
main()
{
person object;
object.setname("Zia ur Rahman");
object.print();
system("pause");
}

замещающий текст http://img264.imageshack.us/img264/8867/inheritanceimage004.jpg< /а>

замещающий текст http://img263.imageshack.us/img263/3770/inheritanceimage003.jpg< /а>

21.01.2010

  • Просто скомпилировал и запустил код. Это немного грязно, но, кажется, работает хорошо. 21.01.2010

Ответы:


1

Конкретная причина того, что ничего не печатается, заключается в том, что в setstring p является копией указателя имени, а не ссылкой на него. Попробуйте изменить подпись setstring на:

void setstring(const char* s, char*& p);

(обратите внимание на &).

См. другие ответы для других значительных ошибок в коде - если эти проблемы не будут устранены, вы, вероятно, получите сбои или странное поведение.

И если целью кода не является просто изучение динамических массивов, используйте вместо этого std::string :-).

21.01.2010
  • Хорошее место, я не видел его, пока не посмотрел снова :) 21.01.2010

  • 2

    Если вы хотите правильно программировать объектно-ориентированное программирование на C++, вам, возможно, следует избегать прямого управления указателями, а использовать строковый класс STL и использовать ссылки вместо указателей. Тогда вам должно быть легче, и ваш источник должен выдавать правильный результат.

    В противном случае проверьте свой конструктор класса person, массив имен имеет всего 3 элемента, но вы ссылаетесь на 4-й (индексы 0-2!). Также в методе setstring() вы не выделяете достаточно места для завершающего '\0' в массиве!

    21.01.2010
  • В указателях нет ничего плохого, я бы сказал, держитесь подальше от ссылок, они могут привести к любым проблемам. 21.01.2010
  • То же самое, конечно, относится и к указателям ;) Но здесь не место начинать флейм, у меня был хороший и плохой опыт с обоими типами. Просто у меня было больше хороших со ссылками, но это мой личный опыт за эти годы. 21.01.2010
  • Нет проблем :) Я не в стиле полицейского патруля. Было просто любопытно. 21.01.2010

  • 3

    Для начинающих:

    name=new char[3];
    strcpy(name,"NILL");
    name[3]='\0';
    

    имя состоит из трех элементов — вы обращаетесь с ним так, как будто оно состоит из пяти. В том же духе:

    p=new char[strlen(s)];
    

    должно быть:

    p=new char[strlen(s) + 1];
    

    На самом деле эта функция совершенно неверна — предполагается, что вы копируете строку в «имя», а не в таинственный параметр «p». Если вам действительно нужна эта функция, то "p" должен быть указателем на указатель или ссылкой на указатель.

    21.01.2010
  • O ДА, хорошо, я делаю это правильно, но все равно есть та же проблема 21.01.2010
  • когда я пишу object.setname(zia) вывод: Name: zia когда я пишу object.setname(Zia ur Rahman) вывод ничего 21.01.2010

  • 4

    Вы думали об использовании std::string из STL?

    Хотя первая проблема, которую я вижу, заключается в следующем.

    person::person()
    {
    name=new char[3];
    strcpy(name,"NILL");
    name[3]='\0';
    }

    Вы выделяете массив символов, размер массива составляет 3 символа, затем вы копируете в него «NILL» с помощью strcpy, поэтому вы заполняете массив всеми символами, но без нулевого терминатора \0. «NILL» — это константная строка, и она имеет нулевой терминатор, который является неявным, но не отображается, например, «NILL\0». \0 — это управляющий символ, который используется для обозначения конец строки. Затем у вас есть индекс за пределами при доступе к 3-му элементу массива имен, когда размер вашего массива равен 3.

    Чтобы помочь вам найти другие части, которые могут работать неправильно, вот несколько ссылок на используемые вами функции.

    strcpy
    strlen

    strcpy скопирует всю строку из одного буфера в другой, включая управляющий символ нулевого конца.

    Strlen вернет количество символов между началом строки и конечным нулевым символом. Хотя он не будет считать нулевой символ символом. Вот почему вы увидите предложения с strlen(string)+1 для включения нулевого терминатора.

    Хотя у вас все хорошо, продолжайте в том же духе, вы поймете эти маленькие хитрости при использовании функций стандартной библиотеки.

    21.01.2010

    5

    Предположим, что s имеет 5 символов. Затем new char[strlen(s)]; выделяет память из 5 символов. Тогда p[strlen(s)]='\0' эквивалентно p[5]=0. Это очень очень плохо. p[5] не существует.

    void person::setstring(const char* s, char*p) 
    { 
    if(s!=NULL) 
    { 
    delete[] p; 
    p=new char[strlen(s)]; 
    strcpy(p,s); 
    p[strlen(s)]='\0';    //<<<< LOOK! Out of range
    } 
    } 
    
    21.01.2010

    6

    Это скорее C, чем C++ код. Существует эквивалент С++:

    #include <string>
    #include <iostream>
    
    class person
    {
        std::string name_;
    public:
        person();
        //preferable design is to set object invariant in appropriate constructor
        explicit person(const std::string &name);
        std::string get_name() const;
        void set_name(const std::string &name);
        void print()const;
    };
    person::person()
     : name_("NILL")
    {}
    
    person::person(const std::string &name)
    : name_(name)
    {}
    
    std::string person::get_name() const
    {
        return name_;
    }
    
    void person::set_name(const std::string &name)
    {
        name_ = name;
    }
    void person::print()const
    {
        std::cout<<"Name: "<<name_<<std::endl;
    }
    
    int main()
    {
        person person1;
        person1.set_name("Zia ur Rahman");
        person1.print();
    
        //this is better design decision
        //because after constructor we have valid object
        person person2("Zia ur Rahman");
        person2.print();
        std::cin.get();
        return 0;
    }
    
    21.01.2010
    Новые материалы

    Управление DOM для чайников вроде меня
    Одной из первых вещей, которую мы рассмотрели, когда начали изучать Javascript во Flatiron, была модель DOM. Кто он? Чем он занимается? Он больше машина, чем человек? Ну да довольно много. ДОМ..

    Что такое структура данных?
    Структура данных хранит и извлекает данные. Все, что обеспечивает эти две функции, является структурой данных . Период. Вы можете пропустить оставшуюся часть статьи, если ответ..

    мои январские чтения по программированию
    Эрик Эллиот Программирование приложения JavaScript Эл Свейгарт «Автоматизируйте скучные вещи с помощью Python» Прогрессивное веб-приложение Google..

    Создание ассоциаций секвелизации с помощью инструмента командной строки Sequelize
    Sequelize - популярный, простой в использовании инструмент объектно-реляционного сопоставления (ORM) JavaScript, который работает с базами данных SQL. Довольно просто начать новый проект с..

    Искусственный интеллект в юридической отрасли - пример прогнозирования судебных решений с помощью глубокого обучения
    На протяжении всей истории люди полагались на суды, присяжных, королей и королев в отправлении правосудия. Сегодня способность судов обеспечивать справедливое и быстрое правосудие для своих..

    Введение в машинное обучение для обнаружения аномалий (часть 1)
    Тщательно созданный, тщательно спроектированный ресурс для специалистов по данным. Часть 1 Главы 03 из Руководства по машинному обучению для обнаружения аномалий Внимание! Прежде чем вы..

    Начало работы с Pulumi в Digital Ocean
    Цифровой океан (ДО) — отличная альтернатива многим другим поставщикам облачных услуг. DO предоставляет простой и понятный пользовательский интерфейс, упрощающий управление инфраструктурой и..