在开始讨论之前,我是C编程和指针的乞丐.:)

Edit: My problem has been resolved and I've put the final code and the desctiptions in the answers section below.

这段代码应该得到一个矩阵,并通过定义的函数以用户所需的方式对其进行操作.但输入过程不能正常工作,在中间崩溃.我从其中一个编写者那里得到了segmentation fault (core dumped).但甚至不知道这种问题会出现在哪里.非常感谢您的回复,因为我已经有几个小时没有进行调试了.

代码是这样的:(first part of the code is related to the matrix-manipulation functions - which in some them also some inputs may be taken - but the whole process of taking inputs is in the main function. So it may not be needed to read the whole code)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_matrix(int *matrix, int row, int column) 
{
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < column; j++) {
            printf("%d ", matrix[i * column + j]);
        }
        printf("\n");
    }
}

void ravel(int *matrix, int *row_address, int *column_address)
{
    for (int i = 0; i < (*row_address) * (*column_address); i++) {
        printf("%d ", matrix[i]);
    }
    printf("\n");
}

void reshape(int *row_address, int *column_address)
{
    scanf(" %d %d", row_address, column_address);
}

void resize(int **matrix_address, int *row_address, int *column_address)
{
    int first_size = (*row_address) * (*column_address);
    scanf(" %d %d", row_address, column_address);
    *matrix_address = (int *)realloc(*matrix_address, (*row_address) * (*column_address) * sizeof(int));
    for (int iterator = first_size; iterator < (*row_address) * (*column_address); iterator++) {
        (*matrix_address)[iterator] = (*matrix_address)[iterator % first_size];
    }
}

void append_row(int **matrix_address, int *row_address, int *column_address)
{
    int row[*column_address];
    for (int k = 0; k < *column_address; k++) {
        scanf(" %d", &row[k]);
    }
    *matrix_address = (int *)realloc(*matrix_address, ((*row_address) + 1) * (*column_address) * sizeof(int));
    for (int j = 0; j < (*column_address); j++) {
        (*matrix_address)[(*row_address) * (*column_address) + j] = row[j];
    }
    (*row_address)++;
}

void insert_row(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    int insert;
    scanf(" %d", &insert);
    int row[*column_address];
    for (int k = 0; k < *column_address; k++) {
        scanf(" %d", &row[k]);
    }
    *matrix_address = (int *)realloc(*matrix_address, ((*row_address) + 1) * (*column_address) * sizeof(int));
    for (int i = 0; i < insert; i++) {
        for (int j = 0; j < *column_address; j++) {
            (*matrix_address)[i * (*column_address) + j] = matrix[i * (*column_address) + j];
        }
    }
    for (int k = 0; k < *column_address; k++) {
        (*matrix_address)[insert * (*column_address) + k] = row[k];
    }
    for (int i = insert + 1; i < *row_address + 1; i++) {
        for (int j = 0; j < *column_address; j++)  {
            (*matrix_address)[i * (*column_address) + j] = matrix[(i - 1) * (*column_address) + j];
        }
    }
    (*row_address)++;
}

void append_column(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    int column[*row_address];
    for (int k = 0; k < *row_address; k++) {
        scanf(" %d", &column[k]);
    }
    *matrix_address = (int *)realloc(*matrix_address, (*row_address) * ((*column_address) + 1) * sizeof(int));
    for (int i = 0; i < *row_address; i++) {
        for (int j = 0; j < *column_address; j++) {
            (*matrix_address)[i * (*column_address + 1) + j] = matrix[i * (*column_address) + j];
        }
        (*matrix_address)[i * (*column_address + 1) + (*column_address)] = column[i];
    }
    (*column_address)++;
}

void insert_column(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    int insert;
    scanf(" %d", &insert);
    int column[*row_address];
    for (int k = 0; k < *row_address; k++) {
        scanf(" %d", &column[k]);
    }
    *matrix_address = (int *)realloc(*matrix_address, (*row_address) * ((*column_address) + 1) * sizeof(int));
    for (int i = 0; i < *row_address; i++) {
        for (int j = 0; j < insert; j++) {
            (*matrix_address)[i * (*column_address + 1) + j] = matrix[i * (*column_address) + j];
        }
        (*matrix_address)[i * (*column_address + 1) + insert] = column[i];
    }
    for (int i = 0; i < *row_address; i++) {
        for (int j = insert + 1; j < *column_address + 1; j++)  {
            (*matrix_address)[i * (*column_address + 1) + j] = matrix[i * (*column_address) + j - 1];
        }
    }
    (*column_address)++;
}

void delete_row(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    int delete;
    scanf(" %d", &delete);
    for (int i = 0; i < delete; i++) {
        for (int j = 0; j < *column_address; j++) {
            (*matrix_address)[i * (*column_address) + j] = matrix[i * (*column_address) + j];
        }
    }
    for (int i = delete; i < *row_address - 1; i++) {
        for (int j = 0; j < *column_address; j++)  {
            (*matrix_address)[i * (*column_address) + j] = matrix[(i + 1) * (*column_address) + j];
        }
    }
    *matrix_address = (int *)realloc(*matrix_address, (*row_address - 1) * (*column_address) * sizeof(int));
    (*row_address)--;
}

void delete_column(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    int delete;
    scanf(" %d", &delete);
    for (int i = 0; i < *row_address; i++) {
        for (int j = 0; j < delete; j++) {
            (*matrix_address)[i * (*column_address - 1) + j] = matrix[i * (*column_address) + j];
        }
    }
    for (int i = 0; i < *row_address; i++) {
        for (int j = delete; j < *column_address - 1; j++)  {
            (*matrix_address)[i * ((*column_address) - 1) + j] = matrix[i * (*column_address) + j + 1];
        }
    }
    *matrix_address = (int *)realloc(*matrix_address, (*row_address) * (*column_address - 1) * sizeof(int));
    (*column_address)--;
}

void tile(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    int x, y;
    scanf(" %d %d", &x, &y);
    *matrix_address = (int *)realloc(*matrix_address, ((*row_address) * y) * ((*column_address) * x) * sizeof(int));
    for (int i = 0; i < (*row_address) * y; i++) {
        for (int j = 0; j < (*column_address) * x; j++) {
            (*matrix_address)[i * (*column_address * x) + j] = matrix[(i % (*row_address)) * (*column_address) +  j % (*column_address)];
        }
    }
    (*row_address) *= y;
    (*column_address) *= x;
}

void transpose(int *matrix, int **matrix_address, int *row_address, int *column_address)
{
    for (int i = 0; i < *row_address; i++) {
        for (int j = 0; j < *column_address; j++) {
            (*matrix_address)[j * (*row_address) + i] = matrix[i * (*column_address) + j];
        }
    }
    // swapping row and column
    int tmp = *row_address;
    *row_address = *column_address;
    *column_address = tmp;
}

int main()
{
    int row, column;
    scanf("%d %d", &row, &column);
    int *matrix = (int *)malloc(row * column * sizeof(int));
    for (int i = 0; i < row * column; i++) {
        scanf("%d", matrix + i);
    }

    int *copy_matrix = (int *)malloc(row * column * sizeof(int));
    for (int i = 0; i < row * column; i++) {
            copy_matrix[i] = matrix[i];
    }
    
    char instruction[20];
    while (1) {
        scanf("%s", instruction);
        //gets(instruction);
        if (!strcmp(instruction, "exit"))
            break;
        for (int i = 0; i < row * column; i++) {
            copy_matrix[i] = matrix[i];
        }
        if (!strcmp(instruction, "ravel"))
            ravel(copy_matrix, &row, &column);
        else if (!strcmp(instruction, "reshape"))
            reshape(&row, &column);
        else if (!strcmp(instruction, "resize"))
            resize(&matrix, &row, &column);
        else if (!strcmp(instruction, "append_row"))
            append_row(&matrix, &row, &column);
        else if (!strcmp(instruction, "insert_row"))
            insert_row(copy_matrix, &matrix, &row, &column);
        else if (!strcmp(instruction, "append_column"))
            append_column(copy_matrix, &matrix, &row, &column);
        else if (!strcmp(instruction, "insert_column"))
            insert_column(copy_matrix, &matrix, &row, &column);
        else if (!strcmp(instruction, "delete_row"))
            delete_row(copy_matrix, &matrix, &row, &column);   
        else if (!strcmp(instruction, "delete_column"))
            delete_column(copy_matrix, &matrix, &row, &column);
        else if (!strcmp(instruction, "tile"))
            tile(copy_matrix, &matrix, &row, &column);
        else if (!strcmp(instruction, "transpose"))
            transpose(copy_matrix, &matrix, &row, &column);
        if (strcmp(instruction, "ravel"))
            print_matrix(matrix, row, column);
    }
    
    free(matrix);
    matrix = NULL;
    free(copy_matrix);
    copy_matrix = NULL;

    return 0;
}

以下是我的样例输入:

3 3
95 61 70
98 84 45
92 21 63
append_row
65 45 28
append_row
66 66 67
insert_column
2
32 40 1 52 52
delete_column
2
insert_column
0
63 98 71 49 94
insert_column
2
57 16 45 75 10
exit

推荐答案

代码太复杂了:

  • 当你分别传递矩阵数组和维度时,你需要在太多的地方解引用指针,这使得代码很难理解.
  • main循环中,您传递copy_matrix以及可能更新的rowcolumn值,但copy_matrix数组永远不会重新分配,因此它可能会变得太小,无法处理matrix个值的副本.这解释了try 在分配的数组末尾之外写入时可能导致的分段.

您应该使用matrix个 struct ,其中包括指向数组和维度的指针,并将指向这些 struct 的指针传递给各种处理程序.

以下是修改后的版本,供您学习:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct matrix {
    size_t rows, cols;
    int *arr;
} matrix;

#define MATRIX_GET(m, row, col)  ((m)->arr[(m)->cols * (row) + (col)])
#define MATRIX_SET(m, row, col, val)  ((m)->arr[(m)->cols * (row) + (col)] = (val))

/* read and discard the rest of the input line */
int flush_input(void) {
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;
    return c;
}

bool matrix_allocate(matrix *m, int rows, int cols) {
    m->rows = rows;
    m->cols = cols;
    m->arr = calloc(m->rows * m->cols, sizeof(*m->arr));
    if (m->arr == NULL) {
        fprintf(stderr, "cannot allocate matrix cells\n");
        return false;
    }
    return true;
}

void matrix_deallocate(matrix *m) {
    free(m->arr);
    m->arr = NULL;
}

bool matrix_init(matrix *m) {
    int rows = 0, cols = 0;
    if (scanf("%d %d", &rows, &cols) != 2) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (rows <= 0 || cols <= 0) {
        fprintf(stderr, "invalid matrix dimensions\n");
        return 1;
    }
    if (!matrix_allocate(m, rows, cols))
        return 1;

    for (size_t i = 0; i < m->rows * m->cols; i++) {
        m->arr[i] = 0;
        scanf("%d", &m->arr[i]);
    }
    return true;
}

bool matrix_copy(matrix *dest, const matrix *src) {
    matrix_deallocate(dest);
    if (!matrix_allocate(dest, src->rows, src->cols))
        return false;
    memcpy(dest->arr, src->arr, src->rows * src->cols * sizeof(*dest->arr));
    return true;
}

void print_matrix(const matrix *m) {
    for (size_t i = 0; i < m->rows; i++) {
        for (size_t j = 0; j < m->cols; j++) {
            printf("%d ", MATRIX_GET(m, i, j));
        }
        printf("\n");
    }
    printf("\n");
}

void ravel(const matrix *m) {
    for (size_t i = 0, size = m->rows * m->cols; i < size; i++) {
        printf("%d ", m->arr[i]);
    }
    printf("\n");
}

bool reshape(matrix *m)
{
    int x, y;
    if (scanf("%d %d", &y, &x) != 2) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (x <= 0 || y <= 0) {
        fprintf(stderr, "invalid dimensions: %d %d\n", y, x);
        return false;
    }

    size_t new_rows = y;
    size_t new_cols = x;
    size_t new_count = new_rows * new_cols;
    if (new_count != m->rows * m->cols) {
        fprintf(stderr, "total number of elements must be the same\n");
        return false;
    }

    int *new_arr = realloc(m->arr, sizeof(*m->arr) * new_count);
    if (new_arr == NULL) {
        fprintf(stderr, "cannot allocate matrix cells\n");
        return false;
    }
    m->rows = new_rows;
    m->cols = new_cols;
    m->arr = new_arr;
    return true;
}

bool resize(matrix *m)
{
    int x, y;
    if (scanf("%d %d", &y, &x) != 2) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (x <= 0 || y <= 0) {
        fprintf(stderr, "invalid dimensions: %d %d\n", y, x);
        return false;
    }

    size_t new_rows = y;
    size_t new_cols = x;
    size_t count = m->rows * m->cols;
    size_t new_count = new_rows * new_cols;
    int *new_arr = realloc(m->arr, sizeof(int) * new_count);
    if (new_arr == NULL) {
        fprintf(stderr, "cannot reallocate matrix cells\n");
        return false;
    }
    if (count == 0) {
        for (size_t i = 0; i < new_count; i++)
            new_arr[i] = 0;
    } else {
        for (size_t i = count; i < new_count; i++) {
            new_arr[i] = new_arr[i % count];
        }
    }
    m->rows = new_rows;
    m->cols = new_cols;
    m->arr = new_arr;
    return true;
}

bool insert_row_internal(matrix *m, size_t insert)
{
    int row[m->cols];
    for (size_t k = 0; k < m->cols; k++) {
        row[k] = 0;
        scanf("%d", &row[k]);
    }
    size_t new_rows = m->rows + 1;
    int *new_arr = realloc(m->arr, sizeof(*new_arr) * new_rows * m->cols);
    if (new_arr == NULL)
        return false;
    if (insert >= m->rows) {
        insert = m->rows;
    } else
    if (insert < m->rows) {
        memmove(&new_arr[(insert + 1) * m->cols], &new_arr[insert * m->cols],
                sizeof(*new_arr) * (m->rows - insert) * m->cols);
    }
    memcpy(&new_arr[insert * m->cols], row, sizeof(*new_arr) * m->cols);
    m->rows = new_rows;
    m->arr = new_arr;
    return true;
}

bool append_row(matrix *m)
{
    return insert_row_internal(m, m->rows);
}

bool insert_row(matrix *m)
{
    int row = 0;
    if (scanf("%d", &row) != 1) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (row < 0 || (size_t)row > m->rows) {
        fprintf(stderr, "invalid row: %d\n", row);
        return false;
    }
    return insert_row_internal(m, row);
}

bool insert_column_internal(matrix *m, size_t insert)
{
    int column[m->rows];
    for (size_t k = 0; k < m->rows; k++) {
        column[k] = 0;
        scanf("%d", &column[k]);
    }
    size_t new_cols = m->cols + 1;
    int *new_arr = realloc(m->arr, sizeof(*new_arr) * m->rows * new_cols);
    if (new_arr == NULL)
        return false;
    if (insert > m->cols)
        insert = m->cols;
    // copy from the end to allow for insertions
    for (size_t i = m->rows; i-- > 0;) {
        for (size_t j = m->cols; j-- > insert;) {
            new_arr[new_cols * i + j + 1] = new_arr[m->cols * i + j];
        }
        new_arr[new_cols * i + insert] = column[i];
        for (size_t j = insert; j-- > 0;) {
            new_arr[new_cols * i + j] = new_arr[m->cols * i + j];
        }
    }
    m->cols = new_cols;
    m->arr = new_arr;
    return true;
}

bool append_column(matrix *m)
{
    return insert_column_internal(m, m->cols);
}

bool insert_column(matrix *m)
{
    int col = 0;
    if (scanf("%d", &col) != 1) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (col < 0 || (size_t)col > m->cols) {
        fprintf(stderr, "invalid column: %d\n", col);
        return false;
    }
    return insert_column_internal(m, col);
}

bool delete_row(matrix *m)
{
    int row = 0;
    if (scanf("%d", &row) != 1) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (row < 0 || (size_t)row >= m->rows) {
        fprintf(stderr, "invalid row: %d\n", row);
        return false;
    }
    size_t new_rows = m->rows - 1;
    memmove(&m->arr[row * m->cols], &m->arr[(row + 1) * m->cols],
            sizeof(*m->arr) * (m->rows - row - 1) * m->cols);
    int *new_arr = realloc(m->arr, sizeof(*new_arr) * new_rows * m->cols);
    if (new_arr == NULL)
        new_arr = m->arr;
    m->arr = new_arr;
    m->rows = new_rows;
    return true;
}

bool delete_column(matrix *m)
{
    int col = 0;
    if (scanf("%d", &col) != 1) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (col <= 0 || (size_t)col >= m->cols) {
        fprintf(stderr, "invalid column: %d\n", col);
        return false;
    }
    size_t new_cols = m->cols - 1;
    for (size_t i = 0; i < m->rows; i++) {
        for (size_t j = 0; j < (size_t)col; j++) {
            m->arr[i * new_cols + j] = m->arr[i * m->cols + j];
        }
        for (size_t j = col; j < new_cols; j++) {
            m->arr[i * new_cols + j] = m->arr[i * m->cols + j + 1];
        }
    }
    int *new_arr = realloc(m->arr, sizeof(*new_arr) * m->rows * new_cols);
    if (new_arr == NULL)
        new_arr = m->arr;
    m->arr = new_arr;
    m->cols = new_cols;
    return true;
}

bool tile(matrix *m)
{
    int x = 0, y = 0;
    if (scanf("%d %d", &y, &x) != 2) {
        fprintf(stderr, "invalid input\n");
        flush_input();
        return false;
    }
    if (x <= 0 || y <= 0 || m->cols == 0 || m->rows == 0) {
        fprintf(stderr, "invalid dimensions\n");
        return false;
    }
    size_t rows = m->rows;
    size_t cols = m->cols;
    size_t new_rows = rows * y;
    size_t new_cols = cols * x;
    int *new_arr = calloc(sizeof(*new_arr), new_rows * new_cols);
    if (new_arr == NULL) {
        fprintf(stderr, "cannot allocate tiled matrix cells\n");
        return false;
    }
    for (size_t i = 0; i < new_rows; i++) {
        for (size_t j = 0; j < new_cols; j++) {
            new_arr[i * new_cols + j] = m->arr[(i % rows) * cols + (j % cols)];
        }
    }
    free(m->arr);
    m->arr = new_arr;
    m->rows = new_rows;
    m->cols = new_cols;
    return true;
}

bool transpose(matrix *m)
{
    size_t rows = m->rows;
    size_t cols = m->cols;
    int *new_arr = calloc(sizeof(*new_arr), rows * cols);
    if (new_arr == NULL) {
        fprintf(stderr, "cannot allocate transposed cells\n");
        return false;
    }
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            new_arr[j * rows + i] = m->arr[i * cols + j];
        }
    }
    // swapping rows and cols
    m->rows = cols;
    m->cols = rows;
    free(m->arr);
    m->arr = new_arr;
    return true;
}

int main(void)
{
    matrix m = { 0, 0, NULL };

    if (!matrix_init(&m))
        return 1;

    print_matrix(&m);

    char instruction[20];
    while (scanf("%19s", instruction) == 1) {
        bool success = true;
        if (!strcmp(instruction, "exit")) {
            break;
        } else
        if (!strcmp(instruction, "reshape")) {
            success = reshape(&m);
        } else
        if (!strcmp(instruction, "resize")) {
            success = resize(&m);
        } else
        if (!strcmp(instruction, "append_row")) {
            success = append_row(&m);
        } else
        if (!strcmp(instruction, "insert_row")) {
            success = insert_row(&m);
        } else
        if (!strcmp(instruction, "append_column")) {
            success = append_column(&m);
        } else
        if (!strcmp(instruction, "insert_column")) {
            success = insert_column(&m);
        } else
        if (!strcmp(instruction, "delete_row")) {
            success = delete_row(&m);
        } else
        if (!strcmp(instruction, "delete_column")) {
            success = delete_column(&m);
        } else
        if (!strcmp(instruction, "tile")) {
            success = tile(&m);
        } else
        if (!strcmp(instruction, "transpose")) {
            success = transpose(&m);
        } else
        if (!strcmp(instruction, "ravel")) {
            ravel(&m);
            continue;
        } else
        if (!strcmp(instruction, "print")) {
            print_matrix(&m);
            continue;
        } else
        if (*instruction >= '0' && *instruction <= '9') {
            /* ignore numbers */
            continue;
        } else {
            printf("%s: unknown command\n", instruction);
            continue;
        }
        if (!success) {
            printf("%s: command failed!\n", instruction);
        }
        print_matrix(&m);
    }

    matrix_deallocate(&m);
    return 0;
}

C++相关问答推荐

问关于C中的指针和数组

为什么listen()(在调用accept()之前)足以让应用程序完成3次握手?

测量ARM MCU中断延迟的问题

可以将C变量限制为特定的读/写速度吗?

C中的指针增量和减量(*--*++p)

C在声明带有值的数组时,声明大小有用吗?

是什么让numpy.sum比优化的(自动矢量化的)C循环更快?

限制不同类型的限定符

如何在C语言中正确打印图形

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

从不兼容的指针类型返回&&警告,但我看不出原因

如何摆脱-WIMPLICIT-Function-声明

用于计算位数和的递归C函数

在printf()中用%.*S格式填充长度为0的字符串是否会调用任何UB?如果是,是哪一个?

Makefile无法将代码刷新到ATmega328p

为什么GCC不能在 struct 初始值设定项中以sizeof作为条件的三进制中处理复合文字的编译时求值?

我错误地修复了一个错误,想了解原因

如何在Rust中处理C的longjmp情况?

快速准确计算double的小数指数

nullptr_t 是否会 destruct 类型双关或指针转换?