PHP: Unicode
Los datos de un programa se almacenan en la memoria de la computadora como una secuencia de ceros y unos. En este nivel, no hay diferencia entre cadenas de texto, números o valores booleanos. Todo se ve igual en la memoria. La diferencia aparece solo en la interpretación.
El programa sabe que dentro de una variable se almacena una cadena de texto, por lo que toma los ceros y unos y los pasa a través de una tabla de códigos. En esta tabla se indica a qué número corresponde cada letra. Como resultado, el programador ve una cadena de texto. En esta lección discutiremos cómo funcionan estas tablas de códigos.
Al principio, solo existía el ASCII - un conjunto de caracteres basado en el alfabeto inglés.
En este conjunto de caracteres, cada símbolo se representa con 7 bits, lo que da un total de 128 caracteres:
- 95 caracteres imprimibles, incluyendo letras mayúsculas y minúsculas, números y signos de puntuación.
- 33 caracteres no imprimibles (códigos de control).
La mayoría de los caracteres no imprimibles ya no son relevantes, pero algunos todavía se utilizan, como el salto de línea \n
.
Los caracteres en ASCII se pueden codificar. Por ejemplo, el carácter i
en minúscula corresponde a:
- El número
1101001
en sistema binario. - El número
105
en sistema decimal.
Al principio todo estaba bien, pero con la proliferación de las computadoras surgió la necesidad de otros alfabetos. Cada país resolvió este problema creando su propio conjunto de caracteres, la mayoría de los cuales eran compatibles con ASCII:
- Los primeros 128 caracteres eran idénticos a ASCII.
- Los otros 128 caracteres se llenaban con el alfabeto local.
Como resultado, estos conjuntos de caracteres tenían 256 caracteres, lo que equivale a 2 a la 8va potencia.
Estos conjuntos de caracteres eran de un solo byte, lo que significa que se necesitaba un byte para almacenar un solo carácter. Pero de repente surgió un problema: al intentar abrir un archivo en un editor con una codificación diferente, aparecían caracteres ilegibles, conocidos como «garabatos»:
Øèðîêàÿ ýëåêòðèôèêàöèÿ þæíûõ ãóáåðíèé äàñò ìîùíûé òîë÷îê ïîäú¸ìó ñåëüñêîãî õîçÿéñòâà
Estos caracteres aparecen porque el mismo código en diferentes codificaciones corresponde a caracteres completamente diferentes, excepto los primeros 128. Por lo tanto, el texto que utiliza letras en inglés siempre se lee correctamente, pero en otros casos, depende de la suerte. La situación se complicaba aún más porque incluso dentro de un solo alfabeto se creaban múltiples codificaciones diferentes, como Windows-1252, KOI8-R, CP 866, ISO 8859-5.
En ese momento, en los lenguajes de programación, todas las funciones para trabajar con cadenas de texto se creaban asumiendo que un carácter era igual a un byte. Al menos, esta propiedad era común a todas las codificaciones.
Las diferentes codificaciones se convirtieron en la causa de problemas constantes en la interacción entre personas y programas. Esta problemática se agravó especialmente con el desarrollo de Internet. Esta situación no podía continuar indefinidamente, y finalmente se creó el estándar Unicode.
Actualmente, Unicode contiene más de 100,000 caracteres y abarca todos los idiomas existentes, incluso los muertos. El estándar Unicode no es una codificación y no dice nada sobre cómo se deben almacenar los caracteres en la memoria, solo establece la relación entre un carácter y un número.
La forma específica de codificar Unicode se determina mediante las codificaciones correspondientes, entre las que se encuentran UTF-8, UTF-16 y algunas otras. En estas codificaciones, un solo byte ya no es suficiente para almacenar un carácter, se necesitan más bytes. UTF-8 se comporta de manera más inteligente: utiliza un byte para los caracteres del alfabeto inglés y algunos otros, y dos bytes para otros alfabetos.
Después de muchos años de popularización de Unicode, ocurrió un milagro y ahora la gran mayoría del software utiliza UTF-8. Este proceso fue doloroso y tuvo diferentes efectos en los lenguajes de programación. Por ejemplo, en PHP, las funciones estándar no admiten codificaciones multibyte:
<?php
echo strlen('Hello!'); // => 6
https://replit.com/@hexlet/php-basics-strings-deeper-strlen
Los lenguajes se dividieron en dos campos. Algunos lenguajes incorporaron soporte para codificaciones multibyte en las funciones existentes, por lo que el cambio a UTF-8 no afectó el proceso de programación. Entre estos lenguajes se encuentran Java, Ruby, JavaScript.
Sin embargo, PHP siguió su propio camino. Para trabajar con codificaciones multibyte, se agregó una extensión separada para trabajar con cadenas multibyte al lenguaje. En su mayoría, esta extensión agrega muchas funciones para trabajar con cadenas, con la única diferencia de que cada función tiene el prefijo mb_
(multibyte):
<?php
echo mb_strlen('Hello!'); // => 6
https://replit.com/@hexlet/php-strings-deeper-mbstrlen
Sin embargo, no existe una alternativa adecuada para obtener un carácter específico en una cadena por su índice. Esta tarea se debe realizar utilizando la función mb_substr()
:
<?php
$str = 'Привет';
$symbol = mb_substr($str, 2, 1); // и
https://replit.com/@hexlet/php-basics-strings-deeper-mbsubstr
Tarea
Completa la implementación de la función invertCase()
, que invierte el caso de cada carácter en la cadena de texto proporcionada.
<?php
$str = 'ПрИвЕт!';
invertCase($str); // пРиВеТ!
¿El ejercicio no pasa la prueba, qué debo hacer? 😶
Si te quedaste atascado, es el momento perfecto para hacer una pregunta en las "Discusiones".
* Asegúrate de incluir la salida de las pruebas. Sin ella, es casi imposible entender qué está mal, incluso si muestras tu código. Los programadores tienen dificultades para ejecutar el código en su mente, pero casi siempre es posible entender a dónde mirar a partir del error que recibiste.
Mi código funciona en mi entorno, pero no aquí 🤨
Las pruebas están diseñadas de manera que verifican la solución de diferentes maneras y con diferentes datos. A menudo, una solución funciona con ciertos datos de entrada pero no con otros. Para entender este punto, revisa la pestaña "Pruebas" y presta atención a los mensajes de error, que suelen contener pistas.
Mi código es diferente a la solución del profesor 🤔
Esto es normal 🙆. En programación, una tarea puede tener muchas soluciones diferentes. Si tu código pasa la prueba, cumple con los requisitos de la tarea.
En raras ocasiones, la solución puede estar ajustada para pasar las pruebas, pero esto suele ser evidente.
Leí la lección, pero no entendí nada 🙄
Crear materiales de aprendizaje comprensibles para todos es bastante difícil. Hacemos nuestro mejor esfuerzo, pero siempre hay margen para mejorar. Si encuentras material que no entiendes, describe el problema en las "Discusiones". Es ideal si puedes formular los aspectos que no entiendes en forma de preguntas. Por lo general, necesitamos unos días para hacer mejoras.
Por cierto, tú también puedes contribuir a mejorar los cursos: en la parte inferior hay un enlace al código fuente de las lecciones, que se puede modificar directamente en el navegador.