В следующем коде всякий раз, когда я иду в отладчик, значение для абзаца удаляется или возвращается к 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;
}
}
Таким образом, все проблемы связаны с неправильным использованием 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
оценивается во время компиляции).
Легко. ваш 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
ловушки, будучи столь же эффективными.
Этот код
//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 );