Попытка получить подмножество на основе строки и столбца матрицы с C - PullRequest
0 голосов
/ 23 марта 2020

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

Я не знаю, как извлечь меньшую матрицу 2x2 из большей матрицы на основе строки и столбца, например, если большая матрица:

1 2 3 4

5 6 7 8

9 1 2 3

4 5 6 7

и я хотел извлечь, начиная со строки 2 и столбца 3

я хотел бы выйти

7 8

2 3

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

кода:

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

//creating a variable type for the matrix created
struct matrix
{
    char name;
    float mValues[10][10];
    int nrows;
    int ncols;
};

//Function declarations
void matrixInput(struct matrix *mat, FILE *in);
void matrixDisplay(struct matrix mat);
float matrixDeterminant(struct matrix m1, struct matrix *m2, int *check);

int main()
{
    FILE *fin; //fin = fopen("matrix.txt","r")
    struct matrix matA;
    struct matrix matB;
    float determinant;
    int i,j,flag;




    fin=fopen("matrix.txt","r");
    if (fin!=NULL)
    {
        printf("File was found!\n");
        matrixInput(&matA,fin);      //Function call to create matrix
        matrixDisplay(matA);         //Function call to display the created matrix
        determinant=matrixDeterminant(matA,&matB,&flag);

        matrixDisplay(matB);

    }
    else printf("File not found\n");
}

void matrixInput(struct matrix *mat, FILE *in)
{
    int i;
    int j;
    struct matrix matA;

    in=fopen("matrix.txt","r");

    /*Asks for a single character input to name the matrix the user is creating*/
    printf("Enter a single character name for your matrix e.g A,B...\n");
    scanf("%c",&(*mat).name);

    /*Asks for a number of rows of the matrix, valid answers are between and equal to 1 and 10. If these conditions aren't met the program will keep
    prompting for a input that is valid*/
    printf("Enter number of rows in the matrix less than or equal to 10\n");
    scanf("%d",&(*mat).nrows);
    while ((*mat).nrows > 10 || ((*mat).nrows < 1))
    {
        printf("Input is not valid, please enter another number\n");
        scanf("%d",&(*mat).nrows);
    }

    /*Asks for a number of columns of the matrix, valid answers are between and equal to 1 and 10. If these conditions aren't met the program will
    keep prompting for a input that is valid*/
    printf("Enter number of columns in the matrix less than or equal to 10\n");
    scanf("%d",&(*mat).ncols);
    while ((*mat).ncols > 10 || (*mat).ncols < 1)
    {
        printf("Input is not valid, please enter another number\n");
        scanf("%d",&(*mat).ncols);
    }

        for(i=0; i<(*mat).nrows; i++)  //looping for number of rows user has entered
        {
            for(j=0; j<(*mat).ncols;j++)   //looping for number of columns user has entered
            {
                fscanf(in,"%f",&(*mat).mValues[i][j]);  //reading numbers from file and storing them into a 2D array
            }
        }


}


void matrixDisplay(struct matrix mat)
{
    int i,j;



    printf("\nMatrix name: %c  Number of rows are: %d  Number of columns are: %d\n\n",mat.name,mat.nrows,mat.ncols);   //Prints the name of the matrix to screen
    for(i=0; i<mat.nrows;i++)
    {
        printf("Row: %d",(i));
        for(j=0; j<mat.ncols;j++)
        {
            printf("%8.2f",mat.mValues[i][j]);
        }
        printf("\n");
    }

}

float matrixDeterminant(struct matrix m1, struct matrix *m2, int *check)
{
    FILE *fin;

    int Rowslim,Colslim,choicecol,choicerow,i,j;


    struct matrix matA;

    struct matrix matB;





    Rowslim=m1.nrows-1;
    Colslim=m1.ncols-1;

    fflush(stdin);

    printf("Please enter a single character name of the 2x2 matrix\n");
    scanf("%c",&(*m2).name);

    printf("Please enter a row number where 2x2 matrix should start, must be between 0 and %d\n",Rowslim);
    scanf("%d",&choicerow);

    printf("please enter a column number where 2x2 matrix should start, must be between 0 and %d\n",Colslim);
    scanf("%d",&choicecol);



    (*m2).nrows=2;
    (*m2).ncols=2;

    fin=fopen("matrix.txt","r");


    {
    for(i=0; i<(choicerow-1); i++)  //looping for number of rows user has entered
        {

            for(j=0; j<(choicecol-1);j++)   //looping for number of columns user has entered
            {
                fscanf(fin,"%f",&(*m2).mValues[i][j]);
            }
            fscanf(fin,"%f",&(*m2).mValues[i][j]);
        }
    }












}

1 Ответ

0 голосов
/ 23 марта 2020

Это код, который я использовал бы для копирования квадратных субматриц из одной матрицы в отдельную матрицу:

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

enum { MAX_MATRIX_SIZE = 10 };

struct matrix
{
    char name;
    float mValues[MAX_MATRIX_SIZE][MAX_MATRIX_SIZE];
    int nrows;
    int ncols;
};

typedef struct matrix Matrix;

static void matrixDisplay(const Matrix *mat);
static int matrixExtractSubMatrix(Matrix *m2, const Matrix *m1, char name,
                                 int r0, int c0, int size);

int main(void)
{
    Matrix matA =
    {
        .name = 'A', .nrows = 4, .ncols = 4,
        .mValues =
        {
            { 1, 2, 3, 4, }, { 5, 6, 7, 8, },
            { 9, 1, 2, 3, }, { 4, 5, 6, 7, },
        },
    };

    matrixDisplay(&matA);
    Matrix matB;
    for (int i = 0; i < matA.nrows - 2 + 1; i++)
    {
        for (int j = 0; j < matA.ncols - 2 + 1; j++)
        {
            if (matrixExtractSubMatrix(&matB, &matA, 'B', i, j, 2) != 0)
                fprintf(stderr, "Failed to extract sub-matrix\n");
            matrixDisplay(&matB);
        }
    }

    return 0;
}

static void matrixDisplay(const Matrix *mat)
{
    printf("\nMatrix %c (%dx%d):\n", mat->name, mat->nrows, mat->ncols);
    for (int i = 0; i < mat->nrows; i++)
    {
        printf("Row: %d:", i);
        for (int j = 0; j < mat->ncols; j++)
            printf(" %8.2f", mat->mValues[i][j]);
        printf("\n");
    }
}

static int matrixExtractSubMatrix(Matrix *m2, const Matrix *m1, char name,
                                  int r0, int c0, int size)
{
    assert(m2 != NULL && m1 != NULL);
    assert(r0 >= 0 && r0 + size <= m1->nrows);
    assert(c0 >= 0 && c0 + size <= m1->ncols);
    if ((r0 < 0 || r0 + size > m1->nrows) ||
        (c0 < 0 || c0 + size > m1->ncols))
        return -1;
    m2->name = name;
    m2->nrows = size;
    m2->ncols = size;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
            m2->mValues[i][j] = m1->mValues[r0 + i][c0 + j];
    }
    return 0;
}

В этом нет ничего примечательного. Это позволяет избежать копирования 412 байт в стек путем передачи структуры матрицы в качестве указателя, а не копирования всей структуры. Все функции static, кроме main(). Если функции должны быть видны за пределами этого файла, они должны быть объявлены в заголовке. Там нет заголовка, поэтому нет никаких функций (кроме main()), которые должны быть видны за пределами этого файла. Размерность массива в структуре Matrix (первоначально struct matrix, но для удобства typedef'd to Matrix) теперь является константой перечисления, поэтому ее можно использовать в коде для обозначения максимального размера массива в структура.

Я исключил ввод файла и функцию определителя; матрица жестко закодирована.

Тестовый код печатает все нерасширяющие подматрицы 2x2:

Matrix A (4x4):
Row: 0:     1.00     2.00     3.00     4.00
Row: 1:     5.00     6.00     7.00     8.00
Row: 2:     9.00     1.00     2.00     3.00
Row: 3:     4.00     5.00     6.00     7.00

Matrix B (2x2):
Row: 0:     1.00     2.00
Row: 1:     5.00     6.00

Matrix B (2x2):
Row: 0:     2.00     3.00
Row: 1:     6.00     7.00

Matrix B (2x2):
Row: 0:     3.00     4.00
Row: 1:     7.00     8.00

Matrix B (2x2):
Row: 0:     5.00     6.00
Row: 1:     9.00     1.00

Matrix B (2x2):
Row: 0:     6.00     7.00
Row: 1:     1.00     2.00

Matrix B (2x2):
Row: 0:     7.00     8.00
Row: 1:     2.00     3.00

Matrix B (2x2):
Row: 0:     9.00     1.00
Row: 1:     4.00     5.00

Matrix B (2x2):
Row: 0:     1.00     2.00
Row: 1:     5.00     6.00

Matrix B (2x2):
Row: 0:     2.00     3.00
Row: 1:     6.00     7.00

Можно было бы переименовать это как matrixExtractSquareSubMatrix() и создать другое функция matrixExtractSubMatrix(), которая сообщает отдельно, сколько строк и столбцов нужно скопировать:

int matrixExtractSubMatrix(Matrix *m2, const Matrix *m1, char name,
                           int r0, int c0, int ncols, int nrows);

Затем можно написать matrixExtractSquareSubMatrix() как встроенную функцию, чтобы вызвать matrixExtractSubMatrix(), передав аргумент size дважды.

Я не уверен, что создание таких подматриц будет эффективным, но это дополнительная проблема по сравнению с «правильной».

...