Строка не проходит через аргумент конструктора

0
#include<iostream>
using namespace std;
#include<conio.h>

class student{
    int roll_no;
    char name[15];
    float per;
public:
    student(int a, char b[15], float c){
        roll_no = a;
        name[15] = b[15];
        per = c;
    }
    ~student(void){
        cout << "Student Details : \n\n"
             << "Roll No : " << roll_no << "\n"
             << "Name : " << name[15] << "\n"
             << "Percentage : " << per << endl;
    }
};

int main(){
    student s(60,"Suraj Jadhav",25.25);
    getch();
    return 0;
}

Выход: Студенческая информация:

Roll No : 60
Name : 
Percentage : 25.25

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

Теги:
string
arguments

4 ответа

4
Лучший ответ

когда вы заявляете

char name[15];

name - массив из 15 символов. Параметр b является указателем ("ожидается", чтобы указать массив из 15 символов). Заявление

name[15] = b[15];

скопируйте только 16-й элемент массива, на который указывает "b" на 16-й элемент в массиве "name" (число начинается с нуля), так как в массиве 15 элементов, здесь нет определенного поведения (так же, когда вы напечатать имя [15]).

В C вы должны копировать каждый символ один за другим. Такие функции, как strcpy, позаботятся об этом, может быть опасно, если назначение недостаточно велико для размещения источника. В C++ вы должны попытаться избежать использования массива char и использовать std :: string, вместо этого возьмите копию с безопасностью. Вы также должны использовать список инициализаторов (синтаксис для инициализации члена в конструкторе). Например:

#include<iostream>
using namespace std;
#include<conio.h>

class student{
    int roll_no;
    string name;
    float per;
public:
    student(int a, const string &b, float c) 
         : roll_no(a), name(b), per(c)
    {
    }
    ~student(){
        cout << "Student Details : \n\n"
             << "Roll No : " << roll_no << "\n"
             << "Name : " << name << "\n"
             << "Percentage : " << per << endl;
    }
};

int main(){
    student s(60,"Suraj Jadhav",25.25);
    getch();
    return 0;
}

Примечание: #include <conio.h> не является стандартным C/C++, это конкретный заголовок MS-DOS. Старайтесь избегать, если это возможно :)

  • 0
    Это должен быть комментарий. Это не отвечает на вопрос (что бы это ни было).
  • 0
    @ 0x499602D2 "Проблема вызвана использованием строк в стиле C, когда вы не понимаете, как они работают. Вместо этого используйте строки в стиле C ++, и у вас не возникнет этой проблемы." является верным ответом, IMO, если только / до тех пор, пока OP не пояснит, что по какой-то причине требуются символьные массивы. Это примерно то, что в этом ответе.
Показать ещё 7 комментариев
3
name[15] = b[15];

не будет копировать строку. Он просто скопирует один символ из b чтобы name, а именно индекс в индексе 15. (Фактически это фактически неопределенное поведение, поскольку каждый массив имеет только индексы 0..14.) Попробуйте следующее:

strcpy(name, b);
2

Вы не должны использовать необработанные указатели, если вы их не понимаете, вместо этого используйте std :: string. В любом случае, ваш конструктор может быть зафиксирован следующим образом:

student(int a, const char *b, float c){
    roll_no = a;
    strncpy( name, b, sizeof( name ) );
    per = c;
}

Существует проблема с strncpy() когда длина строки (то, что возвращает strlen() и исключая \0 terminator), где b указывает, что оно равно или длиннее размера name, не помещает терминатор \0 в целевую строку. Таким образом, код может быть более безопасным:

student(int a, const char *b, float c){
    roll_no = a;
    name[ sizeof( name ) - 1 ] = 0;
    strncpy( name, b, sizeof( name ) - 1 );
    per = c;
}

Снова работа с необработанными указателями довольно сложная, и вам нужно глубоко понять, что там происходит, чтобы написать безопасный код. Использование std :: string в C++ сделает вашу жизнь намного проще.

  • 0
    Возможно, вы захотите рассмотреть, что это делает с name когда b[] длиннее sizeof(name) -chars, включая его терминатор nulchar. Я спасу тебя от ожидания; это не завершает name[] . Любые будущие библиотечные функции сканирования строк (такие как strcpy , strlen , strcmp и т. Д.), strcmp будут их использовать, будут вызывать поиск неопределенного поведения для указанного терминатора.
  • 0
    @WhozCraig спасибо, добавил более безопасный вариант, я думаю, что должен быть другой вариант strncpy, который всегда помещает терминатор в цель.
1

Вместо недействительного оператора

name[15] = b[15];

вы должны использовать стандартную функцию strcpy, объявленную в заголовке

std::strcpy( name, b );

Также правильное объявление конструктора будет выглядеть следующим образом

student(int a, const char b[15], float c);

или

student(int a, const char b[], float c);

или

student(int a, const char *b, float c);

Эти три объявления объявляют одну и ту же функцию.

Чтобы сделать конструктор безопасным, я бы определил его как

student(int a, const char b[], float c){
        roll_no = a;
        std::strncpy( name, b, 15 );
        name[14] = '\0';
        per = c;
}

Также неплохо назначить имя магическому номеру 15 либо с помощью перечислителя, либо с помощью статической константы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню