编辑以添加整个作业和预期输出。
您受雇协助消防员在广阔的地理区域定位野火。该区域被划分为更小的区域。通过卫星扫描每个区域的平均温度。如果一个区域的平均温度严格高于 1000°F,我们假设该区域发生火灾。如果温度在100度(含)到1000度(含)之间,我们就得进一步调查,所以它就成了“观察区”。
您正在观看的大地理区域是一个具有一定长度和宽度的矩形,每个矩形都以区域的形式给出。例如,如果要扫描的区域长为6,宽为9,那么它将被分成6*9个区域:
因为您的程序将用于各种地理区域(每个区域都有自己的长度和宽度),所以您的程序需要为要处理的区域数量(垂直和水平)动态分配内存。
为此,您必须使用以下两个函数而不更改其中的代码:
int ** allocateIntStarArray(int num){
int ** ptr = (int **) malloc(num * sizeof(int *));
return ptr;
}
int * allocateIntArray(int num){
int * ptr = (int *) malloc(num * sizeof(int));
return ptr;
}
The function `allocateIntArray()` will be used to allocate the space required to store the average temperatures in one row of zones, that is, an array of integers. The function therefore returns a pointer to such an array of integers.
The function `allocateIntStarArray()` will be used to allocate an array of pointers, each of which will store a pointer to a row of integers (temperatures of zones). That is, the function returns a pointer to an array of pointers. Each cell of this array will point to an array of integers containing the temperature values for the zones.
The inputs of the program are first the length, then the width of an area, then the average temperatures of all zones, row by row.
Please remember to free the memory you have allocated.
The output should pinpoint the possible zones with fires with [X] and the watch zone with a [*], the other zone are displayed with [ ].
Input:
6
9
70 71 70 72 70 69
71 73 68 71 73 72
70 71 70 76 1900 78
69 71 100 800 75 71
70 70 71 79 70 69
70 71 112 1005 75 72
70 71 70 900 70 70
72 70 70 72 70 69
73 74 73 72 70 70
Output:
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][X][ ]
[ ][ ][*][*][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][*][X][ ][ ]
[ ][ ][ ][*][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
----
The code I'm working on is to create a matrix based off user input. I'm having an issue getting my variable **mat back to the first array element so that it will print the rectangle correctly. Could someone enlighten me on how to do this? What I have so far:
#include <stdio.h>
#include <stdlib.h>
int **allocateIntStarArray(int);
int *allocateIntArray(int);
int **allocateMatrix(int, int);
void readValues(int **, int, int);
void print(int **, int, int);
int main(void) {
int rows, cols;
scanf("%d %d", &rows, &cols);
int **mat = allocateMatrix(rows, cols);
readValues(mat, cols, rows);
print(mat, cols, rows);
/* free your memory */
for (int r = 0; r < rows; r++){
free(mat[r]);
}
free(mat);
return 0;
}
void readValues(int **mat, int ncols, int nrows) {
for (int r = 0; r < nrows; r++) {
for (int c = 0; c < ncols; c++) {
scanf("%d", &mat[r][c]);
}
}
}
void print(int **mat, int ncols, int nrows) {
for (int r = 0; r < nrows; r++) {
for (int c = 0; c < ncols; c++) {
int value = mat[r][c];
if (value > 1000){
printf("[X]");
}
else if (value >= 100){
printf("[*]");
}
else{
printf("[ ]");
}
}
printf("\n");
}
}
int **allocateMatrix(int nrows, int ncols) {
int **mat = allocateIntStarArray(nrows);
for (int row = 0; row <= nrows; ++row) {
mat[row] = allocateIntArray(ncols);
}
return mat;
}
/* Provided functions, do not edit */
int **allocateIntStarArray(int num) {
int **ptr = (int **) malloc(num * sizeof(int *));
return ptr;
}
int *allocateIntArray(int num) {
int *ptr = (int *) malloc(num * sizeof(int));
return ptr;
}
我不会使用双指针代替二维数组。
void *allocateMatrix(size_t nrows, size_t ncols, int (**array)[ncols])
{
int (*arrptr)[ncols] = malloc(nrows * sizeof(*arrptr));
if(array) *array = arrptr;
return arrptr;
}
int main(void)
{
size_t cols = 30, rows = 40;
int (*matrix)[cols] = allocateMatrix(rows, cols, NULL);
if(matrix)
{
matrix[5][4] = 97;
matrix[4][2] = matrix[5][4] * 4;
printf("%d %d\n", matrix[5][4], matrix[4][2]);
}
free(matrix);
}
更简单,只有一次分配/免费,用法与数组相同,并且在删除一级间接时效率更高。
还要为大小和索引使用正确的类型:
size_t
在
scanf("%d", &**mat);
中,第一个*
将被它的&
对应物平衡,因为两个运算符具有相反的效果。
结果将是
*mat
,一个int *
类型的值。虽然 is 是 %d
格式说明符的正确类型,但 *mat
是矩阵中第一个子数组的地址。重复读取该地址的值将继续覆盖第一个子数组的第一个值(mat[0][0]
)。
因为你永远不会移动任何指针,矩阵的其余部分将保持未初始化状态。
也就是说,不需要手动管理你的指针,因为你已经在计算索引了。只需在索引中使用 array subscript notation,并获取每个值位置的地址。
scanf("%d", &mat[rows][cols]);
(参见会员访问运营商)
在 print 函数中,
mat - num
将解析为一些您不应尝试访问的地址,因为它在 mat
对象的范围之外。这是未定义行为的经典例子。
然后您尝试将
m
设置为通过该地址定位的某个值,但只有一次。
同样,您已经在计算索引,因此请充分利用它们。在
inner循环中将
m
设置为在 mat[rows][cols]
处找到的值,这样您就可以在每次迭代中更新它的值。
这是一个函数式程序,其中包含释放您分配的内存的示例。
size_t
是用于内存大小和索引的正确类型。我在这里坚持使用 int
,以匹配您的导师的 flawed 实现。)
#include <stdio.h>
#include <stdlib.h>
int **allocateIntStarArray(int);
int *allocateIntArray(int);
int **allocateMatrix(int, int);
void readValues(int **, int, int);
void print(int **, int, int);
int main(void) {
int rows, cols;
if (2 != scanf("%d %d", &cols, &rows)) {
fprintf(stderr, "Could not read matrix size information.\n");
return EXIT_FAILURE;
}
int **mat = allocateMatrix(rows, cols);
readValues(mat, cols, rows);
print(mat, cols, rows);
/* free your memory */
for (int i = 0; i < rows; i++)
free(mat[i]);
free(mat);
}
void readValues(int **mat, int ncols, int nrows) {
for (int i = 0; i < nrows; i++) {
for (int j = 0; j < ncols; j++) {
if (1 != scanf("%d", &mat[i][j])) {
fprintf(stderr, "Invalid value read.\n");
exit(EXIT_FAILURE);
}
}
}
}
void print(int **mat, int ncols, int nrows) {
for (int i = 0; i < nrows; i++) {
for (int j = 0; j < ncols; j++) {
int value = mat[i][j];
if (value > 1000)
printf("[X]");
else if (value >= 100)
printf("[*]");
else
printf("[ ]");
}
/* print a newline after every row */
putchar('\n');
}
}
int **allocateMatrix(int nrows, int ncols) {
int **mat = allocateIntStarArray(nrows);
for (int row = 0; row < nrows; ++row) {
mat[row] = allocateIntArray(ncols);
}
return mat;
}
/* Provided functions, do not edit */
int **allocateIntStarArray(int num) {
int **ptr = (int **) malloc(num * sizeof(int *));
return ptr;
}
int *allocateIntArray(int num) {
int *ptr = (int *) malloc(num * sizeof(int));
return ptr;
}
这里是我用来快速生成测试数据的程序:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand((unsigned) time(NULL));
int rows = (rand() % 20) + 1;
int cols = (rand() % 20) + 1;
printf("%d %d\n", rows, cols);
for (int i = 0, n = rows * cols; i < n; i++)
printf("%d ", rand() % 2000);
}
更新:
正如我所怀疑的那样,您正在混淆行和列的索引。
你的矩阵构建方式,第一个下标值(
matrix[r]
)对应于row,第二个下标值(matrix[r][c]
)对应于该行中的column
在
read_values
for(i=0;i<ncols;i++){
for(j=0;j<nrows;j++){
scanf("%d", &mat[i][j]);
}
}
在
print
for(i=0;i<ncols;i++){
for(j=0;j<nrows;j++){
int value = mat[i][j];
/* ... */
你已经翻转了那些,访问
mat[COLUMN as i][ROW as j]
.
你会越界访问内存,当
i >= nrows
,或者j >= ncols
.
翻转嵌套循环也可能是个好主意,这样它们就读作 “对于每一行,对于每一列”,这更符合下标语法:
for (int r = 0; r < nrows; r++)
for (int c = 0; c < ncols; c++)
scanf("%d", &mat[r][c]);
此外,在
main
中,只有在释放所有子数组first之后才必须
free(mat);
for(int i=0;i<rows;i++){
free(mat[i]);
}
free(mat); /* move this outside, after the loop */
否则
mat
将在第二次迭代中成为 悬空指针,并且 mat[i]
将调用 Undefined Behavior.
最后注意,为了符合作业要求,您的中间温度范围应该是
value >= 100
,因为该范围包括([100, 1000]
)。
#include <stdio.h>
#include <stdlib.h>
int * allocateIntArray(int num);
int ** allocateIntStarArray(int num);
int main(void)
{
int rown, coln,i,j;
scanf("%d %d",&coln,&rown);
int ** matrix = allocateIntStarArray(rown);
for(i = 0; i < rown; i++){
matrix[i] = allocateIntArray(coln);
}
for(i = 0; i < rown; i++){
for(j = 0; j < coln; j++){
scanf("%d",&matrix[i][j]);
}
}
for(i = 0; i < rown; i++){
for(j = 0; j < coln; j++){
if(matrix[i][j]>1000){
printf("[X]");
}
else{
if(matrix[i][j]>=100){
printf("[*]");
}
else{
printf("[ ]");
}
}
}
printf("\n");
}
return 0;
}
int ** allocateIntStarArray(int num){
int ** ptr = (int **) malloc(num * sizeof(int *));
return ptr;
}
int * allocateIntArray(int num){
int * ptr = (int *) malloc(num * sizeof(int));
return ptr;
}