Seguimos buscando a Arshak. Ayudanos compartiendo!
Encuesta no oficial de docentes
Resultados de la encuesta no oficial de docentes
Probaste el SIGA Helper?

Donar $100 Donar $200 Donar $500 Donar mensualmente


Enviar respuesta 
 
Calificación:
  • 0 votos - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Buscar en el tema
Ejercicio 4 del tp de strings (ayuda)
Autor Mensaje
Gonsha Sin conexión
Presidente del CEIT
Wub Wub Nation
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.491
Agradecimientos dados: 166
Agradecimientos: 693 en 49 posts
Registro en: Mar 2012
Mensaje: #1
Ejercicio 4 del tp de strings (ayuda) Ejercicios Informática I (Electrónica)
Hola gente, como va?

Bueno aca estoy teniendo un problema con el ejercicio 4 de la guia de strings que dice:

"Escribir una función que reciba como argumento puntero a char, la asuma como
una secuencia en ASCII terminada en '\0' (NULL) y devuelva la secuencia
invertida.

void string_reverse (char *)"


Yo lo hice asi:

http://www.copiatelo.com/index.php?show=m19bc71d6

Pero evidentemente no funciona. Creo que estoy fallando a la hora de querer volver el puntero a la primera posicion de la cadena donde almaceno mi palabra (cadena "palabra") en la linea 36.

Muchas gracias, saludos!

[Imagen: tumblr_mram6vK6161rxdmpio1_400.gif]
(Este mensaje fue modificado por última vez en: 01-09-2013 18:11 por Gonsha.)
01-09-2013 18:06
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonza87 Sin conexión
Empleado de Fotocopiadora
Sin estado :(
**

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 41
Agradecimientos dados: 8
Agradecimientos: 17 en 12 posts
Registro en: Dec 2008
Mensaje: #2
RE: Ejercicio 4 del tp de strings (ayuda)
(01-09-2013 18:06)Gonsha escribió:  Hola gente, como va?

Bueno aca estoy teniendo un problema con el ejercicio 4 de la guia de strings que dice:

"Escribir una función que reciba como argumento puntero a char, la asuma como
una secuencia en ASCII terminada en '\0' (NULL) y devuelva la secuencia
invertida.

void string_reverse (char *)"


Yo lo hice asi:

http://www.copiatelo.com/index.php?show=m19bc71d6

Pero evidentemente no funciona. Creo que estoy fallando a la hora de querer volver el puntero a la primera posicion de la cadena donde almaceno mi palabra (cadena "palabra") en la linea 36.

Muchas gracias, saludos!

El tema es que estás perdiendo la posición.

Al avanzar con el puntero original estás perdiendo la primera posición y luego estás asignando, o queriendo asignar la primer pos de algo que ya perdió.
Creo que había un par de estrategias distintas para solucionar esto, podrías usar un puntero auxiliar para recorrer tu string y así contar la cantidad de posiciones.
01-09-2013 18:48
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonsha Sin conexión
Presidente del CEIT
Wub Wub Nation
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.491
Agradecimientos dados: 166
Agradecimientos: 693 en 49 posts
Registro en: Mar 2012
Mensaje: #3
RE: Ejercicio 4 del tp de strings (ayuda)
Puede ser, no se. De todas formas corregi el programa y quite el algoritmo de contar la cantidad de palabras, y lo reemplaze por la funcion "strlen" (el enunciado en ningun momento dice que no se puede utilizar). Pero aun asi, el programa no funciona.

[Imagen: tumblr_mram6vK6161rxdmpio1_400.gif]
01-09-2013 18:50
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonza87 Sin conexión
Empleado de Fotocopiadora
Sin estado :(
**

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 41
Agradecimientos dados: 8
Agradecimientos: 17 en 12 posts
Registro en: Dec 2008
Mensaje: #4
RE: Ejercicio 4 del tp de strings (ayuda)
(01-09-2013 18:50)Gonsha escribió:  Puede ser, no se. De todas formas corregi el programa y quite el algoritmo de contar la cantidad de palabras, y lo reemplaze por la funcion "strlen" (el enunciado en ningun momento dice que no se puede utilizar). Pero aun asi, el programa no funciona.

Ahora sí, con la cuestión esa no presté atención a como estabas asignando los caracteres al vector:

Ponelo así
//ojo con la posición cero del vector (lo pongo explicito)
cant_posiciones = cant_posiciones-1

while (*palabra != NULL) {
auxiliar [cant_posiciones - posicion] = *palabra;
palabra ++;
posicion ++;
}

Le asignás el contenido del puntero. Se pueden manejar los punteros como arrays pero entonces tendrías que fijarte lo que le querés mandar es un char solo.

Slds
01-09-2013 19:06
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Maik Sin conexión
Presidente del CEIT
.
********

Otra
Otra

Mensajes: 5.353
Agradecimientos dados: 47
Agradecimientos: 197 en 141 posts
Registro en: Sep 2011
Mensaje: #5
RE: Ejercicio 4 del tp de strings (ayuda)
fijate que la funcion "ejercicio 4" no devuelve nada.

""Escribir una función que reciba como argumento puntero a char, la asuma como una secuencia en ASCII terminada en '\0' (NULL) y devuelva la secuencia invertida."


usa strlen.
una vez que obtenes el largo del string tenes dos variables, el contador "i" y "largodelstring".
como hizo gonza87

MODS
[Imagen: 2r5t075.jpg]
01-09-2013 19:21
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonsha Sin conexión
Presidente del CEIT
Wub Wub Nation
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.491
Agradecimientos dados: 166
Agradecimientos: 693 en 49 posts
Registro en: Mar 2012
Mensaje: #6
RE: Ejercicio 4 del tp de strings (ayuda)
Hora me funciona "Bien", pero no se como meter el null al final. Creo que por eso es que cuando me invierte la cadena, al comienzo me pone un caracter raro. Tenes idea que puede ser?

(01-09-2013 19:21)Maik escribió:  fijate que la funcion "ejercicio 4" no devuelve nada.

""Escribir una función que reciba como argumento puntero a char, la asuma como una secuencia en ASCII terminada en '\0' (NULL) y devuelva la secuencia invertida."


usa strlen.
una vez que obtenes el largo del string tenes dos variables, el contador "i" y "largodelstring".
como hizo gonza87

Como haria para devolver la cadena?

[Imagen: tumblr_mram6vK6161rxdmpio1_400.gif]
(Este mensaje fue modificado por última vez en: 01-09-2013 19:30 por Gonsha.)
01-09-2013 19:22
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Maik Sin conexión
Presidente del CEIT
.
********

Otra
Otra

Mensajes: 5.353
Agradecimientos dados: 47
Agradecimientos: 197 en 141 posts
Registro en: Sep 2011
Mensaje: #7
RE: Ejercicio 4 del tp de strings (ayuda)
ni me acuerdo xD

podes devolver el puntero.

acordate de agregar el /null al final.

MODS
[Imagen: 2r5t075.jpg]
01-09-2013 19:33
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonsha Sin conexión
Presidente del CEIT
Wub Wub Nation
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.491
Agradecimientos dados: 166
Agradecimientos: 693 en 49 posts
Registro en: Mar 2012
Mensaje: #8
RE: Ejercicio 4 del tp de strings (ayuda)
(01-09-2013 19:33)Maik escribió:  ni me acuerdo xD

podes devolver el puntero.

acordate de agregar el /null al final.

Y se pero no se como agregarlo, por eso lo pregunte antes xd. Deberia devolver el puntero a la primera posicion de mi cadena "auxiliar" pero no se como hacerlo xd.

[Imagen: tumblr_mram6vK6161rxdmpio1_400.gif]
01-09-2013 19:34
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Maik Sin conexión
Presidente del CEIT
.
********

Otra
Otra

Mensajes: 5.353
Agradecimientos dados: 47
Agradecimientos: 197 en 141 posts
Registro en: Sep 2011
Mensaje: #9
RE: Ejercicio 4 del tp de strings (ayuda)
seria algo asi como "return (*string)"

y cuando llamas a la funcion

stringdadovuelta[0] = ejercicio4 (*cadenadato)


pero ni me acuerdo. google->!

MODS
[Imagen: 2r5t075.jpg]
01-09-2013 19:40
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonsha Sin conexión
Presidente del CEIT
Wub Wub Nation
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.491
Agradecimientos dados: 166
Agradecimientos: 693 en 49 posts
Registro en: Mar 2012
Mensaje: #10
RE: Ejercicio 4 del tp de strings (ayuda)
Maik en la guia de TP's dicen que el prototipo de la func debe ser:

void string_reverse (char *)

Asique no devuelve nada. Esta mal redactado =P.

[Imagen: tumblr_mram6vK6161rxdmpio1_400.gif]
01-09-2013 19:57
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Fabiancho Sin conexión
Empleado de Fotocopiadora

**

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 47
Agradecimientos dados: 3
Agradecimientos: 7 en 7 posts
Registro en: Oct 2011
Facebook
Mensaje: #11
RE: Ejercicio 4 del tp de strings (ayuda)
No es que no devuelve nada, la idea del proceso que tenes que hacer es esta:

suponete que a la variable "cad" le asignas "hola mundo"
cuando ejecutas el proceso string_reverse (cad)
el valor de cad deberia quedar en "odnum aloh"

No esta mal redactado
01-09-2013 20:45
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
sacros Sin conexión
Profesor del Modulo A
<img src=x onerror="al...
*****

Otra
Facultad Regional Buenos Aires

Mensajes: 246
Agradecimientos dados: 94
Agradecimientos: 68 en 26 posts
Registro en: Nov 2010
Mensaje: #12
RE: Ejercicio 4 del tp de strings (ayuda)
Hola, vengo a contribuir con una solucion *carlitox*



#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define N 50

void invertir_cadena(char *cadena)
{
int i, longitud = strlen(cadena) - 1;
char *cadena_auxiliar = strdup(cadena);

//hasta que no cubramos la longitud, copiamos del final de la cadena auxiliar en la cadena
for(i = 0; i <= longitud; i++)
cadena[i] = cadena_auxiliar[longitud-i];

free(cadena_auxiliar);
}

int main(void)
{
char cadena[N] = "devolveme invertida, guachin!";

printf("\n La cadena: \"%s\" \n", cadena); //mostramos la cadena

invertir_cadena(cadena); //llamamos a la función del ejercicio

printf("\n Invertida es: \"%s\" \n\n", cadena); //la mostramos invertida, magia

return EXIT_SUCCESS;
}



En una de esas si lo mirás un toque te podes ahorrar alguna línea mas.

EDIT: En tu codigo el problema es que cuando terminas de contar las posiciones, como el operador ++ tiene efecto de lado, tu palabra queda sobre el \0 final
osea, nunca estas entrando al while que copia en la auxiliar, y te queda que al final la auxiliar tambien es solamente \0 (no muestra nada)
lo primero que se me ocurre para resolverlo es guardarte la direccion de memoria de la palabra antes de contar las posiciones y despues reestablecerlo
(Este mensaje fue modificado por última vez en: 01-09-2013 21:48 por sacros.)
01-09-2013 21:13
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Desert69 Sin conexión
Presidente del CEIT
Sin estado :( / "Anarquia...
********

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 2.477
Agradecimientos dados: 230
Agradecimientos: 345 en 206 posts
Registro en: Jun 2008
Mensaje: #13
RE: Ejercicio 4 del tp de strings (ayuda)
Gon, todavía no leí tu código, sólo leí "por arriba" lo que hablaron en este thread. BTW, ¿es el mismo ejercicio que me habías mandado antes o es distinto? Así busco el otro si hiciera falta =P


Primero pensemos qué tenemos que hacer, después cómo lo haríamos, y después tratemos de escribir ese cómo. Lo interesante de esto es ir avanzando de a poco en los constraints de la solución, cosa de empezar "en un mundo ideal" para que la propuesta de solución sea lo más "pura" posible, y de a poco ir afeándola (siempre lo menos posible) hasta terminar en algo compilable y ejecutable. Si arrancamos pensando en las restricciones del lenguaje y en detalles, vamos como "perdiendo el foco".

--------------------------------

El enunciado pide definir string_reverse(), que recibe un string (osea, una lista de chars terminada por un caracter especial - \0), y que debe devolver ese mismo string pero dado vuelta. Algunos posibles casos de ejemplo (test cases, que le llaman) sería hacer que "Hola, mundo!" se convierta en "!odnum ,aloH", "meh" se convierta en "hem", "a" se convierta en "a" y "" se convierta en "" (el string vacío).


Si nuestro string es una lista de caracteres, eso significa que tienen un orden. Digamos, "hola" no es lo mismo que "olah": está compuesta por los mismos caracteres, pero el orden es distinto. Entonces, si hay un orden, podríamos decir que cada caracter tiene un número de orden (lo que se llama "índice" o "index" en inglés). Como sabemos que estamos en C y son todos hippies locos, vamos a empezar indexando por el 0: en "hola", la "h" ocupa la posición 0, la primer "o" está en la posición 1, y la a está en la posición 3. Mirando un poco lo que deseamos conseguir ("aloh"), vemos que la posición 0 la ocupa la "a", que antes ocupaba la posición 3 (la última), mientras que la "h" ahora está en la posición 3 (última), siendo que antes era la primera. Siguiendo un poco más, si nuestro string fuera "warhola", al darla vuelta la última "a" volvería a estar en la primer posición, y la "w" pasa a la última, que en este caso es la 6. ¿Qué cambió entre una y otra palabra para que la primer letra del string original pase a estar en otra posición del resultado? Claro que sí: cambió la longitud de la palabra.

Entonces, analizando todos estos strings, encontramos más o menos una regla "invariante": cada caracter pasa a estar en la posición longitudDeLaPalabra - posicionEnLaOriginal - 1 (el menos 1 es porque pasamos de ordinales a cardinales, o como carajo se llamaran los otros). Así, en "hola"->"aloh", longitudDeLaPalabra es 4, y, por ejemplo, para la "h" tenemos posicionEnLaOriginal 0 => posición final es 3 (4 - 0 - 1). Y funciona para todas las letras. Fiesta.

¿Y con la "a"? Bueno, la longitud es 1, y la posicion original es 0: 1 - 0 - 1 = 0 => la "a" va en la posición 0. ¿Tiene sentido, no?

¿Y si es ""? Buen, je, ahí nos cabe un poco. Con longitud 0, 0 - 0 - 1 daría -1, puaj. Peeeeero, podemos usar como caso "extraño" esto de que la longitud es 0, y hacer que para esos strings no hagamos nada (vamos, el único string con longitud 0 es el vacío, y si está vacío no tenemos nada para hacer).


Volviendo a alto nivel, tenemos que devolver un nuevo string. Como el tamaño es variable, ese string lo vamos a reservar en memoria dinámica (además, necesitamos que siga siendo visible después de que finalize nuestra función).

Entonces nuestra función va a reservar un cacho'e memoria, y escribir ahí uno por uno los caracteres que vienen de la otra, leyendolos según la regla loca esta que inventamos.


Y sólo nos queda un detalle: los \0. TODOS los strings tienen que terminar en \0. En C el "hola" es en realidad un "hola\0". Y ese \0 no queremos darlo vuelta: "hola\0" pasa a ser "aloh\0", y no "\0aloh". Entonces, cuando nos llegue un string, su longitud no va a ser contando incluso el byte del \0 para nuestra fórmula loca, pero sí vamos a tener que tenerlo en cuenta para reservar su memoria (si para "hola\0" sólo reservamos 4 bytes, cuando querramos escribir el \0 del final vamos a hacer cagadas, y no tener un \0 al final va a ser incluso peor, porque nuestro resultado no va a ser un string - será sólo un stream, y cualquier función que espere un string va a reventar, potencialmente).



Ya definimos todo. Emepecemos a escribir C.

Lo primero, el prototipo de nuestra función: recibe un string, y devuelve otro.


char *string_reverse(char *source) {
// TODO: implementar
}


Ahora, necesitaríamos reservar el lugar en que vamos a escribir. Para poder hacerlo, primero tenemos que saber cuántos bytes necesitamos reservar. Consigamos la longitud del string:


#include <string.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
// TODO: implementar
}


strlen() da la longitud del string, por lo que no cuenta el \0. Es lo que definimos antes como longitudDeLaPalabra (que no es una única palabra en realidad, ja). Ahora sí, reservemos el lugar:


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
// TODO: implementar
}


Pedimos un byte más que la longitud del texto porque necesitamos el \0 como terminador (string vs stream, bleh).

Y, ahora, empecemos a escribir. Tendriamos que ir caracter por caracter, copiando de a uno según la fórmula que dimos. Como sabemos hasta qué longitud contar, usemos un for para ir variando un índice nuestro:


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
for(int target_index = 0; target_index < text_length; target_index++) {
// TODO: implementar
}
// TODO: implementar
}


Ese for dice "por cada índice entre 0 y text_length". ¿Qué tenemos que hacer por cada uno de esos? ¡Copiar el caracter correspondiente!


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
for(int target_index = 0; target_index < text_length; target_index++) {
reversed[target_index] = source[text_length - target_index - 1];
}
// TODO: implementar
}


En cada posición, metemos el caracter que estaba en la posición que calculamos con la fórmula.

¿Y ahora qué nos falta? ¡El \0, claro! Y ya que estamos, devolvemos nuestro string (hacer esto en dos pasos ya daba paja).


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
for(int target_index = 0; target_index < text_length; target_index++) {
reversed[target_index] = source[text_length - target_index - 1];
}
reversed[text_length] = \0;
return reversed;
}


¡Fiesta! ¡Terminamos!

[Imagen: internet-meme1365367926-291x375.jpg]

"¿Y eso del string vacío?"

Bueno, medio que viene gratis el asunto. Pensemos que con el string vacío, text_length va a valer 0. En ese caso, el malloc va a de ser de un byte, y la condición del for va a fallar de entrada (target_index 0 no es menor que text_length 0). Entonces, nunca se ejecuta la instrucción dentro del for, y luego en reversed[0] se pone un \0 y se devuelve. Es tal cual lo que queríamos.

"Che, pero, si recibo un string vacío, por qué no devolver el mismo source y ahorrarme un byte de memoria?"

Bueno, sí, podría interesarnos eso, pero hay un problema: el contrato de nuestra función dice que devuelve un nuevo string, porque otra no nos queda (tenemos que reservar nosotros el espacio para ese string, porque sería feo que nos lo manden desde afuera). Entonces, eso significa que quien la use ya sabe que estamos haciendo un malloc(), y que va a ser él el responsable de hacer el free() correspondiente en algún momento (porque nosotros perdemos el control después de devolverlo). Entonces, si para el caso del string vacío devolvieramos el string source, cuando le quieran hacer free() estamos dando lugar a que se rompa todo (porque source era una constante, o porque ya le estaban haciendo el free() a source y terminan haciendo un doble free()). Por eso, si el contrato dice que devolvemos un nuevo string, ****siempre**** devolvamos un nuevo string.



--------------

That's it =)

Cualquier cosa, chifle nomás.

PD: viendo la solución carlitox, usar strdup() es un pequeño hackcito para resolver lo del strlen() + malloc() (igual, no crean que va a hacer algo distinto a eso la función, je =)). Por otro lado, tanto el enunciado que escribiste como la solución de carlitox dicen que la función devuelve void. En ese caso, se contradice con lo de que "devuelve el string cambiado". Más bien sería "cambia el string parámetro", no devuelve nada.

Si ese fuera el caso, la solución esa está bastante bien...

[Imagen: a2.php]
[Imagen: 971aa6599664453c05cb3e42d58bbc0eo.jpg]
(Este mensaje fue modificado por última vez en: 01-09-2013 22:13 por Desert69.)
01-09-2013 22:09
Visita su sitio web Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
sacros Sin conexión
Profesor del Modulo A
<img src=x onerror="al...
*****

Otra
Facultad Regional Buenos Aires

Mensajes: 246
Agradecimientos dados: 94
Agradecimientos: 68 en 26 posts
Registro en: Nov 2010
Mensaje: #14
RE: Ejercicio 4 del tp de strings (ayuda)
el enunciado dice que el prototipo es: void string_reverse(char *); entre la ambiguedad de la palabra "devuelve" y el prototipo me quedo con el prototipo

no creo que los profes prohiban el uso de las funciones del standard, no seria muy inteligente, para que vamos a enseñarle a los pibes a no reutilizar codigo?
(Este mensaje fue modificado por última vez en: 01-09-2013 22:28 por sacros.)
01-09-2013 22:21
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Gonsha Sin conexión
Presidente del CEIT
Wub Wub Nation
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.491
Agradecimientos dados: 166
Agradecimientos: 693 en 49 posts
Registro en: Mar 2012
Mensaje: #15
RE: Ejercicio 4 del tp de strings (ayuda)
(01-09-2013 22:09)Desert69 escribió:  Gon, todavía no leí tu código, sólo leí "por arriba" lo que hablaron en este thread. BTW, ¿es el mismo ejercicio que me habías mandado antes o es distinto? Así busco el otro si hiciera falta =P


Primero pensemos qué tenemos que hacer, después cómo lo haríamos, y después tratemos de escribir ese cómo. Lo interesante de esto es ir avanzando de a poco en los constraints de la solución, cosa de empezar "en un mundo ideal" para que la propuesta de solución sea lo más "pura" posible, y de a poco ir afeándola (siempre lo menos posible) hasta terminar en algo compilable y ejecutable. Si arrancamos pensando en las restricciones del lenguaje y en detalles, vamos como "perdiendo el foco".

--------------------------------

El enunciado pide definir string_reverse(), que recibe un string (osea, una lista de chars terminada por un caracter especial - \0), y que debe devolver ese mismo string pero dado vuelta. Algunos posibles casos de ejemplo (test cases, que le llaman) sería hacer que "Hola, mundo!" se convierta en "!odnum ,aloH", "meh" se convierta en "hem", "a" se convierta en "a" y "" se convierta en "" (el string vacío).


Si nuestro string es una lista de caracteres, eso significa que tienen un orden. Digamos, "hola" no es lo mismo que "olah": está compuesta por los mismos caracteres, pero el orden es distinto. Entonces, si hay un orden, podríamos decir que cada caracter tiene un número de orden (lo que se llama "índice" o "index" en inglés). Como sabemos que estamos en C y son todos hippies locos, vamos a empezar indexando por el 0: en "hola", la "h" ocupa la posición 0, la primer "o" está en la posición 1, y la a está en la posición 3. Mirando un poco lo que deseamos conseguir ("aloh"), vemos que la posición 0 la ocupa la "a", que antes ocupaba la posición 3 (la última), mientras que la "h" ahora está en la posición 3 (última), siendo que antes era la primera. Siguiendo un poco más, si nuestro string fuera "warhola", al darla vuelta la última "a" volvería a estar en la primer posición, y la "w" pasa a la última, que en este caso es la 6. ¿Qué cambió entre una y otra palabra para que la primer letra del string original pase a estar en otra posición del resultado? Claro que sí: cambió la longitud de la palabra.

Entonces, analizando todos estos strings, encontramos más o menos una regla "invariante": cada caracter pasa a estar en la posición longitudDeLaPalabra - posicionEnLaOriginal - 1 (el menos 1 es porque pasamos de ordinales a cardinales, o como carajo se llamaran los otros). Así, en "hola"->"aloh", longitudDeLaPalabra es 4, y, por ejemplo, para la "h" tenemos posicionEnLaOriginal 0 => posición final es 3 (4 - 0 - 1). Y funciona para todas las letras. Fiesta.

¿Y con la "a"? Bueno, la longitud es 1, y la posicion original es 0: 1 - 0 - 1 = 0 => la "a" va en la posición 0. ¿Tiene sentido, no?

¿Y si es ""? Buen, je, ahí nos cabe un poco. Con longitud 0, 0 - 0 - 1 daría -1, puaj. Peeeeero, podemos usar como caso "extraño" esto de que la longitud es 0, y hacer que para esos strings no hagamos nada (vamos, el único string con longitud 0 es el vacío, y si está vacío no tenemos nada para hacer).


Volviendo a alto nivel, tenemos que devolver un nuevo string. Como el tamaño es variable, ese string lo vamos a reservar en memoria dinámica (además, necesitamos que siga siendo visible después de que finalize nuestra función).

Entonces nuestra función va a reservar un cacho'e memoria, y escribir ahí uno por uno los caracteres que vienen de la otra, leyendolos según la regla loca esta que inventamos.


Y sólo nos queda un detalle: los \0. TODOS los strings tienen que terminar en \0. En C el "hola" es en realidad un "hola\0". Y ese \0 no queremos darlo vuelta: "hola\0" pasa a ser "aloh\0", y no "\0aloh". Entonces, cuando nos llegue un string, su longitud no va a ser contando incluso el byte del \0 para nuestra fórmula loca, pero sí vamos a tener que tenerlo en cuenta para reservar su memoria (si para "hola\0" sólo reservamos 4 bytes, cuando querramos escribir el \0 del final vamos a hacer cagadas, y no tener un \0 al final va a ser incluso peor, porque nuestro resultado no va a ser un string - será sólo un stream, y cualquier función que espere un string va a reventar, potencialmente).



Ya definimos todo. Emepecemos a escribir C.

Lo primero, el prototipo de nuestra función: recibe un string, y devuelve otro.


char *string_reverse(char *source) {
// TODO: implementar
}


Ahora, necesitaríamos reservar el lugar en que vamos a escribir. Para poder hacerlo, primero tenemos que saber cuántos bytes necesitamos reservar. Consigamos la longitud del string:


#include <string.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
// TODO: implementar
}


strlen() da la longitud del string, por lo que no cuenta el \0. Es lo que definimos antes como longitudDeLaPalabra (que no es una única palabra en realidad, ja). Ahora sí, reservemos el lugar:


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
// TODO: implementar
}


Pedimos un byte más que la longitud del texto porque necesitamos el \0 como terminador (string vs stream, bleh).

Y, ahora, empecemos a escribir. Tendriamos que ir caracter por caracter, copiando de a uno según la fórmula que dimos. Como sabemos hasta qué longitud contar, usemos un for para ir variando un índice nuestro:


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
for(int target_index = 0; target_index < text_length; target_index++) {
// TODO: implementar
}
// TODO: implementar
}


Ese for dice "por cada índice entre 0 y text_length". ¿Qué tenemos que hacer por cada uno de esos? ¡Copiar el caracter correspondiente!


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
for(int target_index = 0; target_index < text_length; target_index++) {
reversed[target_index] = source[text_length - target_index - 1];
}
// TODO: implementar
}


En cada posición, metemos el caracter que estaba en la posición que calculamos con la fórmula.

¿Y ahora qué nos falta? ¡El \0, claro! Y ya que estamos, devolvemos nuestro string (hacer esto en dos pasos ya daba paja).


#include <string.h>
#include <stdlib.h>

char *string_reverse(char *source) {
size_t text_length = strlen(source);
char *reversed = malloc(text_length + 1);
for(int target_index = 0; target_index < text_length; target_index++) {
reversed[target_index] = source[text_length - target_index - 1];
}
reversed[text_length] = \0;
return reversed;
}


¡Fiesta! ¡Terminamos!

[Imagen: internet-meme1365367926-291x375.jpg]

"¿Y eso del string vacío?"

Bueno, medio que viene gratis el asunto. Pensemos que con el string vacío, text_length va a valer 0. En ese caso, el malloc va a de ser de un byte, y la condición del for va a fallar de entrada (target_index 0 no es menor que text_length 0). Entonces, nunca se ejecuta la instrucción dentro del for, y luego en reversed[0] se pone un \0 y se devuelve. Es tal cual lo que queríamos.

"Che, pero, si recibo un string vacío, por qué no devolver el mismo source y ahorrarme un byte de memoria?"

Bueno, sí, podría interesarnos eso, pero hay un problema: el contrato de nuestra función dice que devuelve un nuevo string, porque otra no nos queda (tenemos que reservar nosotros el espacio para ese string, porque sería feo que nos lo manden desde afuera). Entonces, eso significa que quien la use ya sabe que estamos haciendo un malloc(), y que va a ser él el responsable de hacer el free() correspondiente en algún momento (porque nosotros perdemos el control después de devolverlo). Entonces, si para el caso del string vacío devolvieramos el string source, cuando le quieran hacer free() estamos dando lugar a que se rompa todo (porque source era una constante, o porque ya le estaban haciendo el free() a source y terminan haciendo un doble free()). Por eso, si el contrato dice que devolvemos un nuevo string, ****siempre**** devolvamos un nuevo string.



--------------

That's it =)

Cualquier cosa, chifle nomás.

PD: viendo la solución carlitox, usar strdup() es un pequeño hackcito para resolver lo del strlen() + malloc() (igual, no crean que va a hacer algo distinto a eso la función, je =)). Por otro lado, tanto el enunciado que escribiste como la solución de carlitox dicen que la función devuelve void. En ese caso, se contradice con lo de que "devuelve el string cambiado". Más bien sería "cambia el string parámetro", no devuelve nada.

Si ese fuera el caso, la solución esa está bastante bien...
Gracias desert, este era otro ejercicio, ya lo había hecho funcionar igual =). Lo de malloc me parece inútil igual, osea no tiene sentido acomplejar un problema tan sencillo.

Ahora volvete al otro thread el de listas y armate una respuesta similar porfa =P.

[Imagen: tumblr_mram6vK6161rxdmpio1_400.gif]
(Este mensaje fue modificado por última vez en: 02-09-2013 00:40 por Gonsha.)
02-09-2013 00:34
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Buscar en el tema
Enviar respuesta 




Usuario(s) navegando en este tema: 1 invitado(s)