Запись массива символов с нулевым завершением в класс объектов с массивом символов

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

Мне нужно создать строковый класс, в котором хранится содержимое массива символов с нулевым завершением. Если длина ввода больше 32, сохраните его в куче, иначе сохраните в стеке.

Сейчас я занят конструктором:

 #include "SString.h"   
 #include <iostream>

using namespace std;

SString::SString(const char* input)
{
    // Determine length of input
    int length = 0;
    while (input[length] != '\0')
    {
        length++; 
    }
    // Check for zero length
    if (length == 0)
    {
        st_string[1] = ' ';
    }
    // Based on length, make heap string or use stack string
    if(length > 32) 
    {
        int i = 0;
        p_string = new char[length];
        while (i != length) //write string with input
        {
            p_string[i] = input[i];
            i++;
        }
    }
    else 
    {
        int i = 0;
        while(i != length) //write string with input
        {
            st_string[i] = input[i];
            i++;
        }
    }
    cout << "saved string:" << endl;
    cout << p_string << endl;
} 

Теперь я проверил это, вызвав SimpleString с такой строкой в ​​main:

 SString("test"); // or something

Это работает, помещая строку либо в st_string, либо в p_string, но в обоих случаях сохраненная строка имеет больше (странных неопределенных) символов в конце. Итак, в случае «теста» я получаю тест № 54 или что-то в этом роде.

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


person user1802706    schedule 07.11.2012    source источник


Ответы (3)


Ваши циклы while (i != length) не копируют окончательный \0 внутри нового массива символов. Вы должны изменить их на

while (i <= length) //write string with input
{
    appropriate_string[i] = input[i];
    i++;
}
person halex    schedule 07.11.2012

после вашего цикла while, где вы копируете символы один за другим, сразу после этого цикла вам нужно добавить символ конца строки к вашей переменной, например

st_string[i] = '\0';
person Oxi    schedule 07.11.2012

Я вижу несколько проблем с вашим кодом. Во-первых, в чем конкретно смысл:

// Check for zero length
if (length == 0)
{
    st_string[1] = ' ';
}

? Если остальная часть кода достаточно надежна, пустая строка будет обрабатываться естественным образом. Все, что вы здесь делаете, — это делаете так, чтобы ваш класс нельзя было надежно использовать, если в исходной строке есть пробелы.

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

t e s t \0

а length равно 4. Это означает, что ваш нижний цикл будет копировать 4 символа в локальный массив. Вы еще не видите здесь проблемы?

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

Наоборот, на самом деле. Видите ли, часть, которую я пропустил, это то, что идет после вашей строки в памяти. Оригинал:

t e s t \0 # # # #

где # - это в основном случайные байты. Строка копируется так, что она становится:

t e s t # # # #

потому что вы не скопировали файл \0. Цикл, который считывает строку обратно, будет продолжаться до тех пор, пока не встретится с нулевым байтом, но у вас нет возможности узнать, где он будет, потому что вы сами его туда не поместили. Если это произойдет, чтобы попасть в память, чтобы это выглядело так:

t e s t \54 \0 # # #

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

person jfmatt    schedule 07.11.2012
comment
Это проясняет это для меня. Спасибо за комментарии, ребята! - person user1802706; 07.11.2012