Cómo crear un array vacío en C (sin estructuras)

Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   -  
mamiemando Mensajes publicados 33228 Fecha de registro   Estado Moderador Última intervención   -

Hola

Quiero crear una función que me devuelva un array que no contenga ningún elemento sin utilizar struct array. Pero no sé cómo hacerlo.

¿Cómo puedo hacerlo, por favor?

18 respuestas

  1. mamiemando Mensajes publicados 33228 Fecha de registro   Estado Moderador Última intervención   7 940
     

    Hola,

    Si code_char.code fuera un int *, una forma de salir del paso sería representar el array vacío como NULL. Luego, cuando necesites acceder a code_char.code, primero verificas si esta dirección no es NULL. Si lo es y quieres corregir el valor de code_char.code, solo tienes que hacer una asignación dinámica.

    En tu caso, el hecho de que code_char sea un int[256] significa que, pase lo que pase, este array es un bloque de memoria y su tamaño real es 256*sizeof(int). Si quieres una noción de tamaño efectivo, por lo tanto, debes almacenarla por separado. En tu código, ese es el rol de code_char.lg: como este valor almacena el tamaño efectivo de code_char.code, ¿por qué no simplemente ponerlo a 0 en el caso de que el código corresponda a la cadena vacía? Porque, en realidad, independientemente de la longitud efectiva de code_char.code, dado que se trata de un int[256], en memoria siempre generará un array de 256 ints.

    Con respecto a la pregunta inicial, como dice Pierrot, en sus mensajes #18, no hay noción de array vacío en C a diferencia de C++ o Python. Voy a ir un paso más allá, en realidad no hay una noción de array nativa en el lenguaje C (a menos que definas tu propia estructura). Solo hay una noción de bloque de memoria. El álgebra de punteros hace que podamos indexar un bloque conforme al tamaño del tipo apuntado, y eso es lo que define al operador [ ]. Porque en realidad:

    tab[i] == *(tab + i)

    ... donde tab corresponde a la dirección del bloque. El desplazamiento de i "casillas" depende del tipo apuntado. Por ejemplo, si tab es de tipo int *, entonces el tipo apuntado es int, y por lo tanto la i-ésima "casilla" está i * sizeof(int) bytes después de la dirección tab, como ilustra el siguiente programa:

    #include <stdio.h> #include <stdlib.h> int main() { int * tab = malloc(10 * sizeof(int)); size_t i = 1; printf("tab = %p i = %zu\n", tab, i); printf("tab[i] = %p\n", &tab[i]); printf("tab + i = %p\n", tab + i); printf("((int) tab) + i * sizeof(int) = %p\n", ((long) tab) + i * sizeof(int)); free(tab); return 0; }
     (mando@silk) (~) $ gcc toto.c && ./a.out tab = 0x55de759dc2a0 i = 1 tab[i] = 0x55de759dc2a4 tab + i = 0x55de759dc2a4 ((int) tab) + i * sizeof(int) = 0x55de759dc2a4

    Por lo tanto, entendemos que el operador [ ] es simplemente una forma de escritura que juega con los punteros en el fondo, y que no hay una noción de array en sentido estricto.

    Buena suerte

    1
  2. PierrotLeFou
     

    ¿Podrías explicar qué quieres hacer con eso? Porque no veo la utilidad a priori.
    Y "vacío" significa que su longitud es 0, o que no quieres poner nada desde el principio?

    Es posible hacer int tab[0];, pero no es ISO.

    0
  3. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    Sí, quiero que su tamaño sea igual a 0.

    Nada al partir, exacto.

    0
  4. PierrotLeFou
     

    ¿Cómo vas a añadir elementos?
    No es como Python donde se pueden hacer append, o como C++ donde se puede hacer push_back.

    Acabo de probar, se pueden hacer malloc de longitud 0, aunque luego se haga realloc.

    Pero es más que dudoso como manera de hacerlo...

    0
  5. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    Voy a explicarles el contexto, si no, no van a entender. Debo hacer un ejercicio sobre los árboles de Huffman (no sé si lo conocen)

    Me han pedido que escriba una función que me permita obtener el código de cada carácter y su longitud

    Ejemplo:

    La codificación será:

    • C: 000
    • B: 001
    • D: 1100
    • ...

    Tengo una función ConstruirCodigo cuyo prototipo es:

    void ConstruirCodigo(Arbol huff) { } typedef unsigned char Elemento; struct celda { Elemento etiq; struct celda *fd; struct celda *fg; }; typedef struct celda *Arbol; struct codigo_car { int lg; int codigo[256]; /* solo contiene 0 o 1 */ }; struct codigo_car tab;
    • tab[i] contiene el código del carácter del código ASCII i
    • tab[i].lg contiene la longitud del código (ejemplo para B: código de longitud 3)
    • tab[i].codigo contiene el código del carácter (como en mi ejemplo B=001)

    ¿Por qué hice la pregunta del arreglo vacío?

    Para calcular el código de una letra, necesitamos recorrer desde la raíz hasta la hoja. El lado izquierdo del árbol solo tiene 0 y el lado derecho solo tiene 1.

    Quiero escribir la función recursivamente, así que necesito un caso base, lo que da más o menos esto:

    void ConstruirCodigo(Arbol huff) { if Eshoja(huff) tab[i].codigo=crear_un_arreglo_vacío else //ConstruirCodigo(Filhoizquierdo(huff)) //ConstruirCodigo(Filhoderecho(huff)) }

    En mi solución, aún no he encontrado la manera de poner solo 0 a la izquierda y solo 1 a la derecha.

    Así que necesito crear un arreglo vacío para tratar mi caso base.

    Si un árbol se reduce a una hoja (1 nodo), no debe tener código, por lo tanto, necesito un arreglo vacío para indicar simplemente que no hay nada.

    0
  6. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    Ejemplo en Python:

    from __future__ import annotations from typing import Dict from heapq import heappush, heappop class Nodo(): """ Nodo del árbol de Huffman. """ def __init__(self: Nodo, valor: int, letra: str = "", hijoG: Nodo = None, hijoD: Nodo = None) -> None: self.valor = valor self.letra = letra self.hijoG = hijoG self.hijoD = hijoD def __lt__(self, n: Nodo): """ Comparación de dos nodos = comparación de los valores """ return self.valor < n.valor def crear_codigos_huffman(a: Nodo) -> Dict[str, str]: """ Dado un árbol de Huffman devuelve un diccionario en el que las claves son las cadenas binarias y los valores los caracteres correspondientes. Función envolvente de la función codigos_huffman_recorrido. """ dic = {} codigos_huffman_recorrido(a, dic, "") return dic def codigos_huffman_recorrido(a: Nodo, dic: Dict[str, str], codigo: str) -> None: if es_hoja(a): dic[codigo] = a.letra else: codigos_huffman_recorrido(a.hijoG, dic, codigo + "0") codigos_huffman_recorrido(a.hijoD, dic, codigo + "1")

    En esta versión de Python, nada está simbolizado por "". En la versión C, la estructura que me dieron, la estructura codigo_caracter contiene un arreglo codigo con el código del carácter. Entonces, por analogía, creo que necesito en lugar de un arreglo vacío.

    0
  7. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    En la versión de Python, nada está simbolizado por " " y yo, dado la estructura que me han dado, código-caracter, contiene un arreglo código con el código del carácter, así que por analogía aquí debo tener, pienso, un arreglo vacío.

    0
  8. PierrotLeFou
     

    Ya he hecho un Huffman. Hice una tabla de frecuencias de 256 de largo.
    Cada elemento era un nodo y acumulaba la frecuencia.

    Sólo mantenía los elementos con una frecuencia no nula y los ordenaba en orden descendente.
    Creo que construía el árbol de manera iterativa, pero supongo que también se puede hacer de forma recursiva.
    Me parece que construía una tabla de códigos con la longitud de cada uno, esta vez de forma recursiva.

    0
  9. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    Sí, eso es, mi ejercicio me pide que haga la tabla de códigos

    Ejemplo:

    Huffman[97] = a ​​​​​​​Huffman[97].code = [0011] Huffman[97].lg = 4
    0
  10. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    Entonces, ¿es buena o no mi idea de crear un array vacío?

    Si es así, ¿cómo se crea en C?

    Si lees la versión en Python (consulta #6) entenderás lo que quiero hacer.

    0
  11. PierrotLeFou
     

    Como te dije, he creado mi tabla de códigos a partir de la tabla de frecuencias. Esta tabla estaba formada por nodos.
    Así que, al final, me encontraba con un árbol binario con una raíz.
    Es a partir de este punto, según yo, que vas a crear tu tabla de códigos de forma recursiva.
    Siempre puedo publicar mi código.
    Pero no estará en color porque soy ciego y uso mi ordenador con un sintetizador de voz.
    No me da acceso a la barra de opciones.

    Para responder a tu pregunta, no es una buena idea empezar con una tabla vacía.

    0
  12. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    No sé si funcionará para el mío, pero en cualquier caso, yo también tengo una tabla de frecuencias.

    Por ejemplo, si tengo: bal alh

    tab[97] = 2 // a tab[98] = 1 // b ...

    También tengo una función init_huffman que me devuelve una cola de prioridad cuyos elementos son nodos con como prioridad su frecuencia. ¿Creen que se parece a su tabla de frecuencias?

    Pero tengo curiosidad, me gustaría ver su código.

    0
  13. PierrotLeFou
     

    Aquí está mi código:

    // Árbol de Huffman. #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Node Nodo; struct Node {     Nodo *izquierda;     Nodo *derecha;     int ocurrencias;     char codigo; }; typedef struct Bits Bits; struct Bits {     unsigned char numero;     unsigned char bits; }; void *obtenerArea(char *nombre, int tamaño) {     void *area = malloc(tamaño);     if(area) return area;     perror(nombre);     printf("Requerido: %d\n", tamaño);     exit(EXIT_FAILURE); } Nodo *obtenerNodo(char simbolo) {     Nodo *nodo = obtenerArea("obtenerNodo", sizeof(Nodo));     nodo->izquierda = NULL;     nodo->derecha = NULL;     nodo->ocurrencias = 0;     nodo->codigo = simbolo;     return nodo; } void establecerArbol(Nodo *nodo, Bits convertir[], Bits bits, int nivel) {     if(nodo->izquierda) {   // no es una hoja     bits.numero++;     establecerArbol(nodo->derecha, convertir, bits, nivel+1);     bits.bits |= 1<<nivel;     establecerArbol(nodo->izquierda, convertir, bits, nivel+1); } else {     convertir[nodo->codigo] = bits; } } int comparar(const void *frecuencia1, const void *frecuencia2) {     int cmp =(*((Nodo **)frecuencia2))->ocurrencias - (*((Nodo **)frecuencia1))->ocurrencias;     if(cmp != 0) return cmp;     return ( *((Nodo **)frecuencia1))->codigo - (*((Nodo **)frecuencia2))->codigo; } void liberarArbol(Nodo *nodo) {     if(nodo->izquierda) liberarArbol(nodo->izquierda);     if(nodo->derecha) liberarArbol(nodo->derecha);     free(nodo); } int main(void) {     Nodo **frecuencia = obtenerArea("frecuencia", sizeof(Nodo *) * 256);     unsigned char texto[] = "este es un ejemplo de un árbol de huffman";     for(int i=0; i < 256; i++) frecuencia[i] = NULL;     // Aumentar las ocurrencias.     for(int i=0; texto[i]; i++) {         char codigo = texto[i];         if(frecuencia[codigo] == NULL) frecuencia[codigo] = obtenerNodo(codigo);         frecuencia[codigo]->ocurrencias++;     }     // Mantener solo si hay al menos una ocurrencia.     int conteo = 0;     for(int i=0; i < 256; i++)         if(frecuencia[i])             frecuencia[conteo++] = frecuencia[i];     // Ordenar las frecuencias en orden descendente.     qsort(frecuencia, conteo, sizeof(Nodo **), comparar);     // Construir el árbol a partir de los nodos.     Nodo *nuevoNodo;     int resto = conteo;     while(resto > 1) {         nuevoNodo = obtenerNodo('\0');         nuevoNodo->izquierda = frecuencia[resto-2];         nuevoNodo->derecha = frecuencia[resto-1];         nuevoNodo->ocurrencias = frecuencia[resto-2]->ocurrencias + frecuencia[resto-1]->ocurrencias;         resto -= 2;         // Subir el nodo en el array         int i;         for(i=resto; i>0 && nuevoNodo->ocurrencias > frecuencia[i-1]->ocurrencias; i--) frecuencia[i] = frecuencia[i-1];         frecuencia[i] = nuevoNodo;         resto++;     }     free(frecuencia);     Bits *convertir = obtenerArea("convertir", sizeof(Bits) * 256);     Bits bits;     bits.numero=0;     bits.bits=0;     for(int i=0; i<256; i++) convertir[i] = bits;     establecerArbol(nuevoNodo, convertir, bits, 0);     unsigned char *memoria = obtenerArea("memoria", strlen(texto)*8);   // === revisar     int en =  0;     // recorrer el texto y convertirlo     for(int i=0; texto[i]; i++) {         char codigo =texto[i];         for(int s=0; s < convertir[codigo].numero; s++) {             memoria[en++] = (convertir[codigo].bits >> s) & 1;         }     }     free(convertir);     // decodificar el archivo     printf("%d bits\n", en);     int salida = 0;     int acc = 0;     Nodo *nodo = nuevoNodo;     while(salida < en) {         if(nodo->izquierda == NULL) {             memoria[acc++] = nodo->codigo;             nodo = nuevoNodo;         }         if(memoria[salida++])         nodo = nodo->izquierda;         else         nodo = nodo->derecha;     }     memoria[acc++]=nodo->codigo;     memoria[acc]='\0';     // mostrar el resultado     printf("\n%s\n", memoria);     free(memoria);     liberarArbol(nuevoNodo);     return 0; }
    0
  14. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    He leído todo, pero no veo a partir de qué momento calculan el código de los caracteres.

    0
  15. PierrotLeFou
     

    Lo hago en la función setTree con el array convert. La función setTree es recursiva.

    0
  16. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    De acuerdo, gracias. He mirado, creo que es muy diferente de la firma de mis funciones y de mis estructuras, pero gracias.

    Volvamos a mi problema inicial. Solo quiero saber cómo crear un array vacío.

    Ejemplo:

    struct array{    int *arr;    int size; } void crear_array_vacio(){    array a; a.size = 0; }

    ¿Cómo hacer sin usar struct array??

    0
  17. PierrotLeFou
     

    Lo que quieres hacer sin estructura es imposible en C. En C++, usaría los std::vector
    y sabes cómo hacerlo en Python.
    En tu ejemplo, no devuelves la estructura a la función que llama.

    0
  18. Theo_0055 Mensajes publicados 273 Fecha de registro   Estado Miembro Última intervención   1
     

    de acuerdo, entiendo mejor, gracias

    0