计算出现在大矩阵中的小矩阵中的字母数

时间:2019-03-30 20:30:22

标签: c

C-无效方法计算小矩阵中也出现在大矩阵中的字母不使用 string.h

Count()函数需要使用POINTERS对小矩阵中出现在大矩阵中的字母进行计数。

结果应显示在新的结果矩阵中。结果矩阵的尺寸与小矩阵相同,但是每个单元格都是一个整数,表示小矩阵的字母出现在大矩阵中的次数。

我尝试使用指向小矩阵中特定char的指针。

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。 这个2矩阵和新矩阵的例子应该是

大型矩阵

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 个答案:

答案 0 :(得分:1)

类似的事情可能起作用。我将其分解为一个带有两个参数的count函数:您要搜索的字母和一个指向大矩阵的指针。

然后,我将创建一个尺寸与小矩阵相同的结果矩阵,并为结果矩阵的每个单元格调用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次没有字符出现,则不会打印最大值和最小值。

虽然OP建议我更新Count()函数以查找最频繁的字母,但这确实变得很复杂,尤其是当您有多个字母在的最大时隙中出现相同的次数时在最小插槽中。

因此,我编写了一个利用ResultMatrix的新函数。 ResultMatrix已经包含频率计数。小矩阵会告诉我们哪些字母最频繁。

因此,PrintMaxesAndMins()使用ResultMatrix和SmallMatrix的输入(在我的代码中称为Needlestack)。

可以对代码进行优化,以便在实际收集对应于最小值的字符和对应于最小值的字符之前先找到最小值和最大值。而不是这样做,我的代码每次意识到发现更高的最大值时都会重置max chars字符串。

如果您有任何疑问,请告诉我。如果这对您有用,请接受答案。周末愉快!

代码如下:

#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;
}

答案 1 :(得分:1)

有两种解决方法:

  • 您可以编写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];
    }
}

使用POINTERS的要求 不可思议。该函数的确接收到指向参数数组的指针,我想您可能需要混淆上面的代码,以使用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));
    }
}

答案 2 :(得分:1)

如果您仍在努力采用哪种方法,那么要衡量的一个好的基准就是简单的蛮力方法。虽然通常有多种方式将事物组合在一起,并且通常会获得一些效率提升,但蛮力方法通常最容易理解。只需循环遍历small中的每个字符,然后循环遍历big数组中的每个字符,并将result置零,则每次字符每次都增加result中的索引在small中与big相匹配。

4循环方法只需要跟踪当前正在比较的索引和正在递增的索引即可。在这种情况下,smallresult的索引将彼此对应,您只需使用两个附加索引即可遍历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

仔细检查一下,如果还有其他问题,请告诉我。

答案 3 :(得分:0)

我想添加VOID功能*向用户显示哪个字符出现在MOST中,哪个字符出现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)");

}

它应该看起来像这样: 最重复:无常见字母(最大= 0) 结果矩阵: 1 3 0 2 3 4 2 0 2 1 2 4 1 0 3 3 最重复:P ... 4次