Número de linhas e/ou colunas para matriz genérica

Eu fiz um procedimento para uma matriz específica. Este procedimento transpõe uma matriz. Eu preciso passar para o procedimento o número de linhas para qualquer matriz na chamada deste procedimento. A função que eu criei invocará o procedimento anterior que transpõe a matriz. Eu sei que a linguagem C não faz distinção entre procedimento e função mas eu prefiro fazer esta distinção. Não quero encher muito este tópico. Quem tiver idéia sobre minha dúvida ,eu coloco aqui o código fonte que escrevi.
O esclarecimento pra mim será de grande utilidade. Obrigado.

Coloque o código, mas, eu não entendi o que é para ser feito!

#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstring>
#include <string.h>

#define M 12



void invt(float v[][M]) ;

int main(int argc, char *argv[])
{
float v[][M] = {
				{130.0,155.0,74.0,180.0, 34.0, 40.0, 80.0, 75.0, 20.0, 70.0, 82.0, 58.0} , 
				{150.0,188.0,159.0,126.0,151.0,137.0,121.0,130.0,50.0,100.0, 83.0, 60.0} , 
				{138.0, 110.0, 168.0, 160.0, 174.0, 120.0, 150.0, 139.0, 96.0, 104.0, 82.0, 60.0}
				} ;  

invt(v) ;


system("pause >> NULL");

}

 
void invt(float v[][M]) 
{
int i , j ; 	
float S[12][3];


  for(i=0; i < (sizeof(v[M])/sizeof(v[0][0])) ; i+=1)
 {
 	for(j=0; j < 3 ; j+=1)
 	{
	  S[i][j] = 0;
	 
	}
 printf("\n") ;
 }
puts("\n") ;  

 for(j=0; j <  (sizeof(v[M])/sizeof(v[0][0])) ; j+=1)
 {
 	for(i=0; i < 3 ; i+=1)
 	{
	 S[j][i] = v[i][j] ;
	}
printf("\n") ;
 }

 for(j=0; j <  (sizeof(v[M])/sizeof(v[0][0])) ; j+=1)
 {
 	for(i=0; i < 3 ; i+=1)
 	{
	 printf("%.2f\t",S[j][i]) ;
	}
printf("\n") ;
 }

}



Seria muito mais fácil se você postasse o enunciado do seu exercício.

Não é exercício. Eu não faço mais para-casas.
Eu quero enviar para a função o número de linha de uma matriz que pode variar.

Em C, passar arrays para funções é um tópico mais complicado do que parece. Se quiser uma explicação bem detalhada e aprofundada, sugiro ler aqui e aqui.

Mas em resumo, em geral é preferível que a função receba o array e o tamanho como parâmetros. No caso de array multi-dimensional, todas as dimensões que não são fixas seriam passadas como parâmetros.

No seu caso, você usou float v[][M], e como M é um valor fixo (criado no #define M 12), então apenas a quantidade de linhas não é fixa (a quantidade de colunas é conhecida).

Além disso, a matriz transposta terá dimensões diferentes da original (a menos que seja uma matriz quadrada, o que não é o caso). Por exemplo, no seu código você criou uma matriz 3x12, então a transposta será 12x3. Se você cria essa nova matriz dentro da função, o melhor seria retorná-la (e depois, fora da função, você faz o que quiser com ela - podendo inclusive imprimir, por exemplo).

Só que retornar matrizes em C também é meio chato, pois na verdade não dá, então teria que retornar um ponteiro. Ficaria assim:

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

#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
// número de linhas em um array 2D
#define NUM_ROWS(array_2d) ARRAY_LEN(array_2d)
// número de colunas em um array 2D
#define NUM_COLS(array_2d) ARRAY_LEN(array_2d[0])

#define M 12

float **transposta(float v[][M], size_t linhas) {
    size_t colunas = NUM_COLS(v);

    // matriz transposta tem dimensões "invertidas" (linhas da original são as colunas da transposta)
    // aloca a matriz
    float **t = malloc(sizeof(float *) * colunas);
    for (size_t i = 0; i < colunas; i++) {
        t[i] = malloc(sizeof(float) * linhas);
    }

    for (size_t i = 0; i < linhas; i++) {
        for (size_t j = 0; j < colunas; j++) {
            t[j][i] = v[i][j];
        }
    }

    return t;
}

int main(void) {
    float v[][M] = {
        {130.0, 155.0, 74.0, 180.0, 34.0, 40.0, 80.0, 75.0, 20.0, 70.0, 82.0, 58.0},
        {150.0, 188.0, 159.0, 126.0, 151.0, 137.0, 121.0, 130.0, 50.0, 100.0, 83.0, 60.0},
        {138.0, 110.0, 168.0, 160.0, 174.0, 120.0, 150.0, 139.0, 96.0, 104.0, 82.0, 60.0}
    };
    float **t = transposta(v, NUM_ROWS(v));

    // colunas da matriz original = linhas da matriz transposta (e vice-versa)
    size_t linhas_transposta = NUM_COLS(v);
    size_t colunas_transposta = NUM_ROWS(v);
    for (size_t i = 0; i < linhas_transposta; i++) {
        for (size_t j = 0; j < colunas_transposta; j++) {
            printf("%8.2f", t[i][j]);
        }
        printf("\n");
    }

    // libera a memória alocada pela função
    for (size_t i = 0; i < linhas_transposta; i++) {
        free(t[i]);
    }
    free(t);

    return 0;
}

Ou seja, a função cria a matriz transposta, retorna, e fora da função eu faço o que quiser com ela - no caso, eu imprimi, e a saída foi:

  130.00  150.00  138.00
  155.00  188.00  110.00
   74.00  159.00  168.00
  180.00  126.00  160.00
   34.00  151.00  174.00
   40.00  137.00  120.00
   80.00  121.00  150.00
   75.00  130.00  139.00
   20.00   50.00   96.00
   70.00  100.00  104.00
   82.00   83.00   82.00
   58.00   60.00   60.00

Claro que a função poderia criar a matriz e também imprimir, mas aí teria menos utilidade. Por exemplo, se você tivesse que passar a matriz transposta para outra função, ou fazer qualquer outra operação com ela que não seja imprimir, não seria possível. Fazendo desta forma, você tem a matriz e pode usá-la da forma que bem entender.


Outra alternativa é passar um ponteiro para a matriz transposta, e dentro da função ela aloca a memória e preenche os valores (assim não precisa retorná-la):

#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
// número de linhas em um array 2D
#define NUM_ROWS(array_2d) ARRAY_LEN(array_2d)
// número de colunas em um array 2D
#define NUM_COLS(array_2d) ARRAY_LEN(array_2d[0])

#define M 12

// passa a transposta como parâmetro, aí ela será preenchida dentro da função
void transposta(float v[][M], size_t linhas, float ***t) {
    size_t colunas = NUM_COLS(v);

    *t = malloc(sizeof(float *) * colunas);
    for (size_t i = 0; i < colunas; i++) {
        (*t)[i] = malloc(sizeof(float) * linhas);
    }

    for (size_t i = 0; i < linhas; i++) {
        for (size_t j = 0; j < colunas; j++) {
            (*t)[j][i] = v[i][j];
        }
    }
}

int main(void) {
    float v[][M] = {
        {130.0, 155.0, 74.0, 180.0, 34.0, 40.0, 80.0, 75.0, 20.0, 70.0, 82.0, 58.0},
        {150.0, 188.0, 159.0, 126.0, 151.0, 137.0, 121.0, 130.0, 50.0, 100.0, 83.0, 60.0},
        {138.0, 110.0, 168.0, 160.0, 174.0, 120.0, 150.0, 139.0, 96.0, 104.0, 82.0, 60.0}
    };
    float **t;
    transposta(v, NUM_ROWS(v), &t);

    size_t linhas_transposta = NUM_COLS(v);
    size_t colunas_transposta = NUM_ROWS(v);
    for (size_t i = 0; i < linhas_transposta; i++) {
        for (size_t j = 0; j < colunas_transposta; j++) {
            printf("%8.2f", t[i][j]);
        }
        printf("\n");
    }

    // libera a memória alocada pela função
    for (size_t i = 0; i < linhas_transposta; i++) {
        free(t[i]);
    }
    free(t);
    return 0;
}

E claro que o recomendado é sempre verificar o retorno de malloc para saber se a alocação deu certo - algo como:

*t = malloc(sizeof(float *) * colunas);
if (*t == NULL) {
    printf("Erro\n");
    exit(1);
}

Eu omiti essas verificações para deixar um pouco mais sucinto.