'***************************************************************************************** 'Include "_FuncionesListas.bas" 'Funciones para trabajar con listas 'By COS: 01/2023, 04/2019, 08/13, 12/11 'Basic Pic18 Basic Compiler IDE v4.34 (PSI). '***************************************************************************************** 'Funciones para trabajar con listas (vector de cadenas): '----------------------------------------------------------------------------------------- '_vstradd, _vstrcpy, _vstrlen, _vstrcmp, _vstrcmp2, _vstrdreg, '_vstrsub, _vstrclr, _vstrFormat(), _VstrLong(), _VstrFree(), '_VstrFormat(), _VstrWrite_Eeprom(), _VstrRead_Eeprom(). '----------------------------------------------------------------------------------------- '_vstradd: Suma una cadena a la lista. '_vstrcpy: Copia una cadena determinada contenida en una lista a una cadena. '_vstrlen: Indica el número de cadenas que compone la lista. '_vstrcmp: Busca una cadena dentro de la lista e indica su número de orden. '_vstrcmp2: Busca una cadena dentro de la lista e indica la dirección del primer elemento. '_vstrdreg: Devuelve la dirección del primer elemento de la cadena indicada de la lista. '_vstrsub: Borra la cadena indicada de una lista. '_vstrclr: Borra una lista o lista vacía. '_vstrFormat: Inicializa la lista. '_VstrLong: Devuelve la longitud del vector lista. '_Vstrfree: Devuelve las posiciones libres de la lista. '_vstrFormat_Eeprom: Inicializa vector de cadenas o lista en la eeprom. '_VstrWrite_Eeprom: Pasa una lista en ram a Eeprom. '_VstrRead_Eeprom: Pasa una lista de la Eeprom a ram. '***************************************************************************************** 'Suma una cadena a un vector de cadenas. 'Hay que tener en cuenta que la suma (realmente concatenación) de la cadena al vector, 'es un vector de cadenas que contiene ambas cadenas con sus respectivos caracteres 'de fin de cadena. El vector de cadena tiene en su ultimo elemento el 1 marcador 'de fin de vector, y la ultima cadena introducida en el vector termina en 0 seguida de 1 'como marcador de fin de vector de vectores. 'Devuelve _vstradd = 0 todo correcto, _vstradd = 1 cadena añadir esta vacía o cadena muy larga. '_direccion1 = vector de cadenas o lista, _direccion2 = cadena a añadir Function _VStrAdd(_direccion1 As Word, _direccion2 As Word) As Byte Dim _direccion1aux As Word Dim _direccion2aux As Word Dim _char As Byte Dim _charaux As Byte Dim _x As Bit _direccion1aux = _direccion1 _VStrAdd = 1 'Hay error _x = True _char = Pointer(_direccion2) 'Se extrae el primer elemento de la cadena If _char = 0 Then Exit 'Si la cadena a añadir está vacía se sale con error While _x = True 'Localiza fin de la última cadena _char = Pointer(_direccion1aux) 'Lee caracter _direccion2aux = _direccion1aux 'Para vector vacío o cadena vacía _direccion1aux = _direccion1aux + 1 'Incrementa la posición en el vector _charaux = Pointer(_direccion1aux) 'Lee el siguiente caracter If _char = 1 Or _charaux = 1 Then Exit 'Vector lleno, se sale con error If _char = 0 Then If _direccion2aux = _direccion1 Then _direccion1aux = _direccion1 'Cadena vacía If _charaux = 0 Then _x = False 'No hay más cadenas o vector vacío Endif Wend 'Asigna la segunda cadena _x = True While _x = True _char = Pointer(_direccion2) 'Lee valor Pointer(_direccion1aux) = _char 'Asigna valor _direccion1aux = _direccion1aux + 1 'Dirección proximo caracter de la lista _direccion2 = _direccion2 + 1 'Dirección proximo caracter de la cadena If _char = 0 Then _VStrAdd = 0 'No hay errrores Exit '_x = False 'Marca salir del bucle porque se llego al final Endif 'Comprueba fin de lista _char = Pointer(_direccion1aux) If _char = 1 Then _direccion1aux = _direccion1aux - 1 Pointer(_direccion1aux) = 0 _VStrAdd = 1 'Se marca error Exit Endif Wend End Function '***************************************************************** 'Hace una copia de una cadena contenida en la lista (direccion2) en la primera (direccion1). 'La cadena a copiar se selecciona mediante _index, la primera es la 0. '_vstrcpy = 0 no hay errores. '_vstrcpy = 1 si hay errores por vector vacío o cadena solicitada fuera de rango. Function _VStrCpy(_direccion1 As Word, _direccion2 As Word, _index As Byte) As Byte Dim _char As Byte Dim _cont As Byte 'Numero de orden de las cadenas de la lista Dim _x As Bit _cont = 0 _VStrCpy = 1 'Hay error _x = 1 _char = Pointer(_direccion2) 'Se extrae el primer elemento de la lista While _x = 1 'Bucle infinito If _index = _cont Then 'Cadena en el vector encontrada Pointer(_direccion1) = _char 'Se copia caracter _direccion1 = _direccion1 + 1 'Se apunta al siguiente elemento _VStrCpy = 0 'Se marca OK If _char = 0 Then Exit Endif If _char = 0 And _index <> _cont Then _cont = _cont + 1 'No es esta la cadena y se sigue _direccion2 = _direccion2 + 1 'Siguiente elemento de la lista _char = Pointer(_direccion2) 'Se copia caracter If _char = 1 Then Exit 'Fin de la lista, se sale Wend End Function '********************************************************************************* 'Indica la cantidad de cadenas que contiene un vector de cadenas '_vstrlen = 0 no hay cadenas, _vstrlen = 1 hay una sola cadena. Function _VStrLen(_direccion As Word) As Byte Dim _char As Byte Dim _char1 As Byte Dim _cont As Byte 'Numero de orden de las cadenas de la lista Dim _flag As Byte Dim _x As Bit _cont = 0 _flag = 0 _VStrLen = 0 'Vector vacío _x = 1 While _x = 1 'Bucle infinito _char = Pointer(_direccion) 'Lee primer elemento del vector If _char = 0 And _flag = 0 Then Exit 'Si vector vacío, se sale. _flag = 1 'Hay cadenas If _char = 0 Then If _char1 = 0 Then Exit 'Si dos lecturas consecutivas de fin de cadena, se sale _cont = _cont + 1 'Lleva el número de cadenas _VStrLen = _cont 'Devuelve el número de cadenas Endif If _char = 1 Then Exit 'Fin de la lista _direccion = _direccion + 1 'Se apunta al siguiente elemento de la lista _char1 = _char 'Se utiliza para detectar fin de cadenas en el vector Wend End Function '********************************************************************* 'Devuelve el numero de orden de la cadena. 'Busca una cadena completa dentro de un vector de cadenas, devuelve _vstrcmp=0 no existe, 'devuelve _vstrcmp=numero de orden de la cadena en la lista +1. 'Devuelve _vstrcmp=1 si la cadena y la lista están vacías. 'Se le suministra vector de cadenas (_direccion1) y cadena a buscar (_direccion2). Function _VStrCmp(_direccion1 As Word, _direccion2 As Word) As Byte Dim _char1 As Byte Dim _char11 As Byte Dim _char2 As Byte Dim _direccion11 As Word Dim _direccion2img As Word Dim _nstr As Byte Dim _flag As Byte Dim _paso As Byte Dim _x As Bit _paso = 0 _nstr = 0 _direccion2img = _direccion2 _VStrCmp = 0 _flag = 0 _x = True While _x = True _direccion11 = _direccion1 + 1 'Incrementa la posición, control fin de lista _char1 = Pointer(_direccion1) 'Asigna el valor de la posición _char11 = Pointer(_direccion11) 'Asigna el valor de la posición _char2 = Pointer(_direccion2img) 'Asigna el valor de la posición 'Lista vacía y cadena vacía If _char1 = 0 And _char2 = 0 And _paso = 0 Then _VStrCmp = 1 Exit Endif 'Cadena vacía If _char1 > 0 And _char2 = 0 And _paso = 0 Then _VStrCmp = 0 Exit Endif 'Lista Vacía If _char1 = 0 And _char2 > 0 And _paso = 0 Then _VStrCmp = 0 Exit Endif 'Los caracteres son diferentes, se marca False y se activa _flag=1 If _char1 <> _char2 And _flag = 0 Then _VStrCmp = 0 _flag = 1 Endif 'Si los caracteres son iguales y estamos a principio de cadena _flag=0 If _char1 = _char2 And _flag = 0 Then If _char2 = 0 Then _nstr = _nstr + 1 'Se encontro cadena nueva, se incrementa cadenas comparadas _VStrCmp = _nstr 'Se asigna numero de cadenas al registro de salida de la funcion If _char2 = 0 Then Exit 'Todos los caracteres son iguales, se sale de la funcion Endif 'Deseña los caracteres de la cadena erronea y busca el principio de la siguiente If _char1 = 0 And _flag = 1 Then _flag = 0 'Se encontró el principio de otra cadena _nstr = _nstr + 1 'Se incrementa el contador de cadenas comparadas _direccion2img = _direccion2 - 1 'Se vuelve al principo de la cadena -1 a comparar If _char11 = 0 Or _char11 = 1 Then Exit 'Se encontrol fin de lista y se sale Endif _direccion1 = _direccion1 + 1 'Siguiente elemento de la lista _direccion2img = _direccion2img + 1 'Siguiente elemento de la cadena _paso = 1 Wend End Function '********************************************************************* 'Devuelve la dirección de la cadean. 'Busca una cadena completa dentro de un vector de cadenas, devuelve _vstrcmp=0 no existe, 'devuelve _vstrcmp = direccion del primer elemento de la cadena en la lista. 'Devuelve _vstrcmp = direccion principio de lista si la cadena y la lista están vacías. 'Se le suministra vector de cadenas (_direccion1) y cadena a buscar (_direccion2). Function _VStrCmp2(_direccion1 As Word, _direccion2 As Word) As Word Dim _char1 As Byte Dim _char11 As Byte Dim _char2 As Byte Dim _direccion11 As Word Dim _direccion2img As Word Dim _flag As Byte Dim _paso As Byte Dim _x As Bit _paso = 0 _direccion2img = _direccion2 _VStrCmp2 = _direccion1 _flag = 0 _x = True While _x = True _direccion11 = _direccion1 + 1 'Incrementa la posición, control fin de lista _char1 = Pointer(_direccion1) 'Asigna el valor de la posición _char11 = Pointer(_direccion11) 'Asigna el valor de la posición _char2 = Pointer(_direccion2img) 'Asigna el valor de la posición 'Lista vacía y cadena vacía If _char1 = 0 And _char2 = 0 And _paso = 0 Then _VStrCmp2 = _direccion1 'Asigna principio de la cadena Exit Endif 'Cadena vacía If _char1 > 0 And _char2 = 0 And _paso = 0 Then _VStrCmp2 = 0 Exit Endif 'Lista Vacía If _char1 = 0 And _char2 > 0 And _paso = 0 Then _VStrCmp2 = 0 Exit Endif 'Los caracteres son diferentes, se marca False y se activa _flag=1 If _char1 <> _char2 And _flag = 0 Then _VStrCmp2 = 0 _flag = 1 Endif 'Si los caracteres son iguales y estamos a principio de cadena _flag=0 If _char1 = _char2 And _flag = 0 Then If _char2 = 0 Then Exit 'Todos los caracteres son iguales, se sale de la funcion Endif 'Deseña los caracteres de la cadena erronea y busca el principio de la siguiente If _char1 = 0 And _flag = 1 Then _flag = 0 'Se encontró el principio de otra cadena If _char11 > 1 Then _VStrCmp2 = _direccion1 + 1 'Asigna principio de la posible cadena _direccion2img = _direccion2 - 1 'Se vuelve al principo de la cadena -1 a comparar If _char11 = 0 Or _char11 = 1 Then Exit 'Se encontrol fin de lista y se sale Endif _direccion1 = _direccion1 + 1 'Siguiente elemento de la lista _direccion2img = _direccion2img + 1 'Siguiente elemento de la cadena _paso = 1 'Marca se completo por primera vez la función Wend End Function 'Dentro de una lista devuelve la dirección del primer elemento de la cadena indicada. 'Primera cadena = 0. Devuelve _vstrdreg = 0 si la lista está vacía o la cadena está fuera de rango. Function _VStrDreg(_direccion As Word, _ncadena As Byte) As Word Dim _direccion1img As Word Dim _char As Byte Dim _char1 As Byte Dim _cont As Byte Dim _x As Byte _cont = 0 _x = 0 While _x = 0 'Bucle infinito para recorrer el vector _char = Pointer(_direccion) 'Almacena el valor de la posición de memoria _direccion = _direccion + 1 'Apunta al siguiente elemento del vector _char1 = Pointer(_direccion) 'Almacena el valor de la posición de memoria If _char = 0 And _char1 = 0 Then _VStrDreg = 0 'No hay cadena If _char = 0 And _char1 = 0 Then Exit 'Marca errror If _char = 0 And _char1 = 1 Then _VStrDreg = 0 'Fin de lista If _char = 0 And _char1 = 1 Then Exit 'Marca error If _char = 0 And _ncadena > 0 Then _cont = _cont + 1 'Si no es la primera cadena incremento If _char = 0 Then _VStrDreg = _direccion 'Retorna la direccion siguiente a fin de cadena If _ncadena = 0 Then _VStrDreg = _direccion - 1 'Primera cadena, vuelve a dirección original If _char = 1 Then _VStrDreg = 0 'Fin de lista se marca error If _cont = _ncadena Or _char = 1 Then Exit 'Se sale por fin de operación o fin de lista Wend End Function '********************************************************************* 'Borra una cadena determinada de un vector de cadenas. 'Dirección de memoria de inicio de la cadena a eliminar. 'Reformatea la lista. '_vstrsub devuelve 1 si la direccion indica cadena vacía o fin de lista. Function _VStrSub(_direccion As Word) As Byte Dim _direccion2 As Word Dim _char As Byte Dim _x As Bit _VStrSub = 0 'No hay errores _x = True _direccion2 = _direccion 'Direccion desde donde hay que mover el vector _char = Pointer(_direccion) 'Se extrae el primer elemento de la lista 'Si el elemento indica posición vacía o final se sale y se marca error If _char = 0 Or _char = 1 Then _VStrSub = 1 Exit Endif While _x = True 'Localiza final de la cadena+1 a borrar _char = Pointer(_direccion2) 'Extrae digitos de la cadena a borrar If _char = 0 Or _char = 1 Then _x = False 'Localiza final de la cadena a borrar If _char <> 1 Then _direccion2 = _direccion2 + 1 'Suma uno al final de cadena Wend _x = True While _x = True 'Bucle, desplazamiento hacia la izquierda del vector _char = Pointer(_direccion2) '_char = valor del contenido de la direccion If _char = 1 And _direccion >= _direccion2 Then _x = False 'Exit, fin vector If _x = 1 Then 'Permite salir del bucle sin variaciones Pointer(_direccion) = _char 'Asigna los nuevos valores If _char = 1 Then Pointer(_direccion) = 0 _direccion = _direccion + 1 'Incrementa puntero If _char <> 1 Then _direccion2 = _direccion2 + 1 'Incrementa puntero Endif Wend End Function 'Borra todas los elementos de la lista apartir de la dirección dada. 'Necesita la direccion del primer elemento del vector. Proc _VStrClr(_direccion As Word) Dim _char As Byte Dim _x As Byte _x = 0 While _x = 0 'Bucle infinito para recorrer el vector _char = Pointer(_direccion) 'Elemento del vector If _char = 1 Then Exit 'Si fin de vector se sale Pointer(_direccion) = 0x00 'Elementos del vector a cero _direccion = _direccion + 1 'Indice, dirección del proximo elemento Wend End Proc 'Inicializa vector de cadenas 'Rellena con ceros y el último elemento del vector con el valor 1 '_direccion = primer elemento del vector '_len = longitud del vector Proc _VStrFormat(_direccion As Word, _len As Byte) Dim _x As Byte If _len > 0 Then _len = _len - 1 'El primer elemento de los vectores es el cero For _x = 0 To _len 'Recorre el vector para su inicialización Pointer(_direccion) = 0x00 'Elementos del vector a cero _direccion = _direccion + 1 'Indice, direccion de los elementos Next _x _direccion = _direccion - 1 'Señala el último elemento del vector Pointer(_direccion) = 0x01 'Se marca fin de vector End Proc 'Devuelve la longitud del vector de vectores -1. '_direccion = primer elemento del vector Function _VStrLong(_direccion As Word) As Byte Dim _x As Byte Dim _chart As Byte _VStrLong = 1 _chart = Pointer(_direccion) 'Elemento del vector While _x = _x 'Recorre el vector. _direccion = _direccion + 1 'Indice, direccion de los elementos _chart = Pointer(_direccion) 'Elemento del vector If _chart = 1 Then Exit 'Fin de vector, se sale. _VStrLong = _VStrLong + 1 'Cuenta los caracteres Wend End Function 'Devuelve las posiciones libres que quedan en la lista. '_direccion = primer elemento del vector 'Descuenta el caracter de fin de lista 'Recordar descontar el caracter de fin de cadena Function _VStrFree(_direccion As Word) As Byte Dim _chart As Byte Dim _aux As Byte 'Calcula el numero de vectores que tiene la lista _aux = _VStrLen(_direccion) 'Si la lista esta vacia If _aux = 0 Then _VStrFree = _VStrLong(_direccion) Exit Endif 'Si la lista tiene vectores adelanta el puntero al ultimo elemento + 1 _aux = _aux - 1 'Se adapta el numero de vectores, el primer vector es el cero _direccion = _VStrDreg(_direccion, _aux) 'Devuelve la direccion del ultimo vector _chart = Pointer(_direccion) 'Elemento del vector While _chart <> 0 'Recorre el vector hasta llegar a su final _direccion = _direccion + 1 'Incrementa la posición del elemento del vector _chart = Pointer(_direccion) 'Lee el valor del elemento al que se apunta Wend _direccion = _direccion + 1 'Incrementa a fin de lista 'Calcula el numero de elementos libres que quedan en la lista _VStrFree = _VStrLong(_direccion) End Function '************************************************