Вычислить наиболее часто встречающиеся цифры в строке цифр в C - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь вычислить наиболее часто встречающуюся цифру в строке символов, и мне нужно использовать указатели, но я не уверен, как поступить с указателями.

int most(char* string){
    int counter = 0;
    int* array =(int*) malloc(sizeof(int)*10);
    char* original = string;
    while(*original){
        counter++;
        string++;
        //Not sure what to put in this loop
    }
}

например, я хочу назвать код

char nums[] = "132433423";
printf("%d \n",most(nums));
// 3

Ответы [ 4 ]

0 голосов
/ 01 мая 2018

Вы можете сначала отсортировать строку так, чтобы меньшие цифры появились первыми в num. Вы можете использовать qsort() (из stdlib.h) как

int cmpfn(const void *a, const void *b)
{
    int x = *(char *)a;
    int y = *(char *)b;
    return x-y;
}
int main()
{
    char nums[] = "132433423";//"111222223333";//
    qsort(nums, sizeof(nums)/sizeof(nums[0]) -1, sizeof(nums[0]), cmpfn);
    printf("\nAfter sorting: %s", nums);

    . . . . . . . . . . 
    . . . . . . . . . . 

}

Объявите переменные для хранения режима (т. Е. Значения, которое чаще всего появляется в данных) и частоты значения режима.

int mode=-1, modecount=-1, n;

Теперь найдите частоту каждого символа цифры. Поскольку это отсортированный массив символов, то же значение будет отображаться последовательно.

for(char *ptr=nums, *lptr=NULL; *ptr; ptr+=n)
{
    lptr = strrchr(ptr, *ptr);
    n = lptr - ptr + 1;
    if(n>modecount)
    {
        printf("\n%c", *ptr);
        modecount = n;
        mode = *ptr;
    }
}   
printf("\nMode is: %c", mode);

strrchr() (из string.h) найдет последнее вхождение символа в строку.

0 голосов
/ 01 мая 2018

Я не уверен, что вы подразумеваете под "использованием указателей", но вот версия, в которой не использует указатели, за исключением обхода входной строки:

char most_frequent_character(char *s)
  {
  int freq[10];
  int max_freq;
  int max_idx;
  int idx;

  while(*s)
    freq[*s++ - '0']++;  /* compute character freqs */

  max_idx = 0;
  max_freq = freq[0];

  for(idx = 1 ; idx < 10 ; ++idx)
    if(freq[idx] > max_freq)
      {
      max_freq = freq[idx];
      max_idx = i;
      }

  return '0' + max_idx;
  }

Веселись.


EDIT

Чтобы преобразовать вышеприведенное в «использование указателей»:

A. Измените freq на указатель на int и инициализируйте его, используя malloc; Кроме того, инициализируйте память, указанную freq, используя memset:

int *freq = malloc(sizeof(int) * 10);
memset(freq, 0, sizeof(int)*10);

B. В цикле «вычислить частоту символов» используйте ссылки на указатели вместо индексации:

while(*s)
  {
  *(freq + (*s - '0')) = *(freq + (*s - '0')) + 1;
  s++;
  }

C. Используйте указатель ref для установки начального значения max_freq:

max_freq = *freq;

D. В цикле for используйте указатель math вместо индексации:

  for(idx = 1 ; idx < 10 ; ++idx)
    if( *(freq + idx) > max_freq)
      {
      max_freq = *(freq + idx);
      max_idx = i;
      }

E. Освободите память, выделенную ранее перед оператором возврата:

free(freq);
return '0' + max_idx;

Теперь сядьте и поймите, почему все сделано так, как они здесь. Например, почему не я сделал следующее при вычислении частот символов?

while(*s++)
  *(freq + (*s - '0')) = *(freq + (*s - '0')) + 1;

или

while(*s)
  *(freq + (*s++ - '0')) = *(freq + (*s++ - '0')) + 1;

Каждое из вышеперечисленных сохранит несколько строк кода - почему их не следует использовать? (Очевидный ответ: «потому что они не будут работать как задумано» - но ПОЧЕМУ?)

Удачи.

0 голосов
/ 01 мая 2018
#include<string.h>    
int most (char* nums) {
    int i, max_index = 0;
    int digit_dictionary[10]={0,0,0,0,0,0,0,0,0,0};

    for (i=0; i< strlen(nums); i++) {
        digit_dictionary[nums[i]-'0'] ++;
    }

    for (i=1; i<10; i++) {
        if (digit_dictionary[i]> digit_dictionary[max_index])
            max_index = i;
    }
    return max_index;
}

Я постараюсь быть настолько сложным, насколько смогу:

Вы создаете словарь, в котором каждый индекс соответствует цифре, которая может встречаться (0-9). Затем выполните итерацию по строке (которая в основном представляет собой массив символов) и сохраните каждую цифру в соответствующем индексе в словаре.
Примечание : [nums[i]-'0'] вычисляется в индексе словаря, поскольку каждый символ имеет целочисленное значение (см. Таблицу ASCII).

Счетчик по этому индексу увеличивается, чтобы сохранить количество появлений этой цифры.

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

0 голосов
/ 01 мая 2018

Спецификация для вашей функции неполная:

  • может ли строка содержать нецифровые символы?
  • что должно быть возвращено, если вообще нет цифр?
  • какое значение должно быть возвращено, если есть несколько цифр с одинаковым максимальным числом вхождений?
  • должна ли функция возвращать цифру или ее числовое значение? Ваша main() функция использует последнее, но это не ясно из текста вопроса.

Функция most получает указатель на строку. Вы можете написать цикл, в котором вы обрабатываете один символ за раз и увеличиваете указатель для следующей итерации, пока не достигнете конца строки. Вы также должны решить, что возвращать, если строка не содержит цифр.

Вот простой пример:

int most(const char *s) {
    int count[10] = { 0 };
    int res, i, max;

    while (*s) {
        if (*s >= '0' && *s <= '9')
            count[*s - '0']++;
        s++;
    }
    res = -1;  /* return -1 if no digits */
    max = 0;
    for (i = 0; i < 10; i++) {
        if (count[i] > max)
            res = i;
    }
    return res;
}

Если вам вообще запрещено использовать какой-либо массив, выделение блока памяти кажется действительно хорошим решением:

int most(const char *s) {
    int *count = calloc(sizeof(*count), 10);
    int res, i, max;

    while (*s) {
        if (*s >= '0' && *s <= '9')
            *(count + *s - '0') += 1;
        s++;
    }
    res = -1;  /* return -1 if no digits */
    max = 0;
    for (i = 0; i < 10; i++) {
        if (*(count + i) > max)
            res = i;
    }
    free(count);
    return res;
}

Обозначение *(count + *s - '0') += 1 работает следующим образом: count является указателем на массив int, выделенный и инициализированный в 0 с помощью calloc. *s - '0' - это цифровое значение n символа, на который указывает s, которое было проверено на наличие цифры. count + *s - '0' - указатель на n-ую запись в массиве. *(count + *s - '0') += 1 увеличивает это значение на единицу.

Есть способы сделать это без выделения памяти, с 10 переменными и явными тестами для различных цифр, но я сомневаюсь, что это будет ожидаемое решение.

Если вы можете объяснить свой выбор своему учителю, есть 2 способа использовать массивы без символов [ и ]. Это устаревшие функции стандарта C, с которыми большинство программистов не знакомы и которые можно игнорировать, если вам не интересно:

int most(const char *s) {  /* version with C99 digraphs */
    int count<:10:> = { 0 };
    int res, i, max;

    while (*s) {
        if (*s >= '0' && *s <= '9')
            count<:*s - '0':>++;
        s++;
    }
    res = -1;  /* return -1 if no digits */
    max = 0;
    for (i = 0; i < 10; i++) {
        if (count<:i:> > max)
            res = i;
    }
    return res;
}

Или

int most(const char *s) {  /* version with old-style trigraphs */
    int count??(10??) = { 0 };
    int res, i, max;

    while (*s) {
        if (*s >= '0' && *s <= '9')
            count??(*s - '0'??)++;
        s++;
    }
    res = -1;  /* return -1 if no digits */
    max = 0;
    for (i = 0; i < 10; i++) {
        if (count??(i??) > max)
            res = i;
    }
    return res;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...