Во-первых, я только недавно начал учиться программировать, поэтому может быть что-то довольно очевидное, что мне не хватает. Мне очень жаль, если это так.
При задании слов алгоритм всегда пропускает первое слово и начинает со второго. Я попытался проанализировать это вручную, но не смог понять проблему. Я был бы очень признателен, если бы кто-нибудь мог мне помочь.
#include <stdio.h>
int main()
{
int n,i;
char word[100][100];
char tmp;
int counter[100];
printf("Enter the number of words ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Enter the word ");
scanf("%s", word[i]);
}
for(i='a'; i<'z'; i++)
{
counter[i]=0;
}
for(i=0; i<n; i++)
{
tmp=word[i][0];
counter[tmp]=counter[tmp]+1;
}
for(i='a'; i<'z'; i++)
{
printf("%d", counter[i]);
}
return 0;
}
Вы индексируете массивcounter[]
со значениями кода символа'a'
(97) до'z'
(122), но длина массива равна 100. Вы переполняете буфер и наступаете на соседние переменные - в этом случае началоword[0]
, и вероятноtmp
, но на данный момент он не инициализирован, поэтому на него не влияет.
То, что на самом деле примыкает к конкретной переменной, не определено и будет зависеть от того, как компилятор находит и упорядочивает объекты данных в памяти; в другом компиляторе у вас могут быть разные результаты, включая просто сбой и прерывание.
Цикл инициализации не нужен; вы можете обнулить весь массив таким образом:
int counter[100] = {0} ;
Есть и другие проблемы безопасности кода и стиля, но семантические ошибки включают в себя ваши циклы, останавливающие один из'z'
. Включать'z'
тебе нужно<= 'z'
или< 'z'+1
:
for( int i = 'a'; i <= 'z'; i++ )
{
printf("%d", counter[i]);
}
Размещение более 26 элементовcounter
массив не нужен. Лучше вычислить диапазон из значений символов:
int counter['z'-'a' + 1] = {0} ;
Затем вы должны сгенерировать индекс, вычтя'a'
от значения кода символа:
for( int i = 0; i < n; i++ )
{
char index = word[i][0] - 'a' ;
counter[index]++ ;
}
Чтобы обрабатывать верхний и нижний регистр одинаково, вы можете игнорировать регистр:
char index = tolower(word[i][0]) - 'a' ;
Ваш вывод не будет иметь смысла, если какая-либо буква имеет счетчик> 10. Вам нужно разделить каждое значение, например, пробелом или запятой.
for( int i = 'a'; i <= 'z'; i++ )
{
printf("%-3d", counter[i]);
}
Вы можете добавить ясности, определив константу для количества символов:
#define NUM_COUNTERS ('z'-'a' + 1)
упрощениеcounter[]
объявление и цикл вывода:
int counter[NUM_COUNTERS] = {0} ;
...
for( int i = 0; i < NUM_COUNTERS; i++ )
{
printf( "%-3d ", counter[i - 'a'] ) ;
}
Для предотвращения перегрузкиwords[]
вам следует ограничить значение, еслиn
а также предотвратить ввод более 99 символов в слове.
Все вместе:
#include <stdio.h>
#include <ctype.h>
#define MAX_WORDS 100
#define NUM_COUNTERS ('z'-'a' + 1)
int main()
{
int n = 0 ;
printf( "Enter the number of words " ) ;
scanf( "%d", &n ) ;
if( n > MAX_WORDS )
{
n = MAX_WORDS ;
}
char word[MAX_WORDS][100] ;
for( int i = 0; i < n; i++ )
{
printf( "Enter the word: " );
scanf( "%99s", word[i] ) ;
}
int counter[NUM_COUNTERS] = {0} ;
for( int i = 0; i < n; i++ )
{
char index = word[i][0] - 'a' ;
counter[index]++ ;
}
for( int i = 0; i < NUM_COUNTERS; i++ )
{
printf( "%-3d ", counter[i - 'a'] ) ;
}
return 0;
}
Трудно сказать, почему первое слово не учитывается, не увидев ввод, который вы передаете программе, но я вижу здесь 2 проблемы:
Вы обрабатываете значения ASCII каждого символа как индекс. В ASCII "A" имеет значение 65, "Z" - 90, "a" - 97, "z" - 122. Ваш массив счетчиков достигает только 100, поэтому попытка доступа к counter ['z'] приведет к выйти за пределы массива и повредить память в стеке и вызвать неожиданные результаты. Поскольку мы рассматриваем только буквы, а не все символы ASCII, мы должны сделать наш массив размером 26, и мы должны получить к нему доступ, преобразовав каждый символ ASCII в индекс. Это можно сделать путем вычитания 'a' (таким образом, 'a' - 'a' даст индекс 0, 'b' - 'a' даст индекс 1 и т. Д.)
Вы не учитываете прописные буквы. Это другой диапазон значений ASCII от строчных букв, и рекомендуется преобразовать все буквы в нижний регистр перед индексацией в наш массив.
Вот версия кода с этими двумя изменениями:
int main()
{
int n,i;
char word[100][100];
char tmp;
const int numLetters = 'z' - 'a' + 1;
int counter[numLetters];
printf("Enter the number of words ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Enter the word ");
scanf("%s", word[i]);
}
for(i=0; i<numLetters; i++)
{
counter[i]=0;
}
for(i=0; i<n; i++)
{
tmp=word[i][0];
//convert the letter to lowercase
tmp=tolower(tmp);
//subtract tmp-'a' to get the array index
counter[tmp-'a']++;
}
for(i=0; i<numLetters; i++)
{
printf("%d", counter[i]);
}
return 0;
}
counter
иметь100
элементов, верно? Может26
или2 * 26
. Fiddling Bitscounter
происходит переполнение буфера. например, значение'z'
(в ASCII) равно 122, тогда как массив может содержать только 100 элементов. Этот цикл обнуления можно пропустить, если вы инициализируете его с помощьюint counter[100] = {0};
. P.P