reves - Invertir una cadena, salida extraña c++
invertir una cadena en c++ recursivo (6)
while (&str+n >= &str){
Esto es una tontería, quieres simplemente
while (n >= 0) {
y
str2[i] = *(str+n);
debería ser mucho más legible
str2[i] = str[n];
Está bien, entonces estoy tratando de invertir una cadena de estilo C en C ++, y estoy llegando a una salida extraña. Tal vez alguien puede arrojar algo de luz?
Aquí está mi código:
int main(){
char str[] = "string";
int strSize = sizeof(str)/sizeof(char);
char str2[strSize];
int n = strSize-1;
int i =0;
while (&str+n >= &str){
str2[i] = *(str+n);
n--;
i++;
}
int str2size = sizeof(str)/sizeof(char);
int x;
for(x=0;x<str2size;x++){
cout << str2[x];
}
}
La idea básica aquí es simplemente hacer un puntero apuntando al final de la cadena, y luego leerlo hacia atrás en una nueva matriz usando la aritmética del puntero.
En este caso particular, obtengo una salida de: "gnirts" ¿Hay un espacio molesto al comienzo de cualquier salida que asumo es el carácter nulo? Pero cuando trato de deshacerme de él disminuyendo la variable strSize para excluirlo, termino con otro personaje en el extremo opuesto de la cadena probablemente desde otro bloque de memoria.
¿Alguna idea sobre cómo evitar esto? PD: (¿Podrían considerar esto una buena idea para invertir una cadena?)
@ildjarn y @Blastfurnace ya dieron buenas ideas, pero creo que daría un paso más y usaría los iteradores para construir la cadena invertida:
std::string input("string");
std::string reversed(input.rbegin(), input.rend());
std::cout << reversed;
Dejaría que la biblioteca estándar de C ++ hiciera más del trabajo ...
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
typedef std::reverse_iterator<char const*> riter_t;
char const str[] = "string";
std::size_t const strSize = sizeof(str);
char str2[strSize] = { };
std::copy(riter_t(str + strSize - 1), riter_t(str), str2);
std::cout << str2 << ''/n'';
}
Hay un algoritmo en la biblioteca estándar para invertir una secuencia. ¿Por qué reinventar la rueda?
#include <algorithm>
#include <cstring>
#include <iostream>
int main()
{
char str[] = "string";
std::reverse(str, str + strlen(str)); // use the Standard Library
std::cout << str << ''/n'';
}
Su condición de bucle while (&str+n >= &str)
es equivalente a (n >= 0)
.
Su *(str+n)
es equivalente a str[n]
y yo prefiero este último.
Como dijo HappyPixel, debe comenzar n
en strSize-2
, por lo que el primer carácter copiado será el último carácter real de str, no el carácter de terminación nula de str.
Luego, después de haber copiado todos los caracteres regulares en el ciclo, necesita agregar un carácter de terminación nulo al final de str2
usando str2[strSize-1] = 0;
.
Aquí hay un código de trabajo fijo que genera "gnirts":
#include <iostream>
using namespace std;
int main(int argc, char **argv){
char str[] = "string";
int strSize = sizeof(str)/sizeof(char);
char str2[strSize];
int n = strSize-2; // Start at last non-null character
int i = 0;
while (n >= 0){
str2[i] = str[n];
n--;
i++;
}
str2[strSize-1] = 0; // Add the null terminator.
int str2size = sizeof(str)/sizeof(char);
int x;
cout << str2;
}
Una cadena válida debe ser terminada por un carácter nulo. Por lo tanto, debe mantener el carácter nulo en su posición original (al final de la cadena) y solo invertir los caracteres que no son nulos. Entonces tendrías algo como esto:
str2[strSize - 1] = str[strSize - 1]; // Copy the null at the end of the string
int n = strSize - 2; // Start from the penultimate character