[ Foro de C++ ]

entender fragmento de codigo

02-May-2013 11:47
Invitado (Daniel puyol)
7 Respuestas

hola a todos.
queria pedir ayuda en si me pueden explicar que hace el siguiente codigo:
char temp[100]
string s=string(gets(temp))
string pal[100],sim[100]
int uC=2,npal=-1,nsim=-1
for(int i=0;i<s.size();i++)
 if(s[i]==' '|| s[i]=='.')
  {
    if(uC==1)
     sim[nsim]+=s[i]
  }

reverse(pal,pal+npal+1)

no entiendo cosas como por que se hace inicializa una variable con signo negativo, como lo son: npal=-1,nsim=-1
y que hace o como opera la funcion reverse
agradeceria profesor si pudieras explicarmelo en detalle o en seudocodigo, gracias


02-May-2013 18:17
Nacho Cabanes (+84)

Ahí faltan algunas cosas para que se pueda entender. Como tú mismo dices, no aparece por ningún sitio lo que hace la función "reverse".

Una variable numérica se puede inicializar con valor negativo... según lo que quieras hacer con ella. Pero los nombres son tan poco claros que no es evidente lo que pretende. Quizá "npal" sea la abreviatura de "numeroDePalabras" y "nsim" sea la de "numeroDeSimbolos", y su valor inicial sea -1 para indicar que no hay ninguna palabra ni ningún símbolo..

Pero todo son "quizás". ¿Dónde están los puntos y coma? ¿Qué es la variable "uC"?  ¿Por qué empieza valiendo 2 y luego se comprueba si vale 1? Ante un programa como ese, que no tiene comentarios y que tiene variables con nombres tan poco aclaradores, no hay más remedio que preguntar a su autor original, o buscar otro algoritmo alternativo, o desarrollarlo tú mismo.


05-May-2013 23:33
Invitado (Daniel puyol)

hola profesor, gracias por tu ayuda.
te dejo el codigo completo que encontre en el libro y lo probe y me funciona ok en c++, entendiendo ahora en ejecucion mas no en el codigo como tal lo que realiza.
con un ejemplo como aparecia:
Hola,Maria.Como estas.

en ejecucion el resultado es el siguiente:
estas,Como.Maria Hola.

como ves invierte las palabras de una frase que contiene simbolos sin que estos ultimos cambien su posicion inicial dentro de la frase.


el codigo el cual por favor te pido tu ayuda para entenderlo en su totalidad pues mi idea es aprender.


#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
 main()
 {
     char temp[200];
     string s=string(gets(temp));
     string pal[100],sim[100];
     int uc=2,npal=-1,nsim=-1;
     
     for (int i=0;i<s.size();i++)
      if (s[i]==' ' || s[i]==',' || s[i]=='.')
       {
           if(uc==1)
            {
              sim[nsim]+=s[i];
             
            }
            else
             {
              sim[++nsim]=s[i];
             }
             uc=1;
        } 
        else
          {
              if (uc==0)
              {
                pal[npal]+=s[i];
               
                }
                else
                {
                 pal[++npal]=s[i];
              
                 }
                 uc=0;
                 }
         
         reverse(pal,pal+npal+1);
         
         for(int i=0;i<=npal;i++)
          cout<<pal[i]<<sim[i];
          cout<<endl;
          system("pause");
          }


         
si puedes ademas dame alternativas de mejora si las ves desde tu experiencia. mil gracias por atenderme.
saludos.


11-May-2013 00:33
Nacho Cabanes (+84)

Efectivamente, así se entiende un poco mejor, aunque los nombres de las variables no son los más adecuados. Básicamente, la idea es:

- Para cada símbolo tecleado
-- Si es un separador, guardar en el array de separadores
-- Si no, añadir a la palabra actual
- Finalmente, dar la vuelta al array de palabras
- Y mostrar cada palabra y su separador

Realmente es un poco más complejo, porque cuando hay un separador marca como terminada la palabra actual. Si tengo un respiro, lo intento reescribir de forma un poco más legible, usando "booleanos" y nombres de variable más descriptivos.


16-May-2013 15:09
Invitado (Daniel puyol)

cordial saludo profesor, gracias por responderme.
el algoritmo que me indicas lo comprendo lo que no entiendo ya dentro del codigo es el por que toman una variable u=2 y luego la disminuyen segun sea el if por donde entre, en el codigo a que haria referencia los if if(uc==1) y if(uc==0), es decir en que casos se entraria respectivamente dentro de ellos? ahora otra cosa que no entiendo es cuando dices:
Realmente es un poco más complejo, porque cuando hay un separador marca como terminada la palabra actual
a que te refieres con ello profesor, perdona mi ignorancia.
mil gracias por todo lo que puedas ayudarme


17-May-2013 09:56
Nacho Cabanes (+84)

Es que está programado "como a principios de los 80", usando variables con nombres muy cortos y (por tanto) poco claros, como si cada byte de memoria fuera un recurso valiosísimo.

A muchos programadores (o aspirantes) parece que se les olvida que un programa se escribe una única vez, pero se lee muchas, y suele ser mucho más costoso (en tiempo, y, por tanto en dinero) mantenerlo (corregir, ampliar) que escribirlo, así que hay que intentar que sea fácil de leer.

En este caso, sólo con cambiar los nombres de las variables y añadir algún comentario, el fuente sería mucho más fácil de leer:


#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

main()
{
    // Variables
    string palabras[100],simbolos[100];
    
    #define EN_PALABRA 0
    #define EN_SIMBOLO 1
    #define NO_COMENZADO 2
    int modo = NO_COMENZADO;
    
    int cantidadPalabras=-1;
    int cantidadSimbolos=-1;
    char textoTemporal[200];

    // Pido el texto al usuario    
    string texto=string(gets(textoTemporal));
        
    // Reviso toda la cadena, buscando separadores
    for (int i=0;i<texto.size();i++)
    {
        // Si es un separador
        if (texto[i]==' ' || texto[i]==',' || texto[i]=='.')
        {
            // Si estaba en símbolo, añado más caracteres
            if(modo == EN_SIMBOLO)
            {
                simbolos[cantidadSimbolos] += texto[i];
            }
            // Si no lo estaba, empiezo un símbolo nuevo
            else
            {
                simbolos[++cantidadSimbolos]=texto[i];
            }
            // Y supongo que seguiré comprobando el símbolo actual
            modo = EN_SIMBOLO;
        } 
        // Si no es separador
        else
        {
            // Si estaba en palabra, añado a ella
            if (modo == EN_PALABRA)
            {
                palabras[cantidadPalabras] += texto[i];
            }
            // Si no, empiezo una nueva
            else
            {
                palabras[++cantidadPalabras] = texto[i];
            }
            // Y supongo que seguiré comprobando la palabra actual
            modo = EN_PALABRA;
        }
    }

    // Doy la vuelta a la lista de palabras
    reverse(palabras,palabras+cantidadPalabras+1);

    // Y muestro palaras (invertidas) y separadores
    for(int i=0 ;i <= cantidadPalabras; i++)
        cout << palabras[i] << simbolos[i];
    cout << endl;
    
    // Finalmente, espero a que se pulse Intro
    system("pause");
}



Aun así, en este fuente quedan varias cosas que no me gustan, como la sintaxis tan poco natural que usa para "reverse", o el empezar a contar en -1 en vez de en 0, o el acceder a símbolos[i] cuando en general terminará en símbolos[i-1], pero bueno... espero que al menos te ayude a ver mejor la idea de cómo lo han resuelto.


17-May-2013 21:48
Invitado (Daniel puyol)

gracias profesor,por tu excelnte explicacion, ahora si que lo entiendo perfectamente, muchas gracias.
queria en ultima instancia al respecto preguntarte si hay alguna manera de hacer una funcion propia que pueda reemplazar la linea reverse(palabras,palabras+cantidadPalabras+1);
seria posible, me ayudaria mucho porque asi con esta funcion reverse no es que me aclare mucho respècto a que estoy intentando aprender funciones y esta parece que ta fuera propia del lenguaje, en lo que puedas ayudarme quedaria super satisfecho con el ejercicio.


18-May-2013 11:52
Nacho Cabanes (+84)

Claro que puedes hacerla tú. Primero crea una función que reciba un array, su tamaño y muestre su contenido al revés. Cuando lo consigas, no será mucho más difícil crear una nueva función que en vez de mostrarlo en pantalla lo vuelque a un nuevo array.







(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)