Строковые данные, кажется, удаляются после цикла for

В следующем коде всякий раз, когда я иду в отладчик, значение для абзаца удаляется или возвращается к 0, я не могу понять, почему, мысли?

void getFreqLetter(string paragraph){
char alphabet[26] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
int counter[26];
//set counter values to zero
for (int clear = 0; clear < sizeof(counter) - 1; ++clear){
counter[clear] = 0;
}
cout << paragraph;
int result = 0;
for (int i = 0; i < sizeof(paragraph); ++i){
//case:found
for (int j = 0; j < sizeof(alphabet) - 1; ++j){
if (alphabet[j] == paragraph[i]){
counter[j]++;
}
}
//go through array find largest value
for (int k = 0; k < sizeof(counter) - 1; ++k){
if (counter[k] > result){ result = counter[k]; }
}
cout << result;
}
}

0

Решение

Таким образом, все проблемы связаны с неправильным использованием sizeof,

sizeof(paragraph) не делает то, что вы думаете, что он делает: он возвращает размер string класс, а не количество символов в экземпляре строки.

Вы должны использовать paragraph.size() вместо этого предполагая, что это std::string тип.

sizeof(alphabet) по счастливому совпадению возвращает количество элементов в массиве: sizeof(char) является определенный по стандарту должно быть 1. К такому «тузу» должен быть прикреплен комментарий!

Тебе не так везет с sizeof(counter), Возвращаемое вами значение кратно sizeof(int) которая варьируется от платформы к платформе (2, 4 и 8 являются общими). Вы должны написать либо sizeof(counter) / sizeof(int) или же sizeof(counter) / sizeof(counter[0]), Последний предпочитают некоторые люди, так как вам не нужно жестко кодировать тип, а массивы нулевой длины запрещены стандартом C ++, counter[0] четко определен.

(Здесь следует иметь в виду, что sizeof оценивается во время компиляции).

3

Другие решения

Легко. ваш sizeof(counter) в состоянии цикла на самом деле sizeof(int) * 26таким образом, ваш алфавит сокрушен вашим циклом (начиная с итерации 27), а также частью стека (в частности, для адреса возврата установлено значение 0, а также внутренними элементами paragraph параметр).

И ваш - 1 не должно быть там, так как вы используете строгое сравнение.

Вы можете проследить через первый цикл и наблюдать значение sizeof(counter),

Если вы хотите количество элементов в вашем counter массив, идиоматический способ иметь это sizeof(counter) / sizeof(counter[0]),

Кроме того, длина string должен быть получен paragraph.size(), так как sizeof(paragraph) возвращает размер объекта, управляющего строкой, а не самой строки.

Наконец, sizeof(alphabet) поступает правильно, потому что sizeof(char) определяется как 1.

А теперь немного о магии C ++ 11:

#include <array>

const std::array<char,26u> alphabet{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
std::array<int, 26u> counter;
//set counter values to zero
for (int clear = 0; clear < counter.size(); ++clear){
counter[clear] = 0;
}

Это удаляет многие (все) из sizeof ловушки, будучи столь же эффективными.

3

Этот код

//set counter values to zero
for (int clear = 0; clear < sizeof(counter) - 1; ++clear){
counter[clear] = 0;
}

неверно и приводит к перезаписи памяти.

Либо использовать

for (int clear = 0; clear < sizeof( counter ) / sizeof( *counter ); ++clear){
counter[clear] = 0;
}

или же

for (int clear = 0; clear < 26; ++clear){
counter[clear] = 0;
}

или же

std::memset( counter, 0, 26 * sizeof( int ) );

или просто инициализировать массив нулями при объявлении его

int counter[26] = {};

Этот цикл

for (int j = 0; j < sizeof(alphabet) - 1; ++j){
if (alphabet[j] == paragraph[i]){
counter[j]++;
}

также недействителен. Массив символов alphabet не содержит завершающий ноль. Таким образом, цикл должен быть записан как

for (int j = 0; j < sizeof(alphabet); ++j){
if (alphabet[j] == paragraph[i]){
counter[j]++;
}

И этот цикл недействителен

for (int k = 0; k < sizeof(counter) - 1; ++k){
if (counter[k] > result){ result = counter[k]; }
}

Смотри выше.

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

Например

const int N = 26;

char alphabet[N] =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};

//...

for ( int j = 0; j < N; ++j )
{
if (alphabet[j] == paragraph[i]){
counter[j]++;
}

Чтобы найти наибольшее число, вы можете использовать стандартный алгоритм std::max_element объявлено в заголовке <algorithm>, Например

int ewsult = *std::max_element( counter, counter + 26 );
0