lunes, julio 26, 2021

Vector genérico en C

Deberías leer

Antonio García Pratshttp://antoniogarciaprats.eu/
Estudios de Licenciatura en CC Quimicas e Ingeniería Técnica en Informática de Gestión por la Universidad de Jaén. Social Media autodidacta. Siempre en búsqueda de nuevos retos que proporcionen algún sentido a mi existencia.

Vamos a desarrollar, en éste artículo, una estructura lineal que nos servirá como auxiliar para otras estructuras más complejas. Podéis descargarla de mi repositorio personal de github.

Cabeceras de las funciones y procedimientos

#ifndef ARDI_CHAR_TYPO
#define ARDI_CHAR_TYPO
struct ardi_char_typo  {
	char x;
   };
typedef struct ardi_char_rep *ardi_char;
//  ---------------------------------------------------------------------
ardi_char ardi_char_nuev (void);
ardi_char ardi_char_const (int tamano, struct ardi_char_typo valorinicial);
ardi_char ardi_char_copy (ardi_char a, int prim, int count);
int ardi_char_tamfis (ardi_char a);
int ardi_char_tamlog (ardi_char a);
int ardi_char_infe (ardi_char a);
int ardi_char_supe (ardi_char a);
void ardi_char_obti (ardi_char a, int i, struct ardi_char_typo *e);
void ardi_char_asig (ardi_char a, int i, struct ardi_char_typo e);
void ardi_char_aumd (ardi_char a, struct ardi_char_typo e);
void ardi_char_disd (ardi_char a, struct ardi_char_typo *e);
void ardi_char_dest (ardi_char *a);
void ardi_char_swap (ardi_char a, int l, int r);
int ardi_char_bbin (ardi_char a, struct ardi_char_typo e,
	int (*cmp_char) (const void *, const void *));
int ardi_char_bsecd (ardi_char a, struct ardi_char_typo e,
	int (*cmp_char) (const void *, const void *));
int ardi_char_bseci (ardi_char a, struct ardi_char_typo e,
	int (*cmp_char) (const void *, const void *));
void ardi_char_qsort (ardi_char a, int (*cmp_char) (const void *, const void *));
#endif

Implementación en C

#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#include <math.h>
#include "arrdina.h"
struct ardi_char_rep   {
	int tamfis;
	int tamlog;
	struct ardi_char_typo *arr;
   };
//  ---------------------------------------------------------------------
//               	FUNCIONES PRIVADAS
//  ---------------------------------------------------------------------
void ardi_char_error (int error, char prim [20])     {
	switch (error)    {
		case 1: fprintf (stderr, "\n\t%s: Error, no hay memoria suficiente.\n", prim);
			break;
		case 2: fprintf (stderr, "\n\t%s: Error, el array no existe.\n", prim);
			break;
		case 3:	fprintf (stderr, "\n\t%s: Error, el array esta vacio.\n", prim);
			break;
		case 4:	fprintf (stderr, "\n\t%s: Error, tama¤o < 1.\n", prim);
			break;
		case 5:	fprintf (stderr, "\n\t%s: Error, prim < 0.\n", prim);
			break;
		case 6:	fprintf (stderr, "\n\t%s: Error, count > elementos del array.\n", prim);
			break;
		case 7:	fprintf (stderr, "\n\t%s: Error, fuera de rango del array.\n", prim);
			break;
	  }
    }
//  ---------------------------------------------------------------------
struct ardi_char_typo *ardi_char_aloarr (int tamano)   {
	struct ardi_char_typo *arr;
	if (tamano == 0) return (NULL);
	else   {
		arr = (struct ardi_char_typo *) malloc (sizeof (struct ardi_char_typo) * tamano);
		if (arr == NULL)   {
		     ardi_char_error (1, "ardi_char_aloarr");
		     exit (1);
		   }
		return (arr);
	  }
   }
//   -------------------------------------------------------------------
ardi_char ardi_char_alo (int tamano)    {
	ardi_char p;
	p = (ardi_char) malloc (sizeof (struct ardi_char_rep));
	if (p == NULL)   {
	     ardi_char_error (1, "ardi_char_alo");
	     exit (1);
	   }
	p -> arr = ardi_char_aloarr (tamano);
	p -> tamfis = tamano;
	p -> tamlog = 0;
	return (p);
   }
//   -------------------------------------------------------------------
void ardi_char_daloarr (struct ardi_char_typo *arr)   {
	if (arr)   free (arr);
   }
//   -------------------------------------------------------------------
void ardi_char_dalo (ardi_char *p)    {
	if (*p != NULL)   {
	      ardi_char_daloarr ((*p) -> arr);
	      free (*p);
	      *p = NULL;
	 }
   }
//  ---------------------------------------------------------------------
//  		               	FUNCIONES PUBLICAS
//  ---------------------------------------------------------------------
ardi_char ardi_char_nuev ()  {
	ardi_char x;
	x = ardi_char_alo (1);
	return (x);
  }
//  ---------------------------------------------------------------------
ardi_char ardi_char_const (int tamano, struct ardi_char_typo valorinicial)   {
	ardi_char x;
	int i = 0, tamfis;
	if (tamano < 1)   {
		ardi_char_error (4, "ardi_char_const");
		exit (1);
	    }
	tamfis = (int) pow (2, ceil (log (tamano) / log (2)));
	x = ardi_char_alo (tamfis);
	while (i < tamano)     *(x -> arr+i++) = valorinicial;
	x -> tamlog = tamano;
	return (x);
  }
//  ---------------------------------------------------------------------
ardi_char ardi_char_copy (ardi_char a, int prim, int count)  {
	ardi_char x;
	int tamfis;
	if (!a)   {
		ardi_char_error (2, "ardi_char_copy");
		exit (1);
	   }
	if ((prim < 0) || (prim > a -> tamlog - 1))   {
		ardi_char_error (5, "ardi_char_copy");
		exit (1);
	   }
	if (count + prim - 1 > a -> tamlog - 1)   {
		ardi_char_error (6, "ardi_char_copy");
		exit (1);
	   }
	tamfis = (int) pow (2, ceil (log (count) / log (2)));
	x = ardi_char_alo (tamfis);
	memcpy (x -> arr, a -> arr + prim, count * sizeof (struct ardi_char_typo));
	x -> tamlog = count;
	return (x);
  }
//  ---------------------------------------------------------------------
int ardi_char_tamfis (ardi_char a)  {
	if (!a)   {
		ardi_char_error (2, "ardi_char_tamfis");
		exit (1);
	   }
	return (a -> tamfis);
   }
//  ---------------------------------------------------------------------
int ardi_char_tamlog (ardi_char a)  {
	if (!a)   {
		ardi_char_error (2, "ardi_char_tamlog");
		exit (1);
	   }
	return (a -> tamlog);
   }
//  ---------------------------------------------------------------------
int ardi_char_infe (ardi_char a)   {
	if (!a)   {
		ardi_char_error (2, "ardi_char_infe");
		exit (1);
	   }
	return (0);
   }
//  ---------------------------------------------------------------------
int ardi_char_supe (ardi_char a)   {
	if (!a)   {
		ardi_char_error (2, "ardi_char_supe");
		exit (1);
	   }
	return (a -> tamlog - 1);
   }
//  ---------------------------------------------------------------------
void ardi_char_obti (ardi_char a, int i, struct ardi_char_typo *e)     {
	if (!a)   {
		ardi_char_error (2, "ardi_char_obti");
		exit (1);
	   }
	if ((i < 0) || (i > a -> tamlog - 1))   {
		ardi_char_error (7, "ardi_char_obti");
		exit (1);
	   }
	*e = a -> arr [i];
  }
//  ---------------------------------------------------------------------
void ardi_char_asig (ardi_char a, int i, struct ardi_char_typo e)    {
	if (!a)   {
		ardi_char_error (2, "ardi_char_asig");
		exit (1);
	   }
	if (i < 0 || i > a -> tamlog - 1)   {
		ardi_char_error (7, "ardi_char_asig");
		exit (1);
	   }
	a -> arr [i] = e;
   }
//  ---------------------------------------------------------------------
void ardi_char_aumd (ardi_char a, struct ardi_char_typo e)   {
	struct ardi_char_typo *b;
	if (!a)   {
		ardi_char_error (2, "ardi_char_aumd");
		exit (1);
	   }
	if (!a -> tamlog)    *(a -> arr) = e;
	else if ((a -> tamlog) < (a -> tamfis))    a -> arr [a -> tamlog] = e;
	else   {
		b = ardi_char_aloarr (a -> tamfis * 2);
		memcpy (b, a -> arr, a -> tamfis * sizeof (struct ardi_char_typo));
		b [a -> tamlog] = e;
		ardi_char_daloarr (a -> arr);
		a -> arr = b;
		a -> tamfis *= 2;
	  }
	a -> tamlog++;
   }
//  ---------------------------------------------------------------------
void ardi_char_disd (ardi_char a, struct ardi_char_typo *e)   {
	struct ardi_char_typo *b;
	if (!a)   {
		ardi_char_error (2, "ardi_char_disd");
		exit (1);
	   }
	if (!a -> tamlog)   {
		ardi_char_error (3, "ardi_char_disd");
		exit (1);
	   }
	*e = a -> arr [a -> tamlog - 1];
	a -> tamlog--;
	if (a -> tamlog < (a -> tamfis / 2))   {
		b = ardi_char_aloarr (a -> tamfis / 2);
		memcpy (b, a -> arr, (a -> tamfis / 2) * sizeof (struct ardi_char_typo));
		ardi_char_daloarr (a -> arr);
		a -> arr = b;
		a -> tamfis /= 2;
	   }
   }
//  ---------------------------------------------------------------------
void ardi_char_dest (ardi_char *a)   {
	if (!*a)   {
		ardi_char_error (2, "ardi_char_dest");
		exit (1);
	   }
	ardi_char_dalo (a);
   }
//  --------------------------------------------------------------------
void ardi_char_swap (ardi_char a, int l, int r)   {
	struct ardi_char_typo aux;
	if (!a)   {
		ardi_char_error (2, "ardi_char_swap");
		exit (1);
	   }
	if (!a -> tamlog)   {
		ardi_char_error (3, "ardi_char_swap");
		exit (1);
	   }
	if (l < 0 || l > a -> tamlog - 1 || r < 0 || r > a -> tamlog - 1)   {
		ardi_char_error (7, "ardi_char_swap");
		exit (1);
	   }
	aux = a -> arr [l];
	a -> arr [l] = a -> arr [r];
	a -> arr [r] = aux;
   }
//  ---------------------------------------------------------------------
int ardi_char_bbin (ardi_char a, struct ardi_char_typo e,
			int (*cmp_char) (const void *, const void *))   {
	struct ardi_char_typo *t;
	if (!a)   {
		ardi_char_error (2, "ardi_char_bbin");
		exit (1);
	   }
	if (!a -> tamlog)   {
		ardi_char_error (3, "ardi_char_bbin");
		exit (1);
	   }
	t = (struct ardi_char_typo *) bsearch (&e, a -> arr, a -> tamlog,
		sizeof (struct ardi_char_typo), cmp_char);
	if (!t)   return (-1);
	else   return (t - a -> arr);
   }
//  ---------------------------------------------------------------------
int ardi_char_bsecd (ardi_char a, struct ardi_char_typo e,
			int (*cmp_char) (const void *, const void *))   {
	int i;
	if (!a)   {
		ardi_char_error (2, "ardi_char_bsecd");
		exit (1);
	   }
	if (a -> tamlog)
		for (i = a -> tamlog - 1; i >= 0; i--)
		      if (!cmp_char (&(a -> arr [i]), &e))    return (i);
	return (-1);
   }
//  ---------------------------------------------------------------------
int ardi_char_bseci (ardi_char a, struct ardi_char_typo e,
			int (*cmp_char) (const void *, const void *))    {
	int i;
	if (!a)   {
		ardi_char_error (2, "ardi_char_bseci");
		exit (1);
	   }
	if (a -> tamlog)
		for (i = 0; i <= a -> tamlog - 1; i++)
		      if (!cmp_char (&(a -> arr [i]), &e))    return (i);
	return (-1);
   }
//  ---------------------------------------------------------------------
void ardi_char_qsort (ardi_char a, int (*cmp_char) (const void *, const void *))   {
	if (!a)   {
		ardi_char_error (2, "ardi_char_qsort");
		exit (1);
	   }
	if (!a -> tamlog)   {
		ardi_char_error (3, "ardi_char_qsort");
		exit (1);
	   }
	qsort (a -> arr, a -> tamlog, sizeof (struct ardi_char_typo), cmp_char);
  }

Programa de prueba

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include "arrdina.h"
//  ------------------------------------------------------------------
int cmp_char (const void *a, const void *b)   {
	return (strcmp ((char *) a, (char *) b));
    }
//  ------------------------------------------------------------------
void mostrar_linea (ardi_char array)     {
	struct ardi_char_typo e;
	int i = 0;
	while (i < ardi_char_tamlog (array))     {
	       ardi_char_obti (array, i, &e);
	       i++;
	       printf ("%c", e.x);
	   }
   }
//  ------------------------------------------------------------------
void buscar_palabra (ardi_char array, char *argv [], int linea)     {
	struct ardi_char_typo e;
	int num = 0, i = 0, j = 0;
	char cadena [20], fin;
	while (i < ardi_char_tamlog (array))     {
	       ardi_char_obti (array, i, &e);
	       i++;
	       if ((e.x != ' ') && (e.x != '\n') && (e.x != '.') &&
		   (e.x != ',') && (e.x != ':') && (e.x != ';'))    {
		      cadena [j] = e.x;
		      j++;
		  }
	       else   {
		      cadena [j] = '\0';
		      j = 0;
		      if (cmp_char (cadena, argv [2]) == 0)   num++;
		 }
	  }
	if (num)    {
		printf ("\t La palabra '%s' aparece %d veces en la linea %d, igual a:\n", argv [2], num, linea);
		mostrar_linea (array);
		printf ("\nPulse una tecla para continuar: ");
		fin = getch ();
		clrscr ();
	   }
   }
//  ------------------------------------------------------------------
void fichero_array (char *argv [])   {
	FILE *fp;
	ardi_char array;
	struct ardi_char_typo e;
	int linea = 1;
	char c;
	if ((fp = fopen (argv [1], "rt")) == NULL)    {
		fprintf (stderr, "Fichero_array: El fichero %s no existe.\n", argv [1]);
		exit (1);
	   }
	array = ardi_char_nuev ();
	while ((c = fgetc (fp)) != EOF)  {
		e.x = c;
		ardi_char_aumd (array, e);
		if (c == '\n')    {
			buscar_palabra (array, argv, linea);
			linea++;
			ardi_char_dest (&array);
			array = ardi_char_nuev ();
		   }
	   }
	ardi_char_dest (&array);
	fclose (fp);
   }
//  -------------------------------------------------------------------------
void main (int argc, char *argv [])     {
	char fin;
	if (argc != 3)	{
		fprintf (stderr, "Error: N£mero de par metros incorrecto.\n");
		fprintf (stderr, "Uso: programa <fichero> <palabra a buscar>\n");
		exit (1);
	   }
	fichero_array (argv);
	printf ("\nLa b£squeda ha finalizado.");
	printf (" Pulse una tecla para finalizar.");
	fin = getch ();
	clrscr ();
   }

Conclusión

Dejo la sección de comentarios abierto para que me dejéis vuestra opinión o códigos alternativos. También os invito a que compartais artículos de mi blog personal: ficheros disperos, bicola estática o lista genérica.

Artículo anteriorDesarrollo de una pila de enteros en C
Artículo siguienteTablas hash en C
- Advertisement -spot_img

Más publicaciones

Dejar respuesta

Please enter your comment!
Please enter your name here

- Advertisement -spot_img

Últimas publicaciones