[C] Programma matrice quadrata

martinuccia98
Ciao a tutti.
Sto cercando di creare un programma che chieda all'utente di inserire una matrice quadrata e infine che la visualizzi ma il programma mi segnala questi warning e non parte
- warning: 'j' is used uninitialized in this function [-Wuninitialized]
- warning: 'i' is used uninitialized in this function [-Wuninitialized]

il programma è questo

#include
int main () {

int i, j, rig, col;
int matrix[j];

printf ("Inserisci il numero di righe e di colonne di una matrice quadeata\n");
scanf ("%d%d", &rig, &col);

if ( rig != col) {
printf ("Non e' una matrice quadrata\n");
}

else {
printf ("Inserisci gli elementi della matrice\n");
for (i = 0; i < rig; i++)
for (j = 0; j < col; j++)
scanf ("d", &matrix[j]);
}

printf ("La matrice e': \n");
for (i = 0; i < rig; i++){
printf ("\n");
for (j = 0; j < col; j++) {
printf ("%d ", matrix[j]);
}}

return 0;
}

Risposte
claudio862
int i, j, rig, col;
int matrix[i][j];

Quanto valgono i e j nella seconda linea?

martinuccia98
In che senso?

martinuccia98
Ho risolto grazie

claudio862
Nel senso che stai creando una matrice i x j, ma i e j non sono definiti (che poi è il warning che da il compilatore).
Sarebbe meglio scrivere come hai risolto. Primo, perché qualcuno con lo stesso problema potrebbe trovare questa discussione e risolvere anche lui. Secondo, perché questo particolare problema ha una soluzione semplice che sembra giusta ma in realtà non lo è (o almeno non sempre).

martinuccia98
Ho dichiarato i e j inizializzandole a 0 così:

int i=O;
int j=0;

martinuccia98
L'outputdel programma però non è corretto

apatriarca
Secondo, perché questo particolare problema ha una soluzione semplice che sembra giusta ma in realtà non lo è (o almeno non sempre).

Ed in effetti è stato proprio questo il caso..

Prima di tutto non tutti i compilatori C permettono la dichiarazione di un array a partire da valori variabili. Si tratta di una funzionalità introdotta nel C99, ma che ha ricevuto molte critiche ed è stata quindi resa opzionale nel C11 (il nome dopo la C indica la data dello standard corrispondente). La funzionalità è poi presente (con alcune differenze) in alcuni compilatori. Nel C++ non è mai stata introdotta. In generale è meglio evitarla. Inoltre, anche decidendo di farne uso, è necessario che il valore delle dimensioni dell'array nel punto in cui l'array viene dichiarato abbiano un valore sensato. Zero non è certamente la dimensione che vuoi dare al tuo array. Devi invece leggere il valore della dimensione della tua matrice e solo successivamente dichiarare il tuo array (non è necessario dichiarare le variabili all'inizio della funzione o del blocco come sembra esserti stato insegnato). Se non fai uso di questa funzionalità devi invece ricorrere ad una delle seguenti alternative:
1. Dichiarare l'array con una dimensione costante massima per il tuo problema. Puoi per esempio decidere che il tuo programma non funziona per array più grandi di 100x100 e allocare un array di questa dimensione. Quando userai l'array accederai ovviamente solo alla parte che ti interessa.
2. Dichiarare l'array in modo dinamico usando malloc o calloc.

Un'altra cosa che correggerei nel codice è la richiesta di inserire il numero di righe e colonne. Se la matrice deve essere quadrata allora non ha senso chiedere all'utente due valori, è sufficiente chiedergliene uno..

martinuccia98
Se faccio partire il programma e inserisco come elementi della matrice 1,2,3,4 la matrice che mi da in output ha come prima riga 3,4 e come secondo riga ancora 3,4.. dipende sempre da quel problema?

Obidream
Come detto da apatriarca per questo tipo di esercizi conviene usare creare una matrice con dei valori ragionevolmente grandi (MAX_ROWS e MAX_COLUMNS, una matrice 100x100 è più che sufficiente in questo caso) e chiedere in seguito all'utente di inserire i numeri che effettivamente verranno utilizzati come righe e colonne.
Ovviamente bisogna adattare il codice postato qui sotto affinché i numeri inseriti non superino i valori fissati con i 2 define.

#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 100
#define MAX_COLUMNS 100


int main (void)
{
    int i, j, rig, col;
    int matrix[MAX_ROWS][MAX_COLUMNS];

    printf ("Inserisci il numero di righe e di colonne di una matrice quadeata\n");
    scanf ("%d %d", &rig, &col);
    if ( rig != col)
    {
        printf ("Non e' una matrice quadrata\n");
    }

    else
    {
        printf ("Inserisci gli elementi della matrice\n");
        for (i = 0; i < rig; i++)
        {
            for (j = 0; j < col; j++)
            {
                scanf ("%d", &matrix[i][j]);
            }
        }
    }

    printf ("La matrice e': \n");
    for (i = 0; i < rig; i++)
    {
        for (j = 0; j < col; j++)
        {
            printf ("%2d ", matrix[i][j]);
        }
        printf ("\n");
    }

    return EXIT_SUCCESS;
}

martinuccia98
Ok grazie ora funziona correttamente

apatriarca
Per completezza ti posto il codice delle altre due soluzioni.

La prima fa uso dei VLA (variable length array). Come ti ho detto è importante che la matrice sia a questo punto dichiarata quando il valore della variabile ha senso. Non va assolutamente usata in situazioni in cui la matrice è grande in quanto l'allocazione è completamente nascosta al programmatore e non c'è modo di sapere se ha avuto successo o meno. Non ho le idee chiare su cosa succeda in questo caso, forse lo standard neanche lo chiarisce.
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    int ordine = 0;

    puts("Inserisci l'ordine della matrice quadrata.");
    scanf("%d", &ordine);

    if (ordine <= 0)
    {
        fputs("Ordine non valido..\n", stderr);
        return EXIT_FAILURE;
    }

    /* Dichiara la matrice a questo punto del codice in modo che ordine sia
       valido..
    */
    int matrix[ordine][ordine];

    puts("Inserisci gli elementi della matrice.");
    for (int i = 0; i < ordine; i++)
    {
        for (int j = 0; j < ordine; j++)
        {
            scanf("%d", &matrix[i][j]);
        }
    }

    puts("La matrice e' la seguente.");
    for (int i = 0; i < ordine; i++)
    {
        for (int j = 0; j < ordine; j++)
        {
            printf("%d ", matrix[i][j]);
        }

        puts("");
    }

    return EXIT_SUCCESS;
}


Questo è invece il codice che fa uso dell'allocazione dinamica. Nota che in questo caso non è più possibile (semplice) accedere agli elementi usando la classica notazione degli array bidimensionali. E' inoltre necessario allocare e deallocare esplicitamente la memoria. In applicazioni reali è spesso la soluzione adottata. Esiste un modo spesso insegnato nei corsi di programmazione base alle università per usare la notazione per gli array bidimensionali anche in questo caso, ma complica enormemente la gestione della memoria, rende il codice più lento con gli unici vantaggi di una notazione più comoda per accedere agli elementi e la possibilità di avere ogni riga con un numero di elementi diverso (ha in effetti usi per rappresentare testi).
#include <stdio.h>
#include <stdlib.h>


int main (void)
{
    int ordine = 0;

    puts("Inserisci l'ordine della matrice quadrata.");
    scanf("%d", &ordine);

    if (ordine <= 0)
    {
        fputs("Ordine non valido..\n", stderr);
        return EXIT_FAILURE;
    }

    int *matrix = malloc(sizeof(int)*ordine*ordine);

    puts("Inserisci gli elementi della matrice.");
    for (int i = 0; i < ordine; i++)
    {
        for (int j = 0; j < ordine; j++)
        {
            scanf("%d", &matrix[i*ordine + j]);
        }
    }

    puts("La matrice e' la seguente.");
    for (int i = 0; i < ordine; i++)
    {
        for (int j = 0; j < ordine; j++)
        {
            printf("%d ", matrix[i*ordine + j]);
        }

        puts("");
    }

    free(matrix);

    return EXIT_SUCCESS;
}

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.