Cada caracter ocupa un byte en memoria. Para poder leer un caracter, debes tener un espacio de memoria para almacenarlo, tú estás leyendo en dos formaciones1 de tamaño 1 y 7 respectivamente:
char cadena[] = ""; // Tamaño 1
char cadena2[] = "cadena"; // Tamaño 7
¿Cómo sabemos su tamaño?, en C++ (y C) puedes inicializar formaciones de caracteres con una cadena de caracteres inicial, debes asegurarte que la cadena de caracteres a almacenar quepa en la formación usada y sumarle un caracter para la marca de final de cadena2, en caso contrario el código no compilará:
char hola[5] = "Hola"; // H (1) o (2) l (3) a (4) \0 (5)
char mundo[5] = "Mundo"; // Error, la marca de final de cadena no cabe.
Como suele ser muy tedioso contar los caracteres de un texto para saber el tamaño de la formación, C++ (y C) permiten que el compilador cuente los caracteres por ti, eso se consigue dejando el tamaño de la formación vacío:
char hola[] = "Hola"; // 5 caracteres, contados por el compilador
char mundo[] = "Mundo"; // 6 caracteres, contados por el compilador
Volviendo a tu caso, cuando lees "cadena"
sobre cadena
estás leyendo 7 caracteres sobre una formación que es capaz de almacenar 1... así que estás escribiendo un caracter en cadena
y 6 caracteres fuera del arreglo, cuando le pasas esa memoria mal usada a strlen
, la función puede comportarse de manera inesperada porque al fin y al cabo, has usado la memoria de manera inesperada.
Solución.
Usa búferes más grandes:
char cadena[100] = "";
char cadena2[100] = "cadena";
Propuesta.
Olvida las formaciones de caracteres, usa directamente std::string
:
#include <iostream>
int main() {
std::string cadena = "";
std::string cadena2 = "cadena";
std::cin >> cadena;
std::cout << cadena << std::endl;
auto len = cadena.length();
auto len2 = cadena2.length();
std::cout << len << std::endl;
std::cout << len2 << std::endl;
return 0;
}
Otras cosas a tener en cuenta.
- Las cabeceras
<string.h>
, y <stdio.h>
son de C, no de C++, si realmente necesitas usarlas (que no las necesitas) debes usar los equivalentes de C++: <cstring>
y <cstdio>
. Consulta esta pregunta para saber por qué.
- Evita usar
using namespace std
innecesariamente, si lo usas: usalo en el ámbito más pequeño posible, consulta esta pregunta para saber por qué.
- Evita abusar de
std::endl
, consulta esta pregunta para saber por qué.
- También conocido como arreglo o en inglés array.
- La marca de final de cadena no cuenta en la longitud de la cadena.