Подсчитайте количество букв в маленькой матрице, которые появляются в большой матрице - PullRequest
2 голосов
/ 30 марта 2019

C - метод Void подсчитывает, сколько букв из маленькой матрицы также появляется в большой матрице БЕЗ использования string.h

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

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

Я пытался использовать указатель наконкретный символ в маленькой матрице.

void Count(char mat[ROWS][COLS], char smallMat[SIZE][SIZE]) {
    int i, j;
    int count = 0;
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            const char stringptr = smallMat[i][j];
            if (stringptr == mat[i][j])
                count++;
        }

    }
    return count;
}

Счет должен возвращать main.Этот пример двух матриц и новой матрицы должен быть

Большая матрица

P A D A Q E Q B G H R O P H C W S P B Q
M B R P R N V S C H M U J P W C V M F D
V W R K E V I Y K K Q Y N H N G V L B Z

Малая матрица

U N T E
C P G X
D L A B

Матрица результатов

1 3 0 2
3 4 2 0 
2 1 2 4

Ответы [ 4 ]

1 голос
/ 12 апреля 2019

Если вы все еще боретесь с тем, какой подход выбрать, хорошим эталоном для сравнения является простой метод грубой силы. Несмотря на то, что, как правило, существует множество способов объединить вещи, и, как правило, необходимо добиться некоторого повышения эффективности, метод «грубой силы» обычно легче всего понять. Это означает, что нужно просто зациклить каждый символ в small, а затем зациклить каждый символ в вашем массиве big и, обнулив result, просто увеличивать индекс в result каждый раз, когда символ в small соответствует big .

4-петлевой подход не требует ничего, кроме отслеживания того, какой индекс в настоящее время сравнивается, а какой увеличивается. В этом случае индексы для small и result будут соответствовать друг другу, и вы просто используете два дополнительных индекса для итерации по big, например,

/* fill result count from chars in arr matching small */
void count (char big[ROW][COL], int row, int col, char (*small)[SIZE],
            int rowsm, int (*result)[SIZE])
{
    for (int i = 0; i < rowsm; i++)             /* for each row in small */
        for (int j = 0; j < SIZE; j++)          /* for each col in small */
            for (int k = 0; k < row; k++)       /* for each row in big */
                for (int l = 0; l < col; l++)   /* for each col in big */
                    if (small[i][j] == big[k][l])   /* does small == arr? */
                        result[i][j]++;         /* increment result */
}

В этот момент у вас заполнена матрица result.

Остальная часть довольно проста. Единственной реальной задачей остается чтение big из вашего входного файла (или stdin). Простой подход здесь, учитывая формат big, состоит в том, чтобы прочитать каждый введенный символ как символ и просто проверить isalpha (c) (или isupper (c), если хотите). Просто сохраните альфа-символы, игнорируя остальные, но следя за встреченными '\n' и EOF, чтобы обновить / сбросить необходимые счетчики. Ваше чтение может быть:

int main (int argc, char **argv) {

    char arr[ROW][COL] = {{0}},                     /* big matrix */
        small[][SIZE]  = {{ 'U', 'N', 'T', 'E' },   /* small matrix */
                          { 'C', 'P', 'G', 'X' },
                          { 'D', 'L', 'A', 'B' }};
    int c = 0,          /* to read chars from file into big mtrx */
        rdx = 0,        /* row index */
        cdx = 0,        /* col index */
        colmax = 0,     /* max col found per-row */
        rowsm = sizeof small / sizeof *small,   /* rows in small */
        result[rowsm][SIZE];    /* result matrix */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    zerovla (rowsm, result);    /* zero elements in result */

    while (c != EOF) {  /* while not end of file */
        /* while index < row and char not '\n' or EOF */
        while (rdx < ROW && (c = fgetc (fp)) != '\n' && c != EOF)
            if (isalpha (c))            /* if it's a letter */
                arr[rdx][cdx++] = c;    /* store it in big */
        if (!cdx && (c == '\n' || c == EOF))    /* if end of line/file */
            break;                              /* break */
        if (!colmax)            /* if colmax not set */
            colmax = cdx;       /* set with no. cols from 1st row */
        if (cdx != colmax) {    /* validate remaining rows have same cols */
            fputs ("error: row with unuequal columns.\n", stderr);
            return 1;
        }
        rdx++;      /* increment row index  */
        cdx = 0;    /* reset col index zero */
    }
    ...

В целом, вы можете сделать что-то похожее на:

#include <stdio.h>
#include <ctype.h>

#define ROW  3
#define COL  20
#define SIZE 4

#define CHARSET 62

/* fill result count from chars in arr matching small */
void count (char big[ROW][COL], int row, int col, char (*small)[SIZE],
            int rowsm, int (*result)[SIZE])
{
    for (int i = 0; i < rowsm; i++)             /* for each row in small */
        for (int j = 0; j < SIZE; j++)          /* for each col in small */
            for (int k = 0; k < row; k++)       /* for each row in big */
                for (int l = 0; l < col; l++)   /* for each col in big */
                    if (small[i][j] == big[k][l])   /* does small == arr? */
                        result[i][j]++;         /* increment result */
}

/* simple zero VLA */
void zerovla (int rowsm, int (*result)[SIZE])
{
    for (int i = 0; i < rowsm; i++)
        for (int j = 0; j < SIZE; j++)
            result[i][j] = 0;
}

/* print char array */
void prncharray (int row, int col, char (*arr)[col])
{
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            putchar (' ');
            putchar (arr[i][j]);
        }
        putchar ('\n');
    }
}

/* print int array */
void prniarray (int row, int col, int (*arr)[col])
{
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++)
            printf (" %d", arr[i][j]);
        putchar ('\n');
    }
}

int main (int argc, char **argv) {

    char arr[ROW][COL] = {{0}},                     /* big matrix */
        small[][SIZE]  = {{ 'U', 'N', 'T', 'E' },   /* small matrix */
                          { 'C', 'P', 'G', 'X' },
                          { 'D', 'L', 'A', 'B' }};
    int c = 0,          /* to read chars from file into big mtrx */
        rdx = 0,        /* row index */
        cdx = 0,        /* col index */
        colmax = 0,     /* max col found per-row */
        rowsm = sizeof small / sizeof *small,   /* rows in small */
        result[rowsm][SIZE];    /* result matrix */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    zerovla (rowsm, result);    /* zero elements in result */

    while (c != EOF) {  /* while not end of file */
        /* while index < row and char not '\n' or EOF */
        while (rdx < ROW && (c = fgetc (fp)) != '\n' && c != EOF)
            if (isalpha (c))            /* if it's a letter */
                arr[rdx][cdx++] = c;    /* store it in big */
        if (!cdx && (c == '\n' || c == EOF))    /* if end of line/file */
            break;                              /* break */
        if (!colmax)            /* if colmax not set */
            colmax = cdx;       /* set with no. cols from 1st row */
        if (cdx != colmax) {    /* validate remaining rows have same cols */
            fputs ("error: row with unuequal columns.\n", stderr);
            return 1;
        }
        rdx++;      /* increment row index  */
        cdx = 0;    /* reset col index zero */
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    count (arr, rdx, colmax, small, rowsm, result); /* count/fill result */

    puts ("Big Matrix\n");              /* output all matricies */
    prncharray (rdx, colmax, arr);
    puts ("\nSmall Matrix\n");
    prncharray (rowsm, SIZE, small);    
    puts ("\nResult Matrix\n");
    prniarray (rowsm, SIZE, result);

    return 0;
}

Пример использования / Вывод

$ ./bin/bigsmallfreq <dat/bigmtrxltrs.txt
Big Matrix

 P A D A Q E Q B G H R O P H C W S P B Q
 M B R P R N V S C H M U J P W C V M F D
 V W R K E V I Y K K Q Y N H N G V L B Z

Small Matrix

 U N T E
 C P G X
 D L A B

Result Matrix

 1 3 0 2
 3 5 2 0
 2 1 2 4

Посмотрите вещи и дайте мне знать, если у вас есть еще вопросы.

1 голос
/ 07 апреля 2019

Есть 2 подхода к вашей проблеме:

  • Вы можете написать 4 вложенных цикла, подсчитывая для каждой ячейки в маленькой матрице, сколько раз соответствующая буква появляется в большой матрице. это займет SIZE*SIZE*ROWS*COLS итераций, потенциально много времени.
  • Вы можете использовать массив int и подсчитывать количество вхождений каждой буквы в большой матрице с шагом ROWS*COLS, а затем вычислять счетчик матрицы результатов, копируя соответствующий счетчик из массива для каждой ячейки в маленькая матрица с шагом SIZE*SIZE.

Вот пример для второго подхода:

// assuming 8-bit chars
void Count(char mat[ROWS][COLS], char smallMat[SIZE][SIZE], int result[SIZE][SIZE]) {
    int count[256] = { 0 };
    int i, j;

    for (i = 0; i < ROWS; i++) {
        for (j = 0; j < COLS; j++)
            count[mat[i][j] & 255]++;
    }
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++)
            result[i][j] = count[smallMat[i][j] & 255];
    }
}

Требование с помощью указателей является странным. Функция получает указатели на массивы аргументов, я думаю, что вы могли бы запутать приведенный выше код, чтобы использовать синтаксис pinter *(p + i) вместо синтаксиса массива p[i] для выполнения этого требования. Вот ужасный результат:

// assuming 8-bit chars
void Count(char mat[ROWS][COLS], char smallMat[SIZE][SIZE], int result[SIZE][SIZE]) {
    int count[256] = { 0 };
    int i, j;

    for (i = 0; i < ROWS; i++) {
        for (j = 0; j < COLS; j++)
            *(count + (*(*(mat + i) + j) & 255) += 1;
    }
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++)
            *(*(result + i) + j) = *(count + (*(*(smallMat + i) + j) & 255));
    }
}
1 голос
/ 31 марта 2019

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

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

Наконец, чтобы сделать функцию main ()очистите, создайте последнюю функцию, которая будет печатать матрицу результатов.Примерно так:

Отредактировано : Я отредактировал код в соответствии с обновлениями вопроса ОП.Этот код создает следующий вывод:

$> a.out
P A D A Q E Q B G H R O P H C W S P B Q 
M B R P R N V S C H M U J P W C V M F D 
V W R K E V I Y K K Q Y N H N G V L B Z 

U N T E 
C P G X 
D L A B 

1 3 0 2 
3 5 2 0 
2 1 2 4 

The most repetitive char(s) occurred 5 time(s):  P

The least repetitive char(s) occurred 1 time(s):  U L
Process finished with exit code 0

Код печатает все минимальные и все максимальные символы для наибольшего и наименьшего номера частоты.Для этого он хранит массив max и min.Этот массив не должен быть длиннее, чем произведение сторон матрицы результатов.

Если ни один символ не встречается хотя бы 1 раз, то значения max и min не будут напечатаны.

ПокаОП предложил мне обновить функцию Count (), чтобы позаботиться о поиске наиболее часто встречающихся букв, это действительно становится сложным, особенно если у вас есть несколько писем, встречающихся одинаковое количество раз в максимальном слоте в минимальном слоте.

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

Итак, PrintMaxesAndMins() использует входные данные из ResultMatrix и SmallMatrix (называемые Needlestack в моем коде).

Код можно оптимизировать, чтобы сначала найти минимальное и максимальное значения, прежде чем на самом деле собрать символы, соответствующие минимальному, и символы, соответствующие минимальному.Вместо этого мой код сбрасывает строку max chars каждый раз, когда обнаруживает, что найден более высокий max.

Дайте мне знать, если у вас есть какие-либо вопросы.Если это работает для вас, пожалуйста, примите ответ.Хороших выходных!

Вот код:

#include <stdio.h>
#include <stdint.h>
#include <limits.h>

const size_t ROWS = 3;
const size_t COLUMNS = 20;
const size_t SMALL_ROWS = 3;
const size_t SMALL_COLUMNS = 4;
const size_t SIZE = 4;

char LargeMatrix[ROWS][COLUMNS] =
    {{'P', 'A', 'D', 'A', 'Q', 'E', 'Q', 'B', 'G', 'H', 'R', 'O', 'P', 'H', 'C',
      'W', 'S', 'P', 'B', 'Q'},
     {'M', 'B', 'R', 'P', 'R', 'N', 'V', 'S', 'C', 'H', 'M', 'U', 'J', 'P', 'W',
      'C', 'V', 'M', 'F', 'D'},
     {'V', 'W', 'R', 'K', 'E', 'V', 'I', 'Y', 'K', 'K', 'Q', 'Y', 'N', 'H', 'N',
      'G', 'V', 'L', 'B', 'Z'},};

char SmallMatrix[SIZE][SIZE] =
    {{'U', 'N', 'T', 'E'}, {'C', 'P', 'G', 'X'}, {'D', 'L', 'A', 'B'}};

void Count(char mat[ROWS][COLUMNS], char c, size_t *count)
{
  size_t counter = 0;  // Initialize the count answer cell
  for (size_t i = 0; i < ROWS; i++) {
    for (size_t j = 0; j < COLUMNS; j++) {
      if (mat[i][j] == c)
        counter++;
    }

  }
  *count = counter;

}

// clear the char array
void zero_char_array(char *array, size_t len)
{
  for (size_t i = 0; i < len; i++)
    array[i] = 0;
}
//
//
void PrintMaxesAndMins(char haystack[ROWS][COLUMNS],
                       char needlestack[SMALL_ROWS][SMALL_COLUMNS],
                       size_t answerStack[SMALL_ROWS][SMALL_COLUMNS],
                       size_t result_rows,
                       size_t result_columns)
{
  char max_char; // char that occurred the most
  char min_char; // char that occurred the least
  size_t max_char_count =
      0;  // best to use unsigned ints when a value should never go negative.
  size_t min_char_count = UINT32_MAX; // Value should not go negative.
  char max_chars[SMALL_COLUMNS * SMALL_ROWS]; // save all possible max chars
  char *next_max_char;
  char min_chars[SMALL_COLUMNS * SMALL_ROWS]; // sall all possible min chars
  char *next_min_char;

  size_t counter = 0;  // Initialize the count answer cell
  for (size_t i = 0; i < result_rows; i++) {
    for (size_t j = 0; j < result_columns; j++) {
      if (answerStack[i][j] > max_char_count) {
        max_char_count = answerStack[i][j];  // we have a new max

        zero_char_array(max_chars, SMALL_COLUMNS * SMALL_ROWS);
        next_max_char =
            max_chars;  // We have a new max, reset result char array

        *next_max_char = needlestack[i][j];// grab character from needle stack
        ++next_max_char;  // increment.  Could do in prior line, but try to be clear.
      } else if (answerStack[i][j] >= max_char_count) {
        // we are adding to an old max
        *next_max_char = needlestack[i][j];// grab character from needle stack
        ++next_max_char;  // increment.  Could do in prior line, but try to be clear.
      }
      if (answerStack[i][j] > 0 &&  answerStack[i][j] < min_char_count) {
        min_char_count = answerStack[i][j];  // we have a new min

        zero_char_array(min_chars, SMALL_COLUMNS * SMALL_ROWS);
        next_min_char =
            min_chars;  // We have a new min, reset result char array

        *next_min_char = needlestack[i][j];// grab character from needle stack
        ++next_min_char;  // increment.  Could do in prior line, but try to be clear.
      } else if (answerStack[i][j] > 0 && answerStack[i][j] <= min_char_count) {
        // we are adding to an old max
        *next_min_char = needlestack[i][j];// grab character from needle stack
        ++next_min_char;  // increment.  Could do in prior line, but try to be clear.
      }
    }
  }

  if (max_char_count > 0) {
    printf("The most repetitive char(s) occurred %lu time(s): ", max_char_count);
    next_max_char = max_chars;

    while (*next_max_char)
      printf(" %c", *next_max_char++);
  }
  printf("\n\n");
  if (min_char_count > 0) {
    printf("The least repetitive char(s) occurred %lu time(s): ", min_char_count);

    next_min_char = min_chars;
    while (*next_min_char) {
      printf(" %c", *next_min_char++);
    }
  }

}

// BuildResultMatrix()
// haystack is a pointer to the large matrix.
// needlestack is a pointer to the small matrix.
// answerStack is the result matrix of size_t
void BuildResultMatrix(char haystack[ROWS][COLUMNS],
                       char needlestack[SMALL_ROWS][SMALL_COLUMNS],
                       size_t answerStack[SMALL_ROWS][SMALL_COLUMNS],
                       size_t result_rows,
                       size_t result_columns)
{

  // Loop through the rows and columns of the small matrix
  for (size_t i = 0; i < result_rows; i++) {
    for (size_t j = 0; j < result_columns; j++) {
      // Pass the current cell of the small matrix to Count()
      // Count() will then loop through the large matrix, counting
      // the number of cells with the current cell value from the small matrix.
      // Count() will place the final count into the correpsonding cell of the
      // answerStack matrix.
      Count(LargeMatrix, needlestack[i][j], &answerStack[i][j]);
    }
  }
}

void PrintLargeCharMatrix(char (*matrix)[COLUMNS], size_t rows)
{
  for (size_t i = 0; i < rows; i++) {
    for (size_t j = 0; j < COLUMNS; j++) {
      printf("%c ", matrix[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}
void PrintSmallCharMatrix(char (*matrix)[SMALL_COLUMNS], size_t rows)
{
  for (size_t i = 0; i < rows; i++) {
    for (size_t j = 0; j < SMALL_COLUMNS; j++) {
      printf("%c ", matrix[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}
void PrintCountMatrix(size_t (*matrix)[SMALL_COLUMNS], size_t rows)
{
  for (size_t i = 0; i < rows; i++) {
    for (size_t j = 0; j < SMALL_COLUMNS; j++) {
      printf("%lu ", matrix[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}
int main()
{
  size_t ResultMatrix[SMALL_ROWS][SMALL_COLUMNS];

  PrintLargeCharMatrix(LargeMatrix, ROWS);
  PrintSmallCharMatrix(SmallMatrix, SMALL_ROWS);

  BuildResultMatrix(LargeMatrix,
                    SmallMatrix,
                    ResultMatrix,
                    SMALL_ROWS,
                    SMALL_COLUMNS);

  PrintCountMatrix(ResultMatrix, SMALL_ROWS);

  PrintMaxesAndMins(LargeMatrix,
                    SmallMatrix,
                    ResultMatrix,
                    SMALL_ROWS,
                    SMALL_COLUMNS);

  return 0;
}
0 голосов
/ 12 апреля 2019

Я хочу добавить функцию VOID *, чтобы показать пользователю, какой символ появляется в самом НАЧАЛЕ, а какой появляется 0 раз ** /:

    void Count(const char mat[ROWS][COLS], char c, int *count)
    {
      int i, j;
      int counter = 0; 
      for (i = 0; i < ROWS; i++) {
         for (j = 0; j < COLS; j++) {
              if (mat[i][j] == c)
                counter++;
            }
           *count = counter;
  if(counter>max)
      counter=max;
  else
      counter=min;
  }
  if(count==max)
     printf("Most repetitive: %c %d times", c,counter);
  if(count==min)
     printf("Most repetitive: NO COMMON LETTERS (max = 0)");

}

Это должно выглядеть так: Наиболее повторяющиеся: НЕТОБЩИЕ ПИСЬМА (max = 0) Матрица результатов: 1 3 0 2 3 4 2 0 2 1 2 4 1 0 3 3 Наиболее повторяющиеся: P ... 4 раза

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