2
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;

int main() {
 char cadena[] = "";
 char cadena2[] = "cadena";
 cin >> cadena;
 cout << cadena <<endl;

 int len = strlen(cadena);
 int len2 = strlen(cadena2);
 cout << len << endl;
 cout << len2 << endl;
 return 0;
}

Para este pequeño codigo de prueba, me gustaría saber por que la salida, cuando ingreso "cadena" con el "cin" a la variable cadena[] me da una logintud de 10 con la funcion strlen, pero con la variable cadena2 me da 6?

salida:

cadena
cadena
10
6
Kevin Gutierrez
  • 109
  • 2
  • 11
  • 4
    Y, sin embargo, a mi me muestra 6: http://wandbox.org/permlink/GCfAGViAW0wdQnXZ . Supongo que es lo divertido de los *comportamientos indefinidos* :-) – Trauma Aug 26 '18 at 08:43
  • 1
    Kevin, como dice Trauma es un *undefined behavior*, ¿por qué usas char [] para guardar información de texto?, en C++ debes usar `std::string` :) –  Aug 26 '18 at 15:27

1 Answers1

4

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é.

  1. También conocido como arreglo o en inglés array.
  2. La marca de final de cadena no cuenta en la longitud de la cadena.
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82