GOOGLE ADS

четверг, 28 апреля 2022 г.

Странные символы в скопированном/усеченном массиве символов

#include <iostream>
using namespace std;
void truncate(char* s1, char* s2, int n) {
for (int i = 0; i < n; i++) {
s2[i] = s1[i];
}
}
int main() {
char s1[15] = "Hello World";
char s2[10];
int n{ 5 };
truncate(s1, s2, n);
cout << s2; // this should display: Hello
}

Когда я запускаю это в Visual Studio, я получаю следующий вывод:

Hello╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠Hello World

Но когда я запускаю его с помощью онлайн-компилятора (Online GDB), вывод нормальный:

Hello

Я знаю, что это связано с \0терминатором, но я просто не могу этого понять.


Решение проблемы

Ваша truncateфункция не добавляет требуемый nulсимвол завершенияs2 в строку назначения ( ). Таким образом, когда вы вызываете cout, mainэто будет продолжать печатать символы до тех пор, пока не найдет ожидаемый nul(нулевой) символ в каком-то неуказанном месте после инициализированных мусором данных, которые ранее существовали в частях s2локального массива, которые не были явно заданы вашим функция. (Это неопределенное поведение, и на самом деле может отображаться почти все; программа также может аварийно завершать работу, если coutвызов пытается прочитать память, к которой у него нет необходимого доступа).

Чтобы исправить это, просто добавьте этот символ nul(ноль или '\0') в конец строки в truncateфункции. Предполагая, что вы не выходите за границы массива, вы можете использовать «оставшееся» значение индекса цикла iдля доступа к требуемому элементу; но для этого вам нужно будет объявить int i пределы цикла for:

void truncate(char* s1, char* s2, int n)
{
int i; // Must be declared outside the FOR loop...
for (i = 0; i < n; i++) {
s2[i] = s1[i];
}
s2[i] = '\0'; //... so we can use it here.
}

Примечание. Другим способом (но, по-видимому, запрещенным вашим учителем) было бы установить все элементы s2массива в mainноль перед вызовом вашей truncateфункции:

char s2[10] = ""; // Set ALL elements to zero

Некоторые компиляторы (по-видимому, включая используемый вами онлайн) будут «неявно» устанавливать элементы неинициализированных локальных массивов равными нулю; но никогда не полагайтесь на это: это не является частью стандарта C++, и компиляторы не обязаны обеспечивать такое поведение.

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...