Articulo de referencia

Cadenas de caracteres (informática)

Las cadenas de caracteres suelen estar formadas por caracteres y se utilizan a menudo para almacenar datos legibles por humanos, como palabras o frases. En programación informát...

Diagrama de datos de cadena en informática. Muestra la palabra "ejemplo", con cada letra en un recuadro separado. La palabra "Cadena" se encuentra arriba y hace referencia a la oración completa. La etiqueta "Carácter" se encuentra abajo y apunta a un recuadro individual.
Las cadenas de caracteres suelen estar formadas por caracteres y se utilizan a menudo para almacenar datos legibles por humanos, como palabras o frases.

En programación informática , una cadena es tradicionalmente una secuencia de caracteres , ya sea como una constante literal o como una variable . Esta última puede permitir la modificación de sus elementos y el cambio de longitud, o bien puede ser fija (tras su creación). Una cadena se suele implementar como una estructura de datos de matriz de bytes (o palabras ) que almacena una secuencia de elementos, normalmente caracteres, utilizando alguna codificación de caracteres . De forma más general, una cadena también puede denotar una secuencia (o lista ) de datos distintos de los caracteres.

Dependiendo del lenguaje de programación y del tipo de dato exacto utilizado, una variable declarada como cadena de caracteres puede provocar que el almacenamiento en memoria se asigne de forma estática para una longitud máxima predeterminada o bien emplear una asignación dinámica que le permita contener un número variable de elementos.

Cuando una cadena aparece literalmente en el código fuente , se la conoce como literal de cadena o cadena anónima. [ 1 ]

En los lenguajes formales , que se utilizan en la lógica matemática y la informática teórica , una cadena es una secuencia finita de símbolos que se eligen de un conjunto llamado alfabeto .

Objetivo

Una función principal de las cadenas de caracteres es almacenar texto legible para humanos, como palabras y oraciones. Se utilizan para comunicar información de un programa informático al usuario. [ 2 ] Un programa también puede aceptar cadenas de caracteres como entrada del usuario. Además, las cadenas pueden almacenar datos expresados ​​como caracteres que no están destinados a la lectura humana.

Ejemplos de cadenas de texto y sus propósitos:

  • Un mensaje como " file upload complete" es una cadena que el software muestra a los usuarios finales . En el código fuente del programa , este mensaje probablemente aparecería como una cadena literal .
  • Texto ingresado por el usuario, como " I got a new job today" como actualización de estado en un servicio de redes sociales . En lugar de una cadena literal, el software probablemente almacenaría esta cadena en una base de datos .
  • Datos alfabéticos, como " AGATGCCGT" que representan secuencias de ácidos nucleicos de ADN . [ 3 ]
  • Configuración o parámetros de la computadora, como " ?action=edit" como cadena de consulta URL . A menudo, estos están pensados ​​para ser algo legibles para los humanos, aunque su propósito principal es comunicarse con las computadoras.

El término cadena también puede designar una secuencia de datos o registros informáticos distintos de los caracteres —como una "cadena de bits " pero cuando se usa sin ninguna especificación se refiere a cadenas de caracteres. [ 4 ]

Historia

El uso de la palabra "cadena" para referirse a cualquier elemento dispuesto en una línea, serie o sucesión se remonta a siglos atrás. [ 5 ] [ 6 ] En la composición tipográfica del siglo XIX, los tipógrafos usaban el término "cadena" para denotar una longitud de tipo impreso en papel; la cadena se medía para determinar el salario del tipógrafo. [ 7 ] [ 4 ] [ 8 ]

El uso de la palabra "cadena" para referirse a "una secuencia de símbolos o elementos lingüísticos en un orden definido" surgió de las matemáticas, la lógica simbólica y la teoría lingüística para hablar del comportamiento formal de los sistemas simbólicos, dejando de lado el significado de los símbolos. [ 4 ]

Por ejemplo, el lógico CI Lewis escribió en 1918: [ 9 ]

Un sistema matemático es cualquier conjunto de secuencias de marcas reconocibles, en el que algunas de ellas se toman inicialmente y las restantes se derivan de estas mediante operaciones realizadas según reglas independientes del significado que se les asigne a las marcas. Que un sistema consista en «marcas» en lugar de sonidos u olores es irrelevante.

Según Jean E. Sammet , "el primer lenguaje realista para el manejo de cadenas y la coincidencia de patrones" para computadoras fue COMIT en la década de 1950, seguido por el lenguaje SNOBOL de principios de la década de 1960. [ 10 ]

Tipos de datos de cadena

Un tipo de dato cadena es un tipo de dato modelado a partir de la idea de una cadena formal. Las cadenas son un tipo de dato tan importante y útil que se implementan en casi todos los lenguajes de programación . En algunos lenguajes están disponibles como tipos primitivos y en otros como tipos compuestos . La sintaxis de la mayoría de los lenguajes de programación de alto nivel permite que una cadena, generalmente entrecomillada, represente una instancia de un tipo de dato cadena; dicha metacadena se denomina literal o literal de cadena .

longitud de la cuerda

Aunque las cadenas formales pueden tener una longitud finita arbitraria, en los lenguajes de programación reales la longitud de las cadenas suele estar limitada a un máximo artificial. En general, existen dos tipos de datos de cadena: cadenas de longitud fija , que tienen una longitud máxima fija que se determina en tiempo de compilación y que utilizan la misma cantidad de memoria independientemente de si se necesita este máximo o no; y cadenas de longitud variable , cuya longitud no está fijada arbitrariamente y que pueden utilizar cantidades variables de memoria según los requisitos reales en tiempo de ejecución (véase Gestión de memoria ). La mayoría de las cadenas en los lenguajes de programación modernos son de longitud variable. Por supuesto, incluso las cadenas de longitud variable están limitadas en longitud por la cantidad de memoria disponible. La longitud de la cadena se puede almacenar como un entero independiente (lo que puede imponer otro límite artificial a la longitud) o implícitamente mediante un carácter de terminación, normalmente un valor de carácter con todos los bits a cero, como en el lenguaje de programación C. Véase también " Terminado en nulo " más adelante.

Codificación de caracteres

Históricamente, los tipos de datos de cadena asignaban un byte por carácter y, aunque el conjunto de caracteres exacto variaba según la región, las codificaciones de caracteres eran lo suficientemente similares como para que los programadores a menudo pudieran ignorar esta diferencia, ya que los caracteres que un programa trataba de forma especial (como el punto, el espacio y la coma) se encontraban en la misma posición en todas las codificaciones que el programa pudiera encontrar. Estos conjuntos de caracteres se basaban típicamente en ASCII o EBCDIC . Si un texto con una codificación se mostraba en un sistema que utilizaba una codificación diferente, el texto a menudo aparecía distorsionado , aunque con frecuencia era algo legible, y algunos usuarios de computadoras aprendieron a leer el texto distorsionado.

Los idiomas logográficos como el chino , el japonés y el coreano (conocidos colectivamente como CJK ) requieren muchos más de 256 caracteres (el límite de una codificación de un byte de 8 bits por carácter) para una representación razonable. Las soluciones habituales consistían en mantener representaciones de un byte para ASCII y utilizar representaciones de dos bytes para los ideogramas CJK . El uso de estas con el código existente generaba problemas de coincidencia y corte de cadenas, cuya gravedad dependía del diseño de la codificación de caracteres. Algunas codificaciones, como la familia EUC, garantizan que un valor de byte en el rango ASCII representará únicamente ese carácter ASCII, lo que las hace seguras para sistemas que utilizan esos caracteres como separadores de campos. Otras codificaciones, como ISO-2022 y Shift-JIS, no ofrecen tales garantías, lo que hace que la coincidencia de códigos de bytes sea insegura. Estas codificaciones tampoco eran "autosincronizables", por lo que localizar los límites de los caracteres requería retroceder al inicio de una cadena, y la unión de dos cadenas podía provocar la corrupción de la segunda.

Unicode ha simplificado un poco el panorama. La mayoría de los lenguajes de programación ahora tienen un tipo de dato para cadenas Unicode. El formato de flujo de bytes preferido de Unicode , UTF-8, está diseñado para evitar los problemas descritos anteriormente para codificaciones multibyte más antiguas. UTF-8, UTF-16 y UTF-32 requieren que el programador sepa que las unidades de código de tamaño fijo son diferentes de los "caracteres". La principal dificultad actualmente radica en las API mal diseñadas que intentan ocultar esta diferencia (UTF-32 sí hace que los puntos de código sean de tamaño fijo, pero estos no son "caracteres" debido a la composición de códigos).

Implementaciones

Algunos lenguajes, como C++ , Perl y Ruby , normalmente permiten que el contenido de una cadena se cambie después de haber sido creada; estas se denominan cadenas mutables . En otros lenguajes, como Java , JavaScript , Lua , Python y Go , el valor es fijo y se debe crear una nueva cadena si se va a realizar alguna modificación; estas se denominan cadenas inmutables . Algunos de estos lenguajes con cadenas inmutables también proporcionan otro tipo que es mutable, como Java y .NETStringBuilder , Java seguro para subprocesos StringBuffery Cocoa . La inmutabilidad trae ventajas y desventajas: si bien las cadenas inmutables pueden requerir la creación ineficiente de NSMutableStringmuchas copias, son más simples y completamente seguras para subprocesos .

Las cadenas de caracteres suelen implementarse como matrices de bytes, caracteres o unidades de código, para permitir un acceso rápido a unidades individuales o subcadenas, incluidos los caracteres cuando tienen una longitud fija. Algunos lenguajes, como Haskell, las implementan como listas enlazadas .

Muchos lenguajes de alto nivel proporcionan cadenas como un tipo de dato primitivo, como JavaScript y PHP , mientras que la mayoría de los demás las proporcionan como un tipo de dato compuesto, algunos con soporte especial del lenguaje para escribir literales, por ejemplo, Java y C# .

Algunos lenguajes, como C , Prolog y Erlang , evitan implementar un tipo de dato específico para cadenas de caracteres, optando en su lugar por representarlas como listas de códigos de caracteres. Incluso en lenguajes de programación que sí cuentan con un tipo de cadena específico, estas suelen poder recorrerse como una secuencia de códigos de caracteres, al igual que las listas de enteros u otros valores.

Representaciones

La representación de cadenas depende en gran medida del repertorio de caracteres elegido y del método de codificación de caracteres. Las implementaciones de cadenas más antiguas se diseñaron para funcionar con el repertorio y la codificación definidos por ASCII, o extensiones más recientes como la serie ISO 8859. Las implementaciones modernas suelen utilizar el extenso repertorio definido por Unicode junto con diversas codificaciones complejas como UTF-8 y UTF-16.

El término cadena de bytes suele referirse a una cadena de bytes de uso general, en lugar de cadenas de caracteres (legibles), cadenas de bits, etc. Las cadenas de bytes suelen implicar que los bytes pueden tomar cualquier valor y que cualquier dato puede almacenarse tal cual, lo que significa que no debería haber ningún valor que se interprete como un valor de terminación.

La mayoría de las implementaciones de cadenas son muy similares a los arreglos de longitud variable, donde las entradas almacenan los códigos de los caracteres correspondientes. La principal diferencia radica en que, con ciertas codificaciones, un solo carácter lógico puede ocupar más de una entrada en el arreglo. Esto ocurre, por ejemplo, con UTF-8, donde los códigos individuales ( puntos de código UCS ) pueden ocupar entre uno y cuatro bytes, y los caracteres individuales pueden ocupar un número arbitrario de códigos. En estos casos, la longitud lógica de la cadena (número de caracteres) difiere de la longitud física del arreglo (número de bytes utilizados). UTF-32 evita la primera parte del problema.

Vectores de drogas

La longitud de una cadena se puede almacenar en un vector de datos , separado del almacenamiento que contiene los caracteres propiamente dichos. El compilador IBM PL/I (F) utilizaba un vector de datos de cadena [ 11 ] (SDV) para cadenas de longitud variable y para pasar parámetros de cadena. El SDV contiene una longitud actual y una longitud máxima, y ​​no es adyacente a la cadena propiamente dicha. Después de PL/I (F), IBM abandonó el SDV en favor de cadenas con prefijo de longitud.

Terminado en nulo

La longitud de una cadena se puede almacenar implícitamente mediante un carácter de terminación especial; a menudo se trata del carácter nulo (NUL), que tiene todos los bits a cero, una convención utilizada y perpetuada por el popular lenguaje de programación C. [ 12 ] Por lo tanto, esta representación se conoce comúnmente como cadena C. Esta representación de una cadena de n caracteres ocupa n + 1 espacio (1 para el terminador) y, por consiguiente, es una estructura de datos implícita .

En las cadenas terminadas, el código de terminación no es un carácter permitido en ninguna cadena. Las cadenas con campo de longitud no tienen esta limitación y también pueden almacenar datos binarios arbitrarios .

Un ejemplo de una cadena terminada en nulo almacenada en un búfer de 10 bytes , junto con su representación ASCII (o UTF-8 más moderna ) como números hexadecimales de 8 bits es:

La cadena del ejemplo anterior, " FRANK", tiene una longitud de 5 caracteres, pero ocupa 6 bytes. Los caracteres posteriores al terminador no forman parte de la representación; pueden pertenecer a otros datos o ser simplemente basura. (A las cadenas de este tipo se las denomina a veces cadenas ASCIZ , en referencia a la directiva del lenguaje ensamblador original utilizada para declararlas).

Terminado por byte y por bit

El uso de un byte especial distinto de nulo para terminar cadenas ha aparecido históricamente tanto en hardware [ a ] ​​como en software, aunque a veces con un valor que también era un carácter de impresión. $fue utilizado por muchos sistemas ensambladores, :utilizado por sistemas CDC (este carácter tenía un valor de cero), y el ZX80 utilizó "[ 15 ] ya que este era el delimitador de cadena en su lenguaje BASIC.

De forma similar, las máquinas de procesamiento de datos como la IBM 1401 utilizaban un bit especial para delimitar las cadenas a la izquierda, donde la operación comenzaba a la derecha. Este bit debía estar vacío en el resto de la cadena. Esto significaba que, si bien la IBM 1401 disponía de una palabra de siete bits, casi nadie pensó en utilizarla como una función y modificar la asignación del séptimo bit para, por ejemplo, manejar códigos ASCII.

El software de los primeros microordenadores se basaba en el hecho de que los códigos ASCII no utilizan el bit de orden superior y lo configuraban para indicar el final de una cadena. Debía restablecerse a 0 antes de la salida. [ 16 ]

Prefijo de longitud

La longitud de una cadena también se puede almacenar explícitamente, por ejemplo, anteponiendo la longitud como un valor de byte. Esta convención se utiliza en muchos dialectos de Pascal ; por consiguiente, algunas personas llaman a dicha cadena cadena de Pascal o cadena P. Almacenar la longitud de la cadena como un byte limita la longitud máxima de la cadena a 255. Para evitar tales limitaciones, las implementaciones mejoradas de cadenas P utilizan palabras de 16, 32 o 64 bits para almacenar la longitud de la cadena. Cuando el campo de longitud cubre el espacio de direcciones , las cadenas están limitadas únicamente por la memoria disponible .

Si la longitud está limitada, se puede codificar en un espacio constante, normalmente una palabra de máquina, lo que da lugar a una estructura de datos implícita que ocupa un espacio de n + k caracteres , donde k es el número de caracteres de una palabra (8 para ASCII de 8 bits en una máquina de 64 bits, 1 para UTF-32/UCS-4 de 32 bits en una máquina de 32 bits, etc.). Si la longitud no está limitada, codificar una longitud n ocupa log( n ) espacio (véase código de longitud fija ), por lo que las cadenas con prefijo de longitud son una estructura de datos concisa que codifica una cadena de longitud n en log( n ) + n espacio.

En este último caso, el campo de prefijo de longitud en sí no tiene una longitud fija, por lo que los datos de la cadena real deben moverse cuando la cadena crece, de manera que el campo de longitud deba incrementarse.

Aquí se muestra una cadena Pascal almacenada en un búfer de 10 bytes, junto con su representación ASCII/UTF-8:

Cadenas como registros

Muchos lenguajes, incluidos los orientados a objetos, implementan las cadenas como registros con una estructura interna como:

public final class String { private unsigned long length ; // longitud de la cadena private UniquePointer < char [] > text ; // propiedad explícita // métodos públicos... }

Sin embargo, dado que la implementación suele estar oculta , se debe acceder a la cadena y modificarla a través de funciones miembro. textes un puntero a un área de memoria asignada dinámicamente, que puede expandirse según sea necesario. Véase también string (C++) .

Otras representaciones

Tanto los códigos de terminación de caracteres como los códigos de longitud limitan las cadenas: por ejemplo, las matrices de caracteres de C que contienen caracteres nulos (NUL) no pueden ser manejadas directamente por las funciones de la biblioteca de cadenas de C : las cadenas que utilizan un código de longitud están limitadas al valor máximo de dicho código.

Ambas limitaciones pueden superarse mediante una programación inteligente.

Es posible crear estructuras de datos y funciones que las manipulen sin los problemas asociados a la terminación de caracteres, y que, en principio, pueden superar las limitaciones del código de longitud. También es posible optimizar la cadena representada mediante técnicas de codificación de longitud variable (sustituyendo los caracteres repetidos por el valor del carácter y su longitud) y codificación de Hamming .

Si bien estas representaciones son comunes, existen otras posibles. El uso de cuerdas hace que ciertas operaciones con cadenas, como inserciones, eliminaciones y concatenaciones, sean más eficientes.

La estructura de datos principal en un editor de texto es la que gestiona la cadena (secuencia de caracteres) que representa el estado actual del archivo que se está editando. Si bien ese estado podría almacenarse en una única matriz larga y consecutiva de caracteres, un editor de texto típico utiliza una representación alternativa como su estructura de datos de secuencia —un búfer de espacios , una lista enlazada de líneas, una tabla de piezas o una cuerda— lo que hace que ciertas operaciones con cadenas, como inserciones, eliminaciones y deshacer ediciones anteriores, sean más eficientes. [ 17 ]

Preocupaciones de seguridad

Las distintas distribuciones de memoria y los requisitos de almacenamiento de las cadenas pueden afectar la seguridad del programa que accede a los datos de la cadena. Las representaciones de cadena que requieren un carácter de terminación suelen ser vulnerables a problemas de desbordamiento de búfer si dicho carácter no está presente, ya sea por un error de codificación o por la alteración deliberada de los datos por parte de un atacante . Las representaciones de cadena que utilizan un campo de longitud independiente también son vulnerables si la longitud puede manipularse. En estos casos, el código del programa que accede a los datos de la cadena requiere una comprobación de límites para garantizar que no acceda ni modifique datos fuera de los límites de memoria de la cadena.

Los datos de tipo cadena se obtienen frecuentemente de la entrada del usuario a un programa. Por lo tanto, es responsabilidad del programa validar la cadena para asegurar que tenga el formato esperado. Una validación limitada o nula de la entrada del usuario puede hacer que un programa sea vulnerable a ataques de inyección de código .

Cadenas literales

En ocasiones, es necesario insertar cadenas de texto en archivos legibles por humanos y destinados a ser procesados ​​por máquinas. Esto se requiere, por ejemplo, en el código fuente de lenguajes de programación o en archivos de configuración. En este caso, el carácter nulo no funciona bien como terminador, ya que normalmente es invisible (no imprimible) y resulta difícil de introducir mediante el teclado. Almacenar la longitud de la cadena también sería inconveniente, puesto que el cálculo y el seguimiento manual de la longitud son tediosos y propensos a errores.

Dos representaciones comunes son:

Cadenas que no son de texto

Si bien las cadenas de caracteres son un uso muy común de las cadenas, en informática una cadena puede referirse genéricamente a cualquier secuencia de datos de tipo homogéneo. Una cadena de bits o de bytes , por ejemplo, puede usarse para representar datos binarios no textuales obtenidos de un medio de comunicación. Estos datos pueden o no estar representados por un tipo de dato específico de cadena, según las necesidades de la aplicación, las preferencias del programador y las capacidades del lenguaje de programación utilizado. Si la implementación de cadenas del lenguaje de programación no es compatible con 8 bits , puede producirse corrupción de datos.

Los programadores de C distinguen claramente entre una "cadena", también conocida como "cadena de caracteres", que por definición siempre termina en nulo, y una "matriz de caracteres", que puede almacenarse en la misma matriz pero que a menudo no termina en nulo. El uso de funciones de manejo de cadenas de C en una matriz de caracteres de este tipo suele funcionar, pero posteriormente genera problemas de seguridad . [ 18 ] [ 19 ] [ 20 ]

Algoritmos de procesamiento de cadenas

Existen numerosos algoritmos para el procesamiento de cadenas, cada uno con sus propias ventajas e inconvenientes. Los algoritmos que compiten entre sí pueden analizarse en función del tiempo de ejecución, los requisitos de almacenamiento, etc. El término «stringología» fue acuñado en 1984 por el informático Zvi Galil para referirse a la teoría de algoritmos y estructuras de datos utilizados para el procesamiento de cadenas. [ 21 ] [ 22 ] [ 23 ]

Algunas categorías de algoritmos incluyen:

Los algoritmos avanzados de cadenas de caracteres suelen emplear mecanismos y estructuras de datos complejos, entre ellos árboles de sufijos y máquinas de estados finitos .

Lenguajes y utilidades orientados a cadenas de caracteres

Las cadenas de caracteres son un tipo de dato tan útil que se han diseñado varios lenguajes para facilitar la escritura de aplicaciones de procesamiento de cadenas. Algunos ejemplos son los siguientes lenguajes:

Muchas utilidades de Unix realizan manipulaciones sencillas de cadenas y pueden utilizarse para programar fácilmente potentes algoritmos de procesamiento de cadenas. Los archivos y las secuencias finitas pueden considerarse cadenas.

Algunas API, como la Interfaz de Control Multimedia , SQL embebido o printf, utilizan cadenas de texto para almacenar comandos que serán interpretados.

Muchos lenguajes de programación de scripts , incluidos Perl, Python , Ruby y Tcl, emplean expresiones regulares para facilitar las operaciones de texto. Perl es particularmente conocido por su uso de expresiones regulares, [ 24 ] y muchos otros lenguajes y aplicaciones implementan expresiones regulares compatibles con Perl .

Algunos lenguajes, como Perl y Ruby, admiten la interpolación de cadenas , lo que permite evaluar expresiones arbitrarias e incluirlas en literales de cadena.

funciones de cadena de caracteres

Las funciones de cadena se utilizan para crear cadenas o modificar el contenido de una cadena mutable. También se utilizan para consultar información sobre una cadena. El conjunto de funciones y sus nombres varían según el lenguaje de programación .

El ejemplo más básico de una función de cadena es la función de longitud de cadenalength , que devuelve la longitud de una cadena (sin contar los caracteres de terminación ni la información estructural interna de la cadena) y no la modifica. Esta función suele llamarse , len, o size. Por ejemplo, length("hello world")devolvería 11. Otra función común es la concatenación , donde se crea una nueva cadena añadiendo dos cadenas; a menudo, se utiliza el operador de suma +.

Algunas arquitecturas de conjuntos de instrucciones de microprocesadores contienen soporte directo para operaciones de cadena, como la copia de bloques (por ejemplo, en Intel x86m ). [ 25 ]REPNZ MOVSB

Teoría formal

DejarΣ{\displaystyle \Sigma }ser un conjunto finito de símbolos distintos e inequívocos (también llamados caracteres), llamado alfabeto . Una cadena (o palabra [ 26 ] o expresión [ 27 ] ) sobreΣ{\displaystyle \Sigma }es cualquier secuencia finita de símbolos deΣ{\displaystyle \Sigma }. [ 28 ] Por ejemplo, siΣ={0,1}{\displaystyle \Sigma =\{{\texttt {0}},{\texttt {1}}\}}, entonces01011{\displaystyle {\texttt {01011}}}es una cadena sobreΣ{\displaystyle \Sigma }.

La longitud de una cuerdas{\displaystyle s}es el número de símbolos ens{\displaystyle s}(la longitud de la secuencia) y puede ser cualquier entero no negativo ; a menudo se denota como|s|{\displaystyle |s|}. La cadena vacía es la cadena única sobreΣ{\displaystyle \Sigma }de longitud0{\displaystyle 0}y se denotaε{\displaystyle \varepsilon }oλ{\displaystyle \lambda }. [ 28 ] [ 29 ]

El conjunto de todas las cadenas sobreΣ{\displaystyle \Sigma }de longitudnorte{\displaystyle n}se denotaΣnorte{\displaystyle \Sigma ^{n}}. Por ejemplo, siΣ={0,1}{\displaystyle \Sigma =\{{\texttt {0}},{\texttt {1}}\}}, entoncesΣ2={00,01,10,11}{\displaystyle \Sigma ^{2}=\{{\texttt {00}},{\texttt {01}},{\texttt {10}},{\texttt {11}}\}}. TenemosΣ0={ε}{\displaystyle \Sigma ^{0}=\{\varepsilon \}}para cada alfabetoΣ{\displaystyle \Sigma }.

El conjunto de todas las cadenas sobreΣ{\displaystyle \Sigma }de cualquier longitud es el cierre de Kleene deΣ{\displaystyle \Sigma }y se denotaΣ{\displaystyle \Sigma ^{*}}En términos deΣnorte{\displaystyle \Sigma ^{n}},

Σ=norte=0Σnorte{\displaystyle \Sigma ^{*}=\bigcup _{n=0}^{\infty }\Sigma ^{n}}

Por ejemplo, siΣ={0,1}{\displaystyle \Sigma =\{{\texttt {0}},{\texttt {1}}\}}, entoncesΣ={ε,0,1,00,01,10,11,000,001,010,011,...}{\displaystyle \Sigma ^{*}=\{\varepsilon ,{\texttt {0}},{\texttt {1}},{\texttt {00}},{\texttt {01}},{\texttt {10}},{\texttt {11}},{\texttt {000}},{\texttt {001}},{\texttt {010}},{\texttt {011}},...\}}Aunque el conjuntoΣ{\displaystyle \Sigma ^{*}}en sí mismo es infinitamente numerable , cada elemento deΣ{\displaystyle \Sigma ^{*}}es una cadena de longitud finita.

Un conjunto de cuerdas sobreΣ{\displaystyle \Sigma }(es decir, cualquier subconjunto deΣ{\displaystyle \Sigma ^{*}}) se denomina lenguaje formal sobreΣ{\displaystyle \Sigma }. Por ejemplo, siΣ={0,1}{\displaystyle \Sigma =\{{\texttt {0}},{\texttt {1}}\}}, el conjunto de cadenas con un número par de ceros,{ε,1,00,11,001,010,100,111,0000,0011,0101,0110,1001,1010,1100,1111,...}{\displaystyle \{\varepsilon ,{\texttt {1}},{\texttt {00}},{\texttt {11}},{\texttt {001}},{\texttt {010}},{\texttt {100}},{\texttt {111}},{\texttt {0000}},{\texttt {0011}},{\texttt {0101}},{\texttt {0110}},{\texttt {1001}},{\texttt {1010}},{\texttt {1100}},{\texttt {1111}},...\}}, es un lenguaje formal sobreΣ{\displaystyle \Sigma }.

Concatenación y subcadenas

La concatenación es una operación binaria importante enΣ{\displaystyle \Sigma ^{*}}. Para cualesquiera dos cadenass{\displaystyle s}yt{\displaystyle t}enΣ{\displaystyle \Sigma ^{*}}, su concatenación se define como la secuencia de símbolos ens{\displaystyle s}seguido de la secuencia de caracteres ent{\displaystyle t}y se denotast{\displaystyle st}. Por ejemplo, siΣ={a,b,...,z}{\displaystyle \Sigma =\{{\texttt {a}},{\texttt {b}},...,{\texttt {z}}\}}(es decir, el alfabeto inglés en minúsculas ),s=oso{\displaystyle s={\texttt {bear}}}, yt=abrazo{\displaystyle t={\texttt {hug}}}, entoncesst=abrazo de oso{\displaystyle st={\texttt {bearhug}}}yts=osito de abrazo{\displaystyle ts={\texttt {hugbear}}}.

La concatenación de cadenas es una operación asociativa , pero no conmutativa . La cadena vacíaε{\displaystyle \varepsilon }sirve como elemento identidad ; para cualquier cadenas{\displaystyle s},εs=sε=s{\displaystyle \varepsilon s=s\varepsilon =s}. Por lo tanto, el conjuntoΣ{\displaystyle \Sigma ^{*}}y la operación de concatenación forman un monoide , el monoide libre generado porΣ{\displaystyle \Sigma }Además, la función de longitud define un homomorfismo monoide deΣ{\displaystyle \Sigma ^{*}}a los enteros no negativos (es decir, una funciónL:Σnorte{0}{\displaystyle L:\Sigma ^{*}\mapsto \mathbb {N} \cup \{0\}}, de tal manera queL(st)=L(s)+L(t)s,tΣ{\displaystyle L(st)=L(s)+L(t)\quad \forall s,t\in \Sigma ^{*}}).

Una cuerdas{\displaystyle s}Se dice que es una subcadena o factor det{\displaystyle t}si existen cadenas (posiblemente vacías){\displaystyle u}yv{\displaystyle v}de tal manera quet=sv{\displaystyle t=usv}. La relación "es una subcadena de" define un orden parcial enΣ{\displaystyle \Sigma ^{*}}, cuyo elemento más pequeño es la cadena vacía.

Prefijos y sufijos

Una cuerdas{\displaystyle s}Se dice que es un prefijo det{\displaystyle t}si existe una cadena{\displaystyle u}de tal manera quet=s{\displaystyle t=su}. Si{\displaystyle u}no está vacío,s{\displaystyle s}Se dice que es un prefijo propio det{\displaystyle t}. Simétricamente, una cuerdas{\displaystyle s}Se dice que es un sufijo det{\displaystyle t}si existe una cadena{\displaystyle u}de tal manera quet=s{\displaystyle t=us}. Si{\displaystyle u}no está vacío,s{\displaystyle s}Se dice que es un sufijo propio det{\displaystyle t}. Los sufijos y prefijos son subcadenas det{\displaystyle t}. Tanto la relación "es un prefijo de" como "es un sufijo de" son órdenes de prefijo .

Inversión

La inversa de una cadena es una cadena con los mismos símbolos pero en orden inverso. Por ejemplo, sis=abecedario{\displaystyle s={\texttt {abc}}}(dóndea{\displaystyle {\texttt {a}}},b{\displaystyle {\texttt {b}}}, ydo{\displaystyle {\texttt {c}}}son símbolos del alfabeto), entonces lo contrario des{\displaystyle s}escba{\displaystyle {\texttt {cba}}}. Una cadena que es la inversa de sí misma (por ejemplo,s=señora{\displaystyle s={\texttt {madam}}}) se llama palíndromo , que también incluye la cadena vacía y todas las cadenas de longitud1{\displaystyle 1}.

Rotaciones

Una cuerdas=v{\displaystyle s=uv}Se dice que es una rotación det{\displaystyle t}sit=v{\displaystyle t=vu}. Por ejemplo, siΣ={0,1}{\displaystyle \Sigma =\{{\texttt {0}},{\texttt {1}}\}}la cuerda0011001{\displaystyle {\texttt {0011001}}}es una rotación de0100110{\displaystyle {\texttt {0100110}}}, dónde=00110{\displaystyle u={\texttt {00110}}}yv=01{\displaystyle v={\texttt {01}}}. Como otro ejemplo, la cadenaabecedario{\displaystyle {\texttt {abc}}}tiene tres rotaciones diferentes, a saber:abecedario{\displaystyle {\texttt {abc}}}sí mismo (con=abecedario{\displaystyle u={\texttt {abc}}},v=ε{\displaystyle v=\varepsilon }),bca{\displaystyle {\texttt {bca}}}(con=antes de Cristo,v=a{\displaystyle u={\texttt {bc}},v={\texttt {a}}}), ytaxi{\displaystyle {\texttt {cab}}}(con=do,v=ab{\displaystyle u={\texttt {c}},v={\texttt {ab}}}).

ordenación lexicográfica

A menudo resulta útil definir un orden en un conjunto de cadenas. Si el alfabetoΣ{\displaystyle \Sigma }tiene un orden total (cf. orden alfabético ) se puede definir un orden total enΣ{\displaystyle \Sigma ^{*}}llamado orden lexicográfico . El orden lexicográfico es total si el orden alfabético lo es, pero no está bien fundamentado para ningún alfabeto no trivial, incluso si el orden alfabético lo es. Por ejemplo, siΣ={0,1}{\displaystyle \Sigma =\{{\texttt {0}},{\texttt {1}}\}}y0<1{\displaystyle {\texttt {0}}<{\texttt {1}}}, luego el orden lexicográfico enΣ{\displaystyle \Sigma ^{*}}incluye las relacionesε<0<00<000<...<0001<...<001<...<01<010<...<011<0110<...<01111<...<1<10<100<...<101<...<111<...<1111<...<11111...{\displaystyle \varepsilon <{\texttt {0}}<{\texttt {00}}<{\texttt {000}}<...<{\texttt {0001}}<...<{\texttt {001}}<...<{\texttt {01}}<{\texttt {010}}<...<{\texttt {011}}<{\texttt {0110}}<...<{\texttt {01111}}<...<{\texttt {1}}<{\texttt {10}}<{\texttt {100}}<...<{\texttt {101}}<...<{\texttt {111}}<...<{\texttt {1111}}<...<{\texttt {11111}}...}Con respecto a este ordenamiento, por ejemplo, el conjunto infinito{1,01,001,0001,00001,000001,...}{\displaystyle \{{\texttt {1}},{\texttt {01}},{\texttt {001}},{\texttt {0001}},{\texttt {00001}},{\texttt {000001}},...\}}no tiene ningún elemento mínimo.

Consulte Shortlex para ver un ordenamiento de cadenas alternativo que preserva la buena fundamentación. Para el alfabeto de ejemplo, el orden de Shortlex esε<0<1<00<01<10<11<000<001<010<011<100<101<0110<111<0000<0001<0010<0011<...<1111<00000<00001...{\displaystyle \varepsilon <{\texttt {0}}<{\texttt {1}}<{\texttt {00}}<{\texttt {01}}<{\texttt {10}}<{\texttt {11}}<{\texttt {000}}<{\texttt {001}}<{\texttt {010}}<{\texttt {011}}<{\texttt {100}}<{\texttt {101}}<{\texttt {0110}}<{\texttt {111}}<{\texttt {0000}}<{\texttt {0001}}<{\texttt {0010}}<{\texttt {0011}}<...<{\texttt {1111}}<{\texttt {00000}}<{\texttt {00001}}...}

Operaciones con cadenas

En la teoría formal, suelen aparecer varias operaciones adicionales sobre cadenas. Estas se describen en el artículo sobre operaciones con cadenas .

Topología

(Hiper)cubo de cadenas binarias de longitud3{\displaystyle 3}

Las cadenas admiten la siguiente interpretación como nodos en un grafo, dondek{\displaystyle k}es el número de símbolos enΣ{\displaystyle \Sigma }:

  • Cadenas de longitud fija de longitudnorte{\displaystyle n}se puede ver como las ubicaciones enteras en unnorte{\displaystyle n}Hipercubo dimensional con lados de longitudk1{\displaystyle k-1}.
  • Las cadenas de longitud variable (de longitud finita) pueden verse como nodos en una cadena perfecta.k{\displaystyle k}-ario árbol .
  • Las cadenas infinitas (que no se consideran aquí) pueden verse como caminos infinitos en unak{\displaystyle k}-grafo completo del nodo .

La topología natural en el conjunto de cadenas de longitud fija o variable es la topología discreta, pero la topología natural en el conjunto de cadenas infinitas es la topología límite , que considera el conjunto de cadenas infinitas como el límite inverso de los conjuntos de cadenas finitas. Esta es la construcción utilizada para los números p -ádicos y algunas construcciones del conjunto de Cantor , y produce la misma topología.

Se pueden encontrar isomorfismos entre representaciones de cadenas de topologías normalizando según la rotación de cadena lexicográficamente mínima .

Véase también

Notas explicativas

  1. Por ejemplo, la instrucción RCA 501 Item Transfer (IT) [ 13 ] utiliza un Item Separator Symbol (ISS), las instrucciones RCA 301 Locate Symbol (LSL, LSR), Transfer Data by Symbol (DSL, DSR) y Transfer Symbol to Fill (SF) [ 14 ] utilizan un carácter en la instrucción.

Referencias

  1. "Introducción a Java – MFC 158 G" . Archivado del original el 3 de marzo de 2016. Los literales de cadena (o constantes) se denominan "cadenas anónimas".
  2. de St. Germain, H. James. "Strings" . Universidad de Utah, Escuela de Informática Kahlert .
  3. Francis, David M.; Merk, Heather L. (14 de noviembre de 2019). "El ADN como entidad bioquímica y cadena de datos" .
  4. 1 2 3 Burchfield, RW (1986). "string". Un suplemento del Oxford English Dictionary . Oxford en Clarendon Press.
  5. "string". The Oxford English Dictionary . Vol. X. Oxford at the Clarendon Press. 1933. 
  6. "cuerda (sust.)" . Diccionario etimológico en línea .
  7. Whitney, William Dwight ; Smith, Benjamin E. "string". The Century Dictionary . Nueva York: The Century Company. pág. 5994. 
  8. "La desaparición de Old Union". Milwaukee Sentinel . 11 de enero de 1898. pág. 3. 
  9. Lewis, CI (1918). Un estudio de la lógica simbólica . Berkeley: University of California Press. pág. 355. 
  10. Sammet, Jean E. (julio de 1972). "Lenguajes de programación: historia y futuro" (PDF) . Communications of the ACM . 15 (7). doi : 10.1145/361454.361485 . S2CID 2003242 . 
  11. "Datos de cadena" (PDF) . Sistema operativo IBM System/360 - PL/I (F) - Guía del programador - Número de programa 360S-NL-5ll (PDF) . Biblioteca de referencia de sistemas (quinta ed.). Noviembre de 1968. pág. 136. C28-6594-4 . Recuperado el 2 de septiembre de 2025. Los datos de longitud variable tienen áreas de control asociadas conocidas como "vectores dope" que describen las cadenas . Un vector dope contiene un registro de la longitud máxima y la longitud actual de la cadena, junto con un puntero al inicio de la cadena. Los vectores dope no tienen por qué estar adyacentes a los datos que describen, pero normalmente ocuparán almacenamiento de la misma clase de almacenamiento.  
  12. Bryant, Randal E .; David, O'Hallaron (2003), Sistemas informáticos: Una perspectiva del programador ( ed. 2003), Upper Saddle River, NJ: Pearson Education, pág. 40, ISBN   0-13-034074-XArchivado del original el 6 de agosto de 2007 .
  13. "Instrucciones del RCA 501" (PDF) . Sistema de procesamiento electrónico de datos RCA 501 - Manual de referencia para programadores (PDF) . Radio Corporation of America . 1958. pág. 35. P501-2 . Consultado el 18 de noviembre de 2025 . 
  14. "Instrucciones del RCA 301 - Introducción" (PDF) . Sistema de procesamiento electrónico de datos RCA 301 - Manual de referencia para programadores (PDF) . Radio Corporation of America . Enero de 1962. págs. 33-44 . 93-17-000 . Consultado el 18 de noviembre de 2025 . 
  15. Wearmouth, Geoff. "Listado de ensamblaje de la ROM del Sinclair ZX80" . Archivado del original el 15 de agosto de 2015.
  16. Allison, Dennis. "Notas de diseño para Tiny BASIC" . Archivado del original el 10 de abril de 2017.
  17. Charles Crowley. "Estructuras de datos para secuencias de texto" Archivado el 4 de marzo de 2016 en Wayback Machine . Sección "Introducción" Archivado el 4 de abril de 2016 en Wayback Machine .
  18. "strlcpy y strlcat: copia y concatenación de cadenas consistentes y seguras." Archivado el 13 de marzo de 2016 en Wayback Machine.
  19. "Una diatriba sobre strcpy, strncpy y strlcpy." Archivado el 29/02/2016 en Wayback Machine
  20. Keith Thompson. "No, strncpy() no es una versión "más segura" de strcpy()". 2012.
  21. "El Club de Stringología de Praga" . stringology.org . Archivado del original el 1 de junio de 2015. Consultado el 23 de mayo de 2015 .
  22. Evarts, Holly (18 de marzo de 2021). "El ex decano Zvi Galil nombrado uno de los 10 científicos informáticos más influyentes de la última década" . Columbia Engineering . Inventó los términos "stringología", que es un subcampo de los algoritmos de cadenas,
  23. Crochemore, Maxime (2002). Joyas de la cordología . Singapur. p. v. ISBN  981-02-4782-6El término "stringología" es un apodo popular tanto para los algoritmos de cadenas como para los algoritmos de texto .{{cite book}}: CS1 mantenimiento: falta el editor de ubicación ( enlace )
  24. "Perl esencial" . Archivado del original el 21/04/2012. La principal fortaleza de Perl reside en la manipulación de cadenas mediante expresiones regulares.
  25. "Instrucciones de cadena x86" . Archivado del original el 27 de marzo de 2015.
  26. Fletcher, Peter; Hoyle, Hughes; Patty, C. Wayne (1991). Fundamentos de matemáticas discretas . PWS-Kent. pág. 114. ISBN  0-53492-373-9. Sea Σ un alfabeto. Una palabra no vacía sobre Σ es una secuencia finita con dominio I n (para algún n ∈ ℕ) y codominio Σ.
  27. Shoenfield, Joseph R. (2010) [1967]. Lógica matemática ( Edición reimpresa). CRC Press. pág. 2. ISBN   978-156881135-2Cualquier secuencia finita de símbolos de un idioma se denomina expresión de ese idioma .
  28. 1 2 Barbara H. Partee; Alice ter Meulen ; Robert E. Wall (1990). Métodos matemáticos en lingüística . Kluwer.
  29. John E. Hopcroft, Jeffrey D. Ullman (1979). Introducción a la teoría de autómatas, lenguajes y computación . Addison-Wesley. ISBN 0-201-02988-X.Aquí: sección 1.1, pág. 1
Obtenido de " https://en.wikipedia.org/w/index.php?title=String_(computer_science)&oldid=1361735835 "