简体   繁体   中英

Weird issue - dimensional array input in c

I wrote a program to check wether a square n*n matrix is "perfect", meaning each line and row hold exactly one instance of each number from 1 to n .

I also wrote a main function to allocate memory for a given size and receive values of that matrix from the user.

It seems to work fine, except when I chose 4 for size and input this matrix: {{1,2,3,4},{2,1,4,3},{3,4,2,1),{4,3,1,2}} .

I get the matrix {{1,2,3,4},{2,**3**,4,3},{3,4,**3**,1},{4,3,1,2}} .

It looks like an input thing, but I can t find what s wrong :(

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int IsPerfect(int *arr, int size);

void main() {
    int size = 0, i = 0, j = 0, vol = 0;
    printf("please enter matrix size, 0 to exit:\n");
    scanf("%d", &size);
    printf("size is :%d\n", size);
    while (size != 0) {  //loop for allocating and inputing ,matrix
        int *pmatrix = (int *)malloc(size*size * sizeof(int));
        printf("please input matrix:\n");
        for (i = 0; i < size; i++)
            for (j = 0; j < size; j++) {
                printf("[%d][%d]\n", i, j);
                scanf("%d", ((pmatrix + i) + j));  //storing matrix values
            }
        for (i = 0; i < size; i++) {
            for (j = 0; j < size; j++)
                printf("[%d]", *((pmatrix + i) + j));  //printing matrix
            printf("\n");
        }
        IsPerfect(pmatrix, size);  //perfect check
        free(pmatrix);
        printf("please enter matrix size, 0 to exit:\n");
        scanf("%d", &size);
    }
    printf("bye bye!\n");
}

int IsPerfect(int *arr, int size) {
    int i = 0, j = 0, w = 0, perf = 1;
    int *check = (int *)malloc(sizeof(int) * size);

    for (w = 0; w < size; w++) {  //horizontal check
        for (i = 0; i < size; i++)
            *(check + i) = 0;
        for (i = 0; i < size; i++)
            for (j = 1; j <= size; j++)
                if (*((arr + w) + i) == j)
                    *(check + j - 1) = *(check + j - 1) + 1;
        for (i = 0; i < size; i++)
            if (*(check + i) == 0 || *(check + i) > 1)
                perf = 0;
    }
    for (w = 0; w < size; w++) {  //vertical check
        for (i = 0; i < size; i++)
            *(check + i) = 0;
        for (i = 0; i < size; i++)
            for (j = 1; j <= size; j++)
                if (*((arr + i) + w) == j)
                    *(check + j - 1) = *(check + j - 1) + 1;
        for (i = 0; i < size; i++)
            if (*(check + i) == 0 || *(check + i) > 1)
                perf = 0;
    }


    if (perf == 1)
        printf("the matrix is perfect\n");
    if (perf == 0)
        printf("the matrix is not perfect\n");
    free(check);
    return perf;
}

the following proposed code:

  1. cleanly compiles
  2. uses appropriate horizontal and vertical spacing for readability
  3. properly checks for (and handles) errors
  4. uses size_t for the index types as those values should never be less than 0 and better matches the expectations of the malloc() function
  5. uses statements like: for ( size_t col = 1; col <= size; col++ ) to limit the scope of local variables to the enclosing for() loop body
  6. corrects the problem with the input sequence, where the method of accessing the matrix elements was not correct
  7. does NOT correct the problem within the check() function, where, again, the method of accessing the matrix elements is not correct
  8. the problem in the check() function is the addressing of the elements of the array
  9. renamed variables i and j for better understanding. i ==> row and j ==> col

Note: this statement is typical of the problems in the code:

if ( *(check + row) == 0 || *(check + row) > 1 )

because check is at [0][0] so when adding row that is indexing across the first row IE [0][0]...[0][3]. Not what the code needs to do to check a column of the matrix

Perhaps you meant:

if ( *(check + size*row + col) == 0 || *(check + size*row + col) > 1 )

which would index [0][col]... [3][col]

And now, the proposed code:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>


int IsPerfect( int *arr, size_t size );

int main( void ) 
{
    size_t size;

    printf("please enter matrix size, 0 to exit:\n");
    scanf("%zu", &size);
    printf("size is :%zu\n", size);

    while ( size != 0 ) 
    {  //loop for allocating and inputing ,matrix
        int *pmatrix = malloc( size*size * sizeof(int) );
        if( ! pmatrix )
        {
            perror( "malloc failed" );
            exit( EXIT_FAILURE );
        }

        printf( "please input matrix:\n" );

        for ( size_t row = 0; row < size; row++)
        {
            for ( size_t col = 0; col < size; col++) 
            {
                printf( "[%zu][%zu]\n", row, col );
                if( scanf( "%d", &pmatrix[ (size*row) + col ]) != 1 )  //storing matrix values row by row
                {
                    fprintf( stderr, "scanf for matrix entry failed\n" );
                    free( pmatrix );
                    exit( EXIT_FAILURE );
                }
            }
        }

        for ( size_t row = 0; row < size; row++) 
        {
            for ( size_t col = 0; col < size; col++)
            {
                printf( "[%d]", pmatrix[ row*size + col ] );  //printing matrix
            }
            printf( "\n" );
        }

        IsPerfect( pmatrix, size );  //perfect check
        free( pmatrix );

        printf( "please enter matrix size, 0 to exit:\n" );
        scanf( "%zu", &size );
    }
    printf( "bye bye!\n" );
}


int IsPerfect( int *arr, size_t size ) 
{
    int  perf = 1;

    int *check = malloc( sizeof(int) * size );
    if( !check )
    {
        perror( "malloc failed" );
        exit( EXIT_FAILURE );
    }

    for ( size_t w = 0; w < size; w++ ) 
    {  //horizontal check
        for ( size_t row = 0; row < size; row++ )
        {
            *(check + row) = 0;
        }

        for ( size_t row = 0; row < size; row++ )
        {
            for ( size_t col = 1; col <= size; col++ )
            {
                if ( *((arr + w) + row) == (int)col )
                {
                    *(check + col - 1) = *(check + col - 1) + 1;
                }
            }
        }

        for ( size_t row = 0; row < size; row++ )
        {
            if ( *(check + size*row) == 0 || *(check + size*row) > 1 )
            {
                perf = 0;
            }
        }
    }

    for ( size_t w = 0; w < size; w++ ) 
    {  //vertical check
        for ( size_t row = 0; row < size; row++ )
        {
            *(check + size*row) = 0;
        }

        for ( size_t w = 0; w < size; w++ )
        {
            for ( size_t col = 1; col <= size; col++ )
            {
                 // why expect a position reference in the matrix to be the same as the content
                if ( *((arr + size*col) + w) == (int)col )      
                {
                    *(check + col - 1) = *(check + col - 1) + 1; //  causes seg fault
                }
            }
        }

        for ( size_t row = 0; row < size; row++ )
        {
            if ( *(check + row) == 0 || *(check + row) > 1 )
            {
                perf = 0;
            }
        }
    }


    if (perf == 1)
    {
        printf( "the matrix is perfect\n" );
    }

    else
    {
        printf( "the matrix is not perfect\n" );
    }

    free( check );
    return perf;
}

Note: a run of the proposed code and using the OPs data, results in:

[1][2][3][4]
[2][1][4][3]
[3][4][2][1]
[4][3][1][2]

so the input operation is now correct, but the check() function is still way off (and results in a seg fault event on (approx) line number 109:

if ( *((arr + size*col) + w) == (int)col ) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM