Путаница с предложением из учебника по инициализации неструктурированного массива C ++ - PullRequest
0 голосов
/ 14 мая 2019

Я читаю книгу по программированию на C ++. Я натолкнулся на предложение из книги, которое гласит: «Помимо того, что метод инициализации массива не является утомительным, вы можете изменить любую строку, не боясь случайно забыть изменить размер массива». Когда я пишу код для проверки этого предложения, а затем запускаю код в конце выполнения, я получаю сообщение об ошибке, что .exe перестал работать. И с другим кодом, показанным в моем вопросе, это дает несовместимую ошибку типа, то есть размеры новой строки не совпадают с размерами массива char.

Итак, я проверил предложение, чтобы убедиться, что мое толкование было правильным. Смотрите мой код ниже.

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int main()
{
    char s[] = "";
    s = "Hello, my name is Mickey Mouse.";
    cout << s << endl;
    s = "Hello, my name is Mickey Mouse. I am 83 years old."
    cout << s << endl;

}

Следующий пример кода:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int main()
{
    char s[] = "";
    cout << "Enter a string" << endl;
    cin.getline(s, 50);
    cout << s;
    cout << "How old are you" << endl;
    cin.getline(s, 50);
    cout << s;
}

Я ожидал, что программа успешно запустится, но вместо этого произойдет сбой.

1 Ответ

1 голос
/ 14 мая 2019

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

char s[] = ""; - это то же самое, что и char s[1] = {'\0'};, который содержит только один элемент, нулевой символ. Книга просто говорит, что в этом случае она определяет размер для вас и копирует его в стек.

Затем, когда вы используете cin.getline(s, 50); и сообщаете ему, что на самом деле его длина составляет 50 символов, он может записывать после конца массива и перезаписывать другие вещи, которые компилятор поместил в стек, вызывая повреждение.

Часто для таких вещей, как getline, если у вас есть выделенный массив из стека, sizeof может использоваться для безопасного определения размера, который будет учитывать будущие изменения.

cin.getline(s, sizeof(s));

Но в C ++ почти всегда лучше использовать std::string для строк и либо std::vector для массивов динамического размера, либо std::array для массивов фиксированного размера. Помимо прямой поддержки гораздо большего числа функций, они также управляют памятью и позволяют избежать многих распространенных ошибок.

std::string line;
std::getline(std::cin, line);
...