Первый элемент указателя загрязнен C ++ - PullRequest
3 голосов
/ 04 апреля 2020

У меня есть этот фрагмент кода, который помещает случайную строку в массив указателя символа:

char * str[100] = {0};
const int elems = sizeof(str)/sizeof(str[0]),size=5;

srand(time(0));

for(int i=0;i<elems;i++){
    char rString[size] = {0};
    for(int j = 0;j<size;j++){
        rString[j] = 97+rand()%26;
    }
    rString[size] = '\0';
    str[i] = new char[size];
    strcpy(str[i],rString);
}

for(int i=0;i<elems;i++){
    cout<<str[i]<<endl;
}

Но str[0] загрязнен или пуст.

1 Ответ

5 голосов
/ 04 апреля 2020

Ваш rString[size] = '\0'; пишет элемент за пределами! Последний элемент - rString[size-1]. Все, что после этого будет неопределенное поведение .

Чтобы это исправить (но с сохранением 5-символьных строк), вам нужно увеличить size до 6 и изменить свой l oop пределы и нулевой терминатор, как указано ниже:

int main()
{
    char* str[100] = { 0 };
    const int elems = sizeof(str) / sizeof(str[0]), size = 6; // Add space for nul-terminator
    srand(time(0));
    for (int i = 0; i < elems; i++) {
        char rString[size] = { 0 };
        for (int j = 0; j < size-1; j++) { // End BEFORE last character
            rString[j] = 97 + rand() % 26;
        }
        rString[size-1] = '\0'; // Last element is at [size-1] NOT [size]
        str[i] = new char[size];
        strcpy(str[i], rString);
    }
    for (int i = 0; i < elems; i++) {
        std::cout << str[i] << std::endl;
    }
    // And, for good measure, don't forget to free the allocated strings:
    for (int i = 0; i < elems; i++) {
        delete[] str[i];
    }
    return 0;
}

В качестве альтернативы (если вы настаиваете на использовании необработанных указателей и строк в стиле C), вы можете просто изменить объявление rString и str[i] выделение строк для использования size+1 (меньше ввода):

//...
    char rString[size+1] = { 0 };
   //...
    str[i] = new char[size+1];

Но вы действительно должны рассмотреть возможность использования более современных методов C ++, таких как std::string и std::vector, вместо ваших динамических c массивов. Вот версия, использующая эти контейнеры STL:

int main()
{
    std::vector<std::string> str(100);
    const int elems = str.size(), size = 5;
    srand(time(0));
    for (int i = 0; i < elems; i++) {
        std::string rString {""};
        for (int j = 0; j < size; j++) {
            rString += static_cast<char>(97 + rand() % 26);
        }
        str[i] = rString;
    }
    for (int i = 0; i < elems; i++) {
        std::cout << str[i] << std::endl;
    }
    return 0;
}

Не стесняйтесь просить дальнейших разъяснений и / или объяснений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...