int x = sizeof(sentence);
sizeof
es un operador que se evalúa en tiempo de compilación, es decir, el resultado lo calcula automáticamente el compilador. ¿Sabe el compilador qué va a introducir el usuario en cada momento? Obviamente no, así que sizeof
no puede devolverte la longitud de la cadena.
sizeof
indica la cantidad de memoria que ocupa una variable u objeto. En tu caso sentence
, que es un array de 20 caracteres, ocupara 20 bytes en memoria (1 char
== 1 byte) independientemente de la longitud del texto que almacene.
Para conocer la longitud de la cadena almacenada puedes usar strlen
, de la librería cstring
:
int x = std::strlen(sentence);
Seguidamente intentas separar la frase en palabras... aquí cometes otro error:
for(int a=0; a < x; a++){
if((sentence[a] != ' ')&&(sentence[a+1] == ' ')){
Fíjate que a
se mueve en el rango [0
,x-1
], que por cierto, nota que es un intervalo cerrado. Pues, bien, si a==x-1
, la comprobación sentence[a+1]
está comprobando un valor fuera del rango de la cadena. sentence[x]
debería tener, siempre el caracter nulo que finaliza las cadenas.
Para dividir una cadena en palabras puedes usar strtok
:
for( char* ptr = strtok(sentence," "); *(ptr = strtok(nullptr, " ")) != '\0'; )
{
std::cout << ptr << '\n';
}
Aunque yo sugeriría usar std::string
. En este caso podrías atacar el problema de varias maneras. Una en la que tendrías que escribir bastante poco código seŕia la siguiente:
- Lees la línea completa en un
std::string
(no tienes que preocuparte por la longitud del texto)
- Vuelcas el contenido del
string
en un stream de tipo istringstream
- Lees el contenido del stream con el operador de extracción (extraes cada palabra de la frase)
Dicho con código:
std::string sentence;
std::getline(std::cin, sentence);
std::istringstream iss(sentence);
std::string word;
while( iss >> word )
{
std::cout << word << '\n';
}
también me gustaría saber si se puede transformar un char en char[]
Eso sería como decir que te gustaría convertir un ladrillo en una casa. char[]
es un array, donde cada elemento de ese array es de tipo char
, luego no, no es posible convertir un elemento simple en una colección de elmentos simples.
Otra cosa es que estés mezclando conceptos y que tu intención sea copiar el contenido de ingreso
en ingreso2
. En este caso ambas variables tendrían que ser arrays de caracteres. Bajo estas condiciones, para copiar el contenido tendrías que llamar a funciones heredadas de C, como strcpy
char ingreso[21]; // <<--- no olvides la longitud del array
char ingreso2[21];
strcpy(intreso2, ingreso);
Claro que, por otro lado, el código sería más legible si usases std::string
en vez de elementos heredados de C:
std::string ingreso;
std::string ingreso2;
ingreso2 = ingreso; // <<--- Esto ahora si funciona
Uno de los problemas es que no se puede utilizar string.h
o cualquier clase de string
Bueno, en ese caso te toca implementar las funciones strlen
y strtok
a mano... tampoco son nada del otro mundo:
La función strlen
tiene que devolver el número de caracteres de una cadena de texto dada. Sabemos que hemos llegado al final de la cadena cuando encontramos el caracter nulo:
size_t strlen(char const* ptr)
{
size_t toReturn;
for( toReturn = 0; *ptr != '\0'; ++ptr, ++toReturn );
return toReturn;
}
Claro que también se puede sacar con aritmética de punteros:
size_t strlen(char const* ptr)
{
char const* end = ptr;
for( end = ptr; *end != '\0'; ++end );
return ptr - end;
}
La función strtok
es un poco más compleja, pero no mucho. Utiliza un puntero interno para poder trocear la cadena:
char* strtok(char * cadena, char const* delimitadores)
{
static char* ptr = nullptr;
if( cadena != nullptr )
ptr = cadena;
char* toReturn = ptr;
for( char* ptr2 = ptr; ; ++ptr2 )
{
if( *ptr2 == '\0' )
{
ptr = ptr2;
break;
}
bool is_delim = false;
for( char const* delim = delimitadores; *delim != '\0'; ++delim )
is_delim |= *delim == *ptr2;
if( is_delim )
{
*ptr2 = '\0';
ptr = ptr2 + 1;
break;
}
}
return toReturn;
}