Ir ao conteúdo
  • Cadastre-se

C Exercicio sobre vetores multidimensionais


Ir à solução Resolvido por arfneto,

Posts recomendados

Enunciado:

Citação

Escreva uma função em C, listoff, que aceite como parâmetros dois vetores unidimensionais do mesmo tamanho: range e sub.

range representa a faixa de um vetor de inteiros. Por exeplo, se os elementos de range são:

 

       3 5 10 6 3

 

range representa um vetor a declarado por:

 

      int a[3][5][10][6][3]

 

Os elementos de sub representam índices para o vetor anterior. Se sub não estiver entre 0 e range-1, todos os índices a partir do iésimo em diant estão ausentes. No exemplo anterior, se os elementos de sub são:

 

       1 3 1 2 3

 

sub representa o vetor unidimensional a[1][3][1][2]. A função listoff deve imprimir os deslocamentos a partir da base do vetor a, representado por range, de todos os elementos de a que estejam incluídos no vetor (ou o deslocamento do único elemento, se todos os índices estiverem dentro dos limites) representado por sub. Pressuponha que o tamanho (esize) de cada elemento de a seja 1. No exemplo anterior listoff imprimiria os valores 4, 5 e 6.

Legenda:

esize == sizeof

 

Essa questão (Questão 1.2.7 - página 56 do livro)  foi retirada do livro  ESTRUTURA DE DADOS USANDO C (Tenenbaum/Langsam Augenstein)

 

Talvez a resposta esteja na seção "Vetores multidimensionais" que tá a partir da página 50, no final da sessão foi passado até um algoritmo que consegue percorrer as posições do vetor:

 

offset = 0;
for(j = 0 ; j < n ; j++){
	offset = r[j]*offset+i[j];
}
addr = baseVetor + esize * offset;

 

 

mas mesmo assim eu ainda tenho dúvidas sobre como:

                   -> OBS: Pode ser que eu tenha entendido errado o enunciado, ainda não compreendo esses novos termos de deslocamento, faixa, etc

Citação

Se os dois vetores (range e sub) tem o mesmo tamanho ->

                   cada elemento do vetor range = tamanho de cada dimensão do vetor

                   cada elemento do vetor sub = indice de cada dimensão do vetor

Com isso, na main.c eu criei o vetor range[n] e o vetor sub[n] (n é o tamanho do vetor, definido pelo usuario)


int n;

scanf("%i",&n);

int range[n],sub[n]
 for(int i = 0 ; i < n ; i++){
  scanf("%i", &range[i]);
}
for(int i = 0 ; i < n ; i++){
  scanf("%i", &sub[i]);
}

Com isso eu eu tenho o tamanho do vetor que vai ser criado (os elementos do vetor range) e tenho o elemento do vetor criado que vai ser procurado (os elementos do vetor sub)

 

Minha DÚVIDA vem agora:

Eu tenho que criar a função que vai receber os vetores range e sub


void listoff(int range[],sub[]){





}

Pelo que eu entendi do enunciado, eu tenho que criar uma vetor a dentro da função listoff, de tamanho a[range[n1]] ... [range[n-1]]

 

Meu problema é nesta parte... Como vou criar um vetor com base nos números dos elementos de range?

 

Já pensei em utilizar alocação dinamica mas aí eu teria que criar o ponteiro com base no número de elementos de range:


n = tamanho do vetor
range[n];

if(n == 4){
  int**** vet;
}

vet = (int****) malloc(range[0]*sizeof(int***);
vet[0] = (int***) malloc(range[1]*sizeof(int**);
vet[1] = (int***) malloc(range[1]*sizeof(int**);
                         .
                         .
                         .
vet[0][0][0] = (int*) malloc(range[3]*sizeof(int);
                         .
                         .
                         .
vet[n][n][n] = (int*) malloc (range[3]*sizeof(int);
                          

E sinceramente, ainda não tenho noção se da pra fazer isso.

                 

   - Imprimir os deslocamentos

 

 

Obrigado desde já!

Link para o comentário
Compartilhar em outros sites

  • Moderador

Caro usuário,

 

Seja bem-vindo ao Fórum do Clube do Hardware.

 

No intuito de servir como fonte de pesquisa no caso de instituições de ensino, informamos que incorrer no resolvimento por completo de questões relacionadas a disciplinas escolares de cursos técnicos e faculdades podem ser revistas e removidas pela Equipe de Moderação do Clube do Hardware.

 

Para sanar dúvidas sobre esse tipo de problema, por gentileza, publique o passo a passo do desenvolvimento da questão, projeto, monografia ou conteúdo em dúvida para que possamos analisar se a resposta está correta ou não, ou para que possa ser auxiliado com a dúvida no desenvolvimento do exercício.

 

Infelizmente, não há como resolver os trabalhos pelos usuários. O objetivo do Fórum do Clube do Hardware é auxiliar seus usuários a encontrar soluções para que possam sanar suas dúvidas, e não de trazer soluções prontas para seus usuários.. Além disso, copiar e colar respostas que não são de autoria própria do qualquer usuário é considerado plágio, o que é ilegal.

 

Esperamos que compreenda.

 

Atenciosamente,

Equipe Clube do Hardware

  • Triste 1
Link para o comentário
Compartilhar em outros sites

Boa tarde @DiF, tudo bem?

 

Então cara, ainda estou de férias da faculdade e estou me preparando para adiantar algumas máterias. Algoritmos e Estrutura de Dados é uma delas, que inclusive é a máteria que estou estudando com o livro que eu anexei no inicio do post.

 

Como pode ver, eu linkei o livro e mencionei onde encontrar o enunciado, e sobre qual conteúdo eu ACHO que a questão está se referindo.

 

Acredito que houve um mal entendido, pois eu fiz esse post com intuito de sanar minhas dúvidas que estão no final do post e não obter respostas prontas.

 

Talvez eu não tenha sido muito claro e por isso peço desculpas.

 

Vou reformular minhas dúvida  :)

 

Link para o comentário
Compartilhar em outros sites

11 horas atrás, Reberth Siqueira disse:

Meu problema é nesta parte... Como vou criar um vetor com base nos números dos elementos de range?

 

 

11 horas atrás, Reberth Siqueira disse:

Já pensei em utilizar alocação dinamica mas aí eu teria que criar o ponteiro com base no número de elementos de range:


Bom, obviamente você deve usar alocação dinâmica; é a unica maneira que C disponibiliza pra alocar novos recursos. Não seria o caso apenas se as dimensões da matriz (no caso, elementos do vetor range) fossem conhecidos no momento da compilação mas então o exercicio perderia a razão de ser. :D

Como bem disse DiF n
ão faremos o exercicio. Mas podemos ajudar com o que você precisa saber pra fazer. Suponha que queira alocar memoria pra um array com n floats:

 

float *array = malloc(sizeof(float)*n);

 

Agora, um array com n por m floats (duas dimensões) :

 

float *array = malloc(sizeof(float)*n*m);

 

E os elementos (i, j) podem ser acessados assim:

 

float f = array[i*m + j];

 

Os elementos dessa matriz 2D estão organizados num esquema chamado "row-major", ou seja, todas as linhas da matriz estão enfileiradas num longo vetor, cujo primeiro elemento é apontado por array[0] ou *array. Os elementos podem ser acessados da mesma forma assim:

 

float f = *(array + i*m + j);

 

De fato array apenas representa o primeiro endereço na memoria (a base do vetor) e i*m + j está calculando o endereço do proximo (ponteiro) elemento (i, j).

 

Alternativamente você pode fazer a mesma coisa usando um array de ponteiros, por exemplo:

 

    float **array = malloc(sizeof(float)*n);

    for (i = 0; i < n; ++i)
         array[i] = malloc(sizeof(float)*m);

 

E manipular os elementos assim:

    for (i = 0; i < n; ++i)
      for (j = 0; j < m; ++j)
         array[i][j] = ++a; // Ou, *( *(array + i) + j) = ++a;

 

E o mesmo conceito pra um array 3D, 4D etc. Nestes casos a formula pra calcular o proximo elemento seria diferente e eu deixo pra você o dever de casa.

 

Por fim, nos exemplos acima, n e m estão no vetor range do exercicio assim como i e j no vetor sub.

 

Edit: E não esqueça de dealocar tudo quando terminar, usando a função free( ).

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Ainda estou em dúvida em como criar o ponteiro que vai ser utilizado para realizar a alocação. Por exemplo

 

n = 1
  range[n] // 1 dimensão
  
  scanf("%i",&range[n]); // 2 

  int* vet;

vet = (int*) malloc(range[n] * sizeof(int)); // será criado um vetor vet[2]

 

Como a variável n  fica a critério do usuário, podemos ter n dimensões... Logo, pra cada dimensão eu teria que transformar o ponteiro atual em outro ponteiro:

 

se n = 1
  
  *vet //1 dimensao
se n = 2
  **vet // 2 dimensões
se n = 3
  ***vet // 3 dimensões
  

Existe um algoritmo que cria um ponteiro de ponteiro com base nas dimensões especificadas?

Link para o comentário
Compartilhar em outros sites

Acho que há uma pequena confusão com os termos:
 

1 hora atrás, Reberth Siqueira disse:

n = 1

range[n] // 1 dimensão

 

n == 1 representa a segunda dimensão (0 representa a primeira) e range[1] representa quantos elementos existem na tal segunda dimensão. Ou seja, o tamanho dos vetores range e sub determina o número de dimensões.

 

Por sua vez, cada elemento de range determina o tamanho de cada dimensão. P/ex, se range[2] == 100, então há 100 elementos na terceira dimensão.

Você pode começar a exercitar com um número fixo de dimensões e escrever um código que funcione, p/ex 3:

int range[3] = {100, 200, 300};

Com cem elementos na dimensão um (range[0]), duzentos na dimensão dois (range[1]) e trezentos na dimensão três (range[2]).

Melhor ainda, tente com apenas duas dimensões.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Por enquanto cheguei no código abaixo, onde é criado um vetor de n dimensões com range[n] elementos.

Se estiver correto, agora, estou tendo problemas pra entender a parte final da questão:

 

Em 07/01/2020 às 15:44, Reberth Siqueira disse:

A função listoff deve imprimir os deslocamentos a partir da base do vetor a, representado por range, de todos os elementos de a que estejam incluídos no vetor (ou o deslocamento do único elemento, se todos os índices estiverem dentro dos limites) representado por sub.

 

Até

Citação

...base do vetor a

 eu entendi. Depois disso... kkk

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


int main(){

int n; 
scanf("%i",&n);//2

int range[n],sub[n];

for(int i = 0 ; i < n; i++){
    scanf("%i",&range[i]); //5 5
}

for(int i = 0 ; i < n; i++){
    scanf("%i",&sub[i]); // 0 0
}


listOff(range,sub,n);



    return 0;

}

void listOff(int range[], int sub[],int n){

int base;
int aux=1;
int offset = 0;
int* vet;
int* posicao;

for(int i = 0 ; i < n ; i++){
    aux*= range[i];
}

vet = (int*) malloc(aux*sizeof(int));

base = vet;



for(int i = 0 ; i < n ; i++){

    offset=range[i]*offset+sub[i];
}

vet[0] = -3;


posicao = base+(offset*sizeof(int));

printf("%i",*posicao); //-3

free(vet);
}
Link para o comentário
Compartilhar em outros sites

  • Solução
1 hora atrás, Reberth Siqueira disse:

Por enquanto cheguei no código abaixo, onde é criado um vetor de n dimensões com range[n] elementos.

Se estiver correto, agora, estou tendo problemas pra entender a parte final da questão

 

Acho que está no caminho certo.

 

Foi azar eu acho pegar justo esse livro, exercício e tradução eu acho. Esse livro é o máximo em C e estruturas de dados e o autor é tipo um ícone. Mas...

 

Se tiver paciência, acompanhe o que vou escrever. Pode ser útil em outros casos. Estou praticamente de férias também e me interessei pelo problema ao ver o que imaginei ser uma resposta impossível :D

 

Não tenho acesso ao livro original, até procurei (um pouco, confesso). Acho que eu até usei uma edição desse livro, mas não o tenho mais. Tem problemas nessa tradução e na formatação, por exemplo na própria página 56 onde se discute a teoria do problema. Esse livro é de '89 e essa edição em português é de 95. Eu gostaria mesmo de ler o texto original. Veja a formatação toda zoada na fórmula. E o [in] em itálico por engano e o baseiar) ao invés de base(ar) só porque o i fica logo abaixo do ( no teclado... E acho que truncou a resposta do exercício :(

 

A parte da teoria

 

listoff-b.png.d40a47020c04b460694b5de51fd328ee.png

O exercício1.2.7

 

listoff.png.795843ec6682781b2ec79708e3dcaed5.png


Vou explicar a seguir.

 

De todo modo, entenda que o que listoff(range,sub) deve fazer é listar um elemento ou potencialmente uma "fatia" de elementos do vetor a. O que se chama eu acho de projeção. O livro é claro voltado a programação em C e por isso a nota para pressupor que esize seja 1: C tem aritmética de ponteiros e vai multiplicar o deslocamento pelo tamanho

 

Alocando o vetor a

 

Eis o protótipo de malloc():

void *malloc(size_t size)

Quando você aloca por exemplo um vetor de estruturas, você faz a conta do tamanho total a alocar. Peguei um pedaço de um programa que postei outro dia aqui para exemplo

struct exemplo
{
    int    i_parametro;
    double d_parametro;
    char*  s_parametro;
    int    (*f_parametro_i)(int);
    void   (*f_parametro_v)(int, int);
};
typedef struct exemplo Exemplo;

 

Esse trem tem um certo tamanho. Imagina uma função 

 

Exemplo*    aloca_exemplo(int n);

Que faz o óbvio: aloca um array dessas coisas, de tamanho n. Veja esse exemplo abaixo, que aloca as n structs e numera o array usando o valor de exemplo.i_parametro para ficar fácil de conferir depois

Exemplo* aloca_exemplo(int total)
{
    int      a_alocar = total * sizeof(Exemplo);
    Exemplo* pE = (Exemplo*)malloc(a_alocar);
    if (pE == NULL) return pE;
    for (int i = 0; i < total; i += 1)(*(pE + i)).i_parametro = i;
    return pE;
};

 

Veja essa linha que numera: 
 

    for (int i = 0; i < total; i += 1)(*(pE + i)).i_parametro = i;

E vai entender o porque da nota lá no livro para considerar esize = 1: o compilador faz essa conta e isso é uma coisa sensacional da linguagem 😄 aritmética de ponteiros...

 

Esse trecho testa o serviço

    int         n = 125;

    Exemplo*    p = aloca_exemplo(n);
    if (p == NULL) exit(-1);
    printf("so pra testar, ultimo valor dos %d a partir de 0 = %d\n", n, (*(p+n-1)).i_parametro);
    free(p);

E o printf() mostra o esperado: 124

so pra testar, ultimo valor dos 125 a partir de 0 = 124
Citação

Lá está a conta de novo: o compilador calcula (n-1) em relação ao tamanho total da estrutura, que eu nem sei qual é. Isso torna essa linguagem tão adequada para programar drivers e sistemas, talvez porque ela tenha sido escrita exatamente para isso.


De volta ao tópico e ao livro

 

Por exemplo, se os elementos de range são:
3 5 10 6 3
range representa um vetor a declarado por:

i n t  a  [3] [5] [10] [6] [3] ;

Pois é: então você vai alocar um certo número de int e esse número vai ser dado por esses índices aí. Cada int tem sizeof(int) bytes. E quantos são? basta multiplicar tudo isso

Imagine uma função similar a que eu mostrei acima, a do meu programa antigo

int*        aloca_exemplo_range(char*);

Que você chama assim:

    int* ex_range = aloca_exemplo_range("3 5 10 6 3");

E mostra isso 

 

range = [3 5 10 6 3]

range is = [3 5 10 6 3]
        planes = 5
        unit size = 4
        quant = 2700
        total size = 10800

Eis uma implementação. Desculpe escrever metade em inglês metade em português

//
// aloca um vetor como no livro
//
int* aloca_exemplo_range(char* range)
{
    char Range[81];
    strncpy(Range, range, 80);
    unsigned int sz = 1;
    int planos = 0;
    char* valor;
    const char* delim = " ";
    printf("range = [%s]\n", range);
    valor = strtok(Range, delim);
    while (valor != NULL)
    {
        sz = sz * atoi(valor);
        planos = planos + 1;
        valor = strtok(NULL, delim);
    };
    printf("\nrange is = [%s]\n\tplanes = %d\n\tunit size = %d\n\tquant = %d\n\ttotal size = %d\n\n",
        range, planos, sizeof(int), sz, sz*sizeof(int) );

    return (int*) malloc( sz*sizeof(int));
};

O problema de como está escrito no livro é que se você só tem um int* não tem como saber o tamanho, o número de dimensões. Sim, se pode usar exóticos varargs, ou usar um sentinela no vetor, usando -1 como valor no índice seguinte, como { 3,5,10,6,3-1 } para esse exemplo, e aí na hora de alocar você sabe que são só 5 dimensões, ou planos como diz o autor. Mas eu usei a própria string no exemplo porque fica muito mais fácil de testar :D.

 

Imagine poder escrever 

    listoff_str("3 5 10 6 3", "1 3 1 2 2");
    listoff_str("3 5", "4 4");
    listoff_str("3 5 2", "2 6 2");

E o programa faz o resto. Não é mais simples? Afinal esse é um exercício de estrutura de dados.

 

Porque funciona?

 

Calculamos a área a alocar usando strtok() para separar os valores de cada plano na string e multiplicamos. Depois multiplicamos pelo tamanho do tipo a ser usado usando sizeof() e um cast para o ponteiro (void*) retornado por malloc() exatamente como de costume. E retornamos o ponteiro.

 

E tendo o vetor alocado como acessar pelo indice?

 

no livro está a fórmula, que copiei acima. Mais precisamente eis a fórmula

listoff-c.png.c36f97cf1ab84e30858d05a0a325ce4c.png


Então é só escrever, mentalmente agradecendo ao prof. Aaron

 

int calcula_offset(const int range[], const int index[], const int size)
{
    int offset = 0;
    for (int j = 0; j < size; j++)
        offset = range[j] * offset + index[j];
    return offset;
};    // calcula_offset()

Essa função recebe os vetores e calcula o offset, como está no livro.

Veja o que acontece para 1 dimensão:

offset = index[0];

E para 2?
imagine a matriz M[2][4] 

    7 6 5 4
    3 2 1 0

e queremos calcular o deslocamento de M[1][2], o 1. Assim Range={2,4} e Index={1,2}
C aloca por linha, como está escrito na no livro toda hora então isso vai estar assim na memória

7 6 5 4 3 2 1 0

E o deslocamento que queremos é claro 6.

Na fórmula do livro isso vai dar Index[1] + Index[0] * Range[1] e isso dá... 2 + 1 * 4. 6


A demonstração está logo acima no livro

 

E listoff()
 

Está no livro 

    addr = base(array) + esize*offset; // by the book

e o offset está na fórmula. Quando um dos índices passar do range você para de calcular. Está no enunciado

Exemplo

 

range = 4 2 4 

e sub = 4 2 0

Então a "projeção" de sub em range vai trazer todo mundo a partir de 4 1 0 até 4 1 3, ou seja, 4 elementos.


Não consigo ler de outro modo. OK, estou de férias e não li muito. Mas é o que está escrito lá.


No exemplo do Exercicio


Range 3 5 10 6 3 e Sub 1 3 1 2 3 o último índice sub[4] é maior que range[4] então listoff() vai listar 3 caras:

1 3 1 2 0
1 3 1 2 1
1 3 1 2 2

só que não são os deslocamentos 4 5 e 6 de jeito nenhum. Mesmo porque

4 é o deslocamento de a[0][0][1][0]
5 é o deslocamento de a[0][0][1][1]
4 é o deslocamento de a[0][0][1][2]

Os deslocamentos são 1464 1465 e 1466. como pode ver na saída do programa de exemplo abaixo. Acho que algo saiu errado na revisão. Ou eu estou errado mesmo. [não creio]

 

Eis uma implementação de listoff, cheia de printf() para ajudar a entender
 

void listoff(const int* range, const  int* sub, int n)
{
    // addr = base(ar) + esize*offset; by the book
    printf("\nn = %d\n",n);
    printf("Range: ");
    for (int i = 0; i < n; i++) printf("%d ", range[i]);
    printf("\n");
    printf("  Sub: ");
    for (int i = 0; i < n; i++) printf("%d ", sub[i]);
    printf("\n");
    //
    int esize = 1;
    int last_plane = -1;

    for (int i = 0; i < n; i++)
    {
        if (sub[i] >= range[i])
        {
            last_plane = i;
            break;
        }
    }    // for

    if (last_plane == -1)
    {
        printf("unico elemento: addr = base + 1 * (%d)\n", calcula_offset(range, sub, n));
        return;
    };    // if

    // vai listar um monte de gente talvez...
    int* novo = (int*) malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) novo[i] = sub[i];
    for (int i = last_plane; i < n; i++)
    {
        novo[i] = 0;
    };
    printf("\nBase: ");
    for (int i = 0; i < n; i++) printf("%d ", novo[i]);
    printf("\n");

    printf("offset da base : %d ", calcula_offset(range, novo, n));

    // final
    for (int i = last_plane; i < n; i++)
    {
        novo[i] = range[i] - 1;
    };    // for
    printf("offset do final: %d ", calcula_offset(range, novo, n));

    return;
};    // listoff()


Optei por listar só o primeiro e o último endereço do offset para não ficar longo demais

 

listoff_str() usando strings para testar com mais conforto

void        listoff_str(const char* range_str, const char* sub_str)
{
    // cria os vetores de int on-the-fly para facilar os testes de listoff()
    // usando as strings de entrada
    printf(
        "\n\nteste listoff(\"%s\",\"%s\",n) ... listoff_str(char* range, char* sub)\n",
        range_str, sub_str);

    char vetor[81];
    strncpy(vetor, range_str, 80);
    char* valor;
    const char* delim = " ";
    valor = strtok(vetor, delim);
    int planos = 0;
    while (valor != NULL)
    {
        planos = planos + 1;
        valor = strtok(NULL, delim);
    };
    printf("\n\tdimensoes = %d\n", planos);
    // agora cria o vetor e converte
    strncpy(vetor, range_str, 80);
    int* range = malloc(planos * sizeof(int));
    valor = strtok(vetor, delim);
    int plano = 0;
    while (valor != NULL)
    {
        range[plano] = atoi(valor);
        plano += 1;
        valor = strtok(NULL, delim);
    };
    // agora mostra o vetor criado
    printf("\tVetor range: ");
    for (int i = 0; i < planos; i++)
        printf(" %d", range[i]);
    printf("\n");

    // agora o sub

    strncpy(vetor, sub_str, 80);
    int* sub = malloc(planos * sizeof(int));
    valor = strtok(vetor, delim);
    plano = 0;
    while (valor != NULL)
    {
        sub[plano] = atoi(valor);
        plano += 1;
        valor = strtok(NULL, delim);
    };
    // agora mostra o vetor criado
    printf("\tVetor   sub: ");
    for (int i = 0; i < planos; i++)
        printf(" %d", sub[i]);
    printf("\n");

    printf("\nChamando listoff com os vetores criados. de ordem %d\n", planos);
    listoff(range, sub, planos);

    free(range);
    free(sub);
    return;
};    // listoff_str()

Uma função main() que testa isso

int main(int argc, char** argv)
{
    int         n = 125;

    Exemplo*    p = aloca_exemplo(n);
    if (p == NULL) exit(-1);
    printf("so pra testar, ultimo valor dos %d a partir de 0 = %d\n",
         n, (*(p+n-1)).i_parametro);
    free(p);

    int* ex_range = aloca_exemplo_range("3 5 10 6 3");

    const int range[2] = { 24,80 };
    const int index[2] = { 23,79 };
    int offset = calcula_offset(range, index, 2);
    printf("offset para a[24][80] em int a[23,79] = %d\n", offset);

    const int range5[5] = { 3,5,10,6,3 };
    const int index5[5] = { 2,4,9,5,2 }; 
    offset = calcula_offset(range5, index5, 5);
    printf("offset para o ultimo elemento de a[3][5][10][6][3] = %d\n", offset);

    const int index6[5] = { 1,3,1,2,0 };
    offset = calcula_offset( range5, index6, 5);
    printf("offset para o a[1][3][1][2][0] em int a[3][5][10][6][3] = %d\n", offset);

    listoff_str("3 5 10 6 3", "1 3 1 2 2");
    listoff_str("3 5", "4 4");
    listoff_str("3 5 2", "2 6 2");

    return 0;
}    // main()

Ele mostra isso
 

so pra testar, ultimo valor dos 125 a partir de 0 = 124
range = [3 5 10 6 3]

range is = [3 5 10 6 3]
        planes = 5
        unit size = 4
tquant = 2700
        total size = 10800

offset para a[24][80] em int a[23,79] = 1919
offset para o ultimo elemento de a[3][5][10][6][3] = 2699
offset para o a[1][3][1][2][0] em int a[3][5][10][6][3] = 1464


teste listoff("3 5 10 6 3","1 3 1 2 3",n) ... listoff_str(char* range, char* sub)

        dimensoes = 5
        Vetor range:  3 5 10 6 3
        Vetor   sub:  1 3 1 2 3

Chamando listoff com os vetores criados. de ordem 5

n = 5
Range: 3 5 10 6 3
  Sub: 1 3 1 2 3

Base: 1 3 1 2 0
offset da base : 1464 offset do final: 1466

teste listoff("3 5","4 4",n) ... listoff_str(char* range, char* sub)

        dimensoes = 2
        Vetor range:  3 5
        Vetor   sub:  4 4

Chamando listoff com os vetores criados. de ordem 2

n = 2
Range: 3 5
  Sub: 4 4

Base: 0 0
offset da base : 0 offset do final: 14

teste listoff("3 5 2","2 6 2",n) ... listoff_str(char* range, char* sub)

        dimensoes = 3
        Vetor range:  3 5 2
        Vetor   sub:  2 6 2

Chamando listoff com os vetores criados. de ordem 3

n = 3
Range: 3 5 2
  Sub: 2 6 2

Base: 2 0 0
offset da base : 20 offset do final: 29

Um programa de teste completo pode ser visto aqui e baixado aqui.  Optei por mostrar apenas o deslocamento inicial e o final

Boas férias!

  • Amei 1
Link para o comentário
Compartilhar em outros sites

Eu estou com o livro físico e nele está igual o pdf :(

Enfim,

 

23 horas atrás, arfneto disse:

Quando você aloca por exemplo um vetor de estruturas, você faz a conta do tamanho total a alocar. Peguei um pedaço de um programa que postei outro dia aqui para exemplo


struct exemplo
{
    int    i_parametro;
    double d_parametro;
    char*  s_parametro;
    int    (*f_parametro_i)(int); //<- ESSE        //_ Protótipo 
    void   (*f_parametro_v)(int, int); //<- ESSE   //            de função?
};
typedef struct exemplo Exemplo;

 

 

Eu não entendi os ultimos dois parametros... Eles são protótipos de função?? Eu to entre prototipo de função e ponteiros que podem ser alocados para virar vetor/matriz

 

23 horas atrás, arfneto disse:

Os deslocamentos são 1464 1465 e 1466

 

Esses deslocamentos são números de bytes?

 

 

Enfim, também consegui chegar nos números deslocamentos que você chegou. Tá muito confuso pra mim esse exercicio kkkk

 

Mas desde já obrigado pela ajuda!! Sempre é bom contar com você nos tópicos que eu crio, sempre sei que vou aprender muita coisa.

Curti muito a tua explicação sobre vetores de estruturas.

 

Boas ferias pra você também

 

Link para o comentário
Compartilhar em outros sites

10 horas atrás, Reberth Siqueira disse:

Eu estou com o livro físico e nele está igual o pdf :(

 

O livro original em inglês? Que edição?
Como te disse, os deslocamentos são 1464 1465 e 1466, então a resposta está errada... E só naquela página tem 3 outros erros, como falei

 

10 horas atrás, Reberth Siqueira disse:

Esses deslocamentos são números de bytes?

 

Não. Em número de esize do vetor. C faz a conta dos deslocamentos e por isso está lá no exercício para você considerar esize = 1. A fórmula é mesmo no final 

addr = base(ar) + esize * offset;

como está no livro e como estamos acostumados a usar sem pensar. Só que com muitas dimensões fica mais complicado

 

10 horas atrás, Reberth Siqueira disse:

Eu não entendi os ultimos dois parametros... Eles são protótipos de função?? Eu to entre prototipo de função e ponteiros que podem ser alocados para virar vetor/matriz

 

struct exemplo
{
    int    i_parametro;
    double d_parametro;
    char*  s_parametro;
    int    (*f_parametro_i)(int); //<- ESSE        //_ Protótipo 
    void   (*f_parametro_v)(int, int); //<- ESSE   //            de função?
};
typedef struct exemplo Exemplo;

Eu reaproveitei o programa que está em 

 para ganhar tempo :). Só queria mostrar um exemplo mais completo de como declarar um vetor de estruturas aqui e peguei essa. Não são protótipos de função mas apenas ponteiros para funções. Era para mostrar no tópico original que você pode simplesmente passar um ponteiro para qualquer coisa e depois usar de acordo com sua lógica. Por isso a estrutura tem variáveis de vários tipos e inclui esses dois últimos para ficar mais completo

 

A bit off-topic: como ler int    ( *f (int) (int)  );

 

  • Você deve ler a partir da direita.
  • Tem o ) então é uma função.
  • Tem (int)(int) então ela recebe dois int como argumentos.
  • Tem o nome d variável, f.
  • Tem um * então é um ponteiro.
  • Tem int( então ela retorna (int).
  • Ou seja, f é um ponteiro para uma função que retorna int e recebe dois parâmetros int. 

 

*f é uma função como esses protótipos

int		funcao_1(int, int);
int		funcao_2(int, int);
int		funcao_3(int, int);

E você poderia usar assim

int (*pF)(int, int) = NULL;
int r;

    f = funcao_1;
	r = (*f)(1,2);
	printf("\nUsando funcao_1... Retornou %d\n", r);

    f = funcao_2;
	r = (*f)(1,2);
	printf("\nUsando funcao_2... Retornou %d\n", r);


EXEMPLO: VFT: um array de ponteiros para funções

 

Postei um programa nesse forum que usa isso para criar um vetor de endereços de funções, não me lembro do tópico mas era algo relacionado a C++ e funções virtuais perto de 14 de dezembro. Isso é o que se chama Virtual Function Table na literatura --- VFT --- e não sei se é um bom nome.

 

O programa mostra

Chama as 3 funcoes pela ordem
Ola!Esta e a funcao_1(1,2)
Ola!Esta e a funcao_2(3,4)
Ola!Esta e a funcao_3(5,6)

Chama as 3 funcoes a partir do vetor de enderecos
Ola!Esta e a funcao_1(11,22)
Ola!Esta e a funcao_2(33,44)
Ola!Esta e a funcao_3(55,66)

Chama as 3 funcoes a partir de uma funcao seletora

seletor(1) Chama funcao_1()
Ola!Esta e a funcao_1(100,100)

seletor(2) Chama funcao_2()
Ola!Esta e a funcao_2(200,200)

seletor(3) Chama funcao_3()
Ola!Esta e a funcao_3(300,300)

Eis o programa. É um conceito MUITO importante: permite que você passe para uma função qualquer um vetor de endereços funções para usar do outro lado como preciso, usando uns poucos bytes e viabiliza coisas importantes em sistemas operacionais por exemplo

#include "stdio.h"
#include <Windows.h>

typedef int (*pF_int_int)(int, int);


int		funcao_1(int, int);
int		funcao_2(int, int);
int		funcao_3(int, int);

int		seletor(int, pF_int_int*);

int main(int argc, char** argv)
{
	pF_int_int VFT[4]; // nao usei f[0] so porque nao
	int (*pF)(int, int) = NULL;
	printf("\nChama as 3 funcoes pela ordem\n");
	funcao_1(1, 2);
	funcao_2(3, 4);
	funcao_3(5, 6);

	VFT[1] = funcao_1;
	VFT[2] = funcao_2;
	VFT[3] = funcao_3;

	printf("\nChama as 3 funcoes a partir do vertor de enderecos\n");
	VFT[1](11, 22);
	VFT[2](33, 44);
	VFT[3](55, 66);

	printf("\nChama as 3 funcoes a partir de uma funcao seletora\n");
	for (int i = 1; i <= 3; i += 1)	seletor(i, VFT);
	return 0;
}

int		funcao_1(int a, int b)
{	printf("Ola!Esta e a funcao_1(%d,%d)\n", a, b);
	return 0;
};

int		funcao_2(int a, int b)
{	printf("Ola!Esta e a funcao_2(%d,%d)\n", a, b);
	return 0;
};

int		funcao_3(int a, int b)
{	printf("Ola!Esta e a funcao_3(%d,%d)\n", a, b);
	return 0;
};

int		seletor(int qual, pF_int_int* VFT)
{
	if ((qual < 1) || (qual > 3)) return -1;

	printf("\nseletor(%d) Chama funcao_%d()\n", qual, qual);
	(*VFT[qual])(qual * 100, qual * 100);	// chama a funcao pelo numero
	return 0;
};

Essa é a linha chave para entender:

    (*VFT[qual])(qual * 100, qual * 100);    // chama a funcao pelo numero

Você deve imaginar como isso é útil...

 

10 horas atrás, Reberth Siqueira disse:

Enfim, também consegui chegar nos números deslocamentos que você chegou. Tá muito confuso pra mim esse exercicio

 

Você deu azar. Até a fórmula está com a formatação zoada. Se estivesse ok você teria resolvido antes eu acho. Era só acreditar na fórmula que não dá pra ler e duvidar da resposta legível. F%$a.

 

:) Até

 

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...