#c
#c
Вопрос:
Метод 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 М Б Р Р Р Н В С К Ч М У Дж. П. Ш. К В М Ф Д 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
Комментарии:
1. Сначала я бы создал массив с количеством символов для букв в большой матрице. Затем вы можете просмотреть вторую матрицу, просматривая значения из вашего массива.
2. ПОНЯТИЯ не имею :/ Как это сделать… Пытался
3. Будет ли функция Count возвращать только одно количество? Похоже, вы хотели бы либо вызвать Count один раз для каждой ячейки в маленькой матрице, возвращая количество для этой ячейки, либо создать результирующую матрицу с помощью функции Count. Однако функция Count не объявлена для выполнения ни того, ни другого. Можете ли вы изменить аргументы Count()?
4. Что ж, если вы готовы ограничить количество букв заглавными буквами и хотите использовать набор символов ANSI, тогда вы можете создать массив
int counts[26]
. Инициализируйте все записи нулем. Затем выполните итерацию по каждому элементу большой матрицы. Индекс массива будет таким,c - 'A'
гдеc
находится символ. Таким образом,'A'
дает индекс 0 и'Z'
дает индекс 25. Затем просто сделайтеcounts[c - 'A'] ;
для каждого символаc
в большом массиве. По завершенииcounts
будет содержать количество каждой буквы (включая те, которые не отображаются в большом массиве, количество которых будет равно нулю).5. В вашем примере big matrix есть 5 «P»s, но соответствующая позиция в матрице результатов вашего примера показывает только 4.
Ответ №1:
Если вы все еще не знаете, какой подход выбрать, хорошим эталоном для сравнения является простой метод перебора. Хотя, как правило, существует множество способов объединения элементов и, как правило, можно добиться некоторого повышения эффективности, подход грубой силы обычно самый простой для понимания. Это означает, что нужно просто перебирать каждый символ в 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 amp;amp; (c = fgetc (fp)) != 'n' amp;amp; c != EOF)
if (isalpha (c)) /* if it's a letter */
arr[rdx][cdx ] = c; /* store it in big */
if (!cdx amp;amp; (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 amp;amp; (c = fgetc (fp)) != 'n' amp;amp; c != EOF)
if (isalpha (c)) /* if it's a letter */
arr[rdx][cdx ] = c; /* store it in big */
if (!cdx amp;amp; (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 Matrixn"); /* output all matricies */
prncharray (rdx, colmax, arr);
puts ("nSmall Matrixn");
prncharray (rowsm, SIZE, small);
puts ("nResult Matrixn");
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
Просмотрите все и дайте мне знать, если у вас возникнут дополнительные вопросы.
Ответ №2:
Есть 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] amp; 255] ;
}
for (i = 0; i < SIZE; i ) {
for (j = 0; j < SIZE; j )
result[i][j] = count[smallMat[i][j] amp; 255];
}
}
Требование использования УКАЗАТЕЛЕЙ является сверхъестественным. Функция действительно получает указатели на массивы аргументов, я думаю, вы могли бы запутать приведенный выше код, чтобы использовать синтаксис pinter *(p i)
вместо синтаксиса array 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) amp; 255) = 1;
}
for (i = 0; i < SIZE; i ) {
for (j = 0; j < SIZE; j )
*(*(result i) j) = *(count (*(*(smallMat i) j) amp; 255));
}
}
Ответ №3:
Я бы разбил это на функцию подсчета, которая принимает два аргумента: букву, которую вы ищете, и указатель на большую матрицу.
Затем я бы создал результирующую матрицу с теми же размерами, что и у малой матрицы, и вызвал функцию count для каждой ячейки результирующей матрицы, передавая большую матрицу и присваивая результат для каждого вызова count каждой последующей ячейке результирующей матрицы.
Наконец, чтобы сделать функцию main() понятной, создайте конечную функцию, которая будет печатать результирующую матрицу. Что-то вроде этого:
Отредактировано: Я отредактировал код в соответствии с обновлениями вопроса OP. Этот код создает следующий вывод:
$> 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 и mins. Этот массив не должен быть длиннее произведения сторон результирующей матрицы.
Если ни один символ не встречается хотя бы 1 раз, то значения max и min не будут напечатаны.
В то время как OP предложил мне обновить функцию Count (), чтобы позаботиться о поиске наиболее частых букв, это действительно усложняется, особенно когда у вас есть более одной буквы, встречающейся одинаковое количество раз в максимальном слоте или в минимальном слоте.
Итак, я написал новую функцию, которая использует ResultMatrix. Результирующая матрица уже содержит значения частоты. Маленькая матрица сообщает нам, какие буквы встречаются чаще всего.
Итак, PrintMaxesAndMins()
использует входные данные из ResultMatrix и SmallMatrix (в моем коде называется Needlestack).
Код можно было бы оптимизировать, чтобы сначала найти min и max, прежде чем фактически собирать символы, соответствующие min, и символы, соответствующие min. Вместо этого мой код сбрасывает строку с максимальными символами каждый раз, когда понимает, что найдено большее максимальное значение.
Вот код:
#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 amp;amp; 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 amp;amp; 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("nn");
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], amp;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;
}
Комментарии:
1. Спасибо (: что такое u_int32_t? Могу ли я изменить это на что-то более простое?
2. Вы можете вызвать это
unsigned int
.3. Я стараюсь избегать
int
случаев, когда значение никогда не должно быть отрицательным, но мой компилятор этого не делаетuint
. Вместо этого он имеетu_int32_t
иu_int16_t
и так далее. Я уверен, что это где-то стандартно. Вероятно, мне следует просто создать typedef дляunsigned int.
4.
#include <stdint.h>
5. Обновлено, чтобы исправить ошибку в функции поиска (
[j][j]
должна была быть[i][j]
) и использовать <stdint.h> иuint32_t
которое является 32-разрядным целым числом без знака.
Ответ №4:
я хочу ДОБАВИТЬ функцию 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 раза
Комментарии:
1. Вы должны передать Smallmat[i][j] вместо smallmat[SIZE][РАЗМЕР] для функции count
2. Бесконечный шарик ма. Удачи
3. Я изменил вопрос о функции… Я удаляю it…@sergeyrar @David C. Ranki
4. Спасибо. Копировать / вставлять выходной текст нормально, просто избегайте делать его скриншот.