elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Sigue las noticias más importantes de seguridad informática en el Twitter! de elhacker.NET


  Mostrar Mensajes
Páginas: 1 ... 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ... 125
271  Programación / Programación C/C++ / Re: Problema guardando 2d arrays en binarios en: 5 Agosto 2014, 16:30 pm
Código
  1. int palabras_found=0;
  2.  
  3. // ...
  4.  
  5. arch.write((char *)palabras_found,sizeof(int));

¿por qué motivo tratas palabras_found como si fuese un puntero? Me da que no terminas de entender el significado y funcionamiento de los punteros.

En este caso concreto, "palabras_found" no es puntero, y dado que la función "write" necesita un puntero, lo que tienes que facilitarle a la función es la posición de memoria donde se encuentra "palabras_found", es decir:

Código
  1. arch.write((char *)&palabras_found,sizeof(int));

Lo que tu estabas almacenando antes en el fichero era guarrería... además le estabas dando al sistema operativo motivos más que suficientes para que matase tu programa por acceder a memoria que no le corresponde.
272  Programación / Programación C/C++ / Re: Espacios en concatenación strcat. en: 5 Agosto 2014, 13:23 pm
Que tal algo del tipo...

Código
  1. char buffer[ 100 ];
  2. strcat( buffer, "palabra1" );
  3. strcat( buffer, " " );
  4. strcat( buffer, "palabra2" );

Por cierto, esta línea, por ejemplo:

Código
  1. scanf ("%s",&pal);

Está mal... pal es de por sí un puntero, si pasas la referencia en vez del puntero vas a escribir donde no debes.

Además:

Código
  1. char cad[ 100 ];
  2. // ...
  3. strcat( cad, pal );

¿Dónde has inicializado "cad"?? strcat concatena a partir del final de cadena, es decir, de que encuentra el carácter nulo... si la cadena no está inicializada vas a tener basura y la función va a concatenar donde le de la gana... y seguro que no coincide con el sitio donde tú quieres que escriba.
273  Programación / Programación C/C++ / Re: Problema guardando 2d arrays en binarios en: 5 Agosto 2014, 11:20 am
No entiendo por qué aparecen lineas horizontales dentro del código... Qué debo hacer para hacerlo visible?

Para que el código aparezca "correcto" tienes que añadirle a la etiqueta "code" el lenguaje empleado:

code=cpp -> C++
code=c -> C
...

Si la etiquetas la dejas como "code" a secas al código se le da una interpretación que puede no ser la correcta... en tu caso [ s ] se está interpretando como texto tachado, por lo que te tacha todo lo que se encuentra entre esa etiqueta y la de cierre... que como no hay te tacha hasta el final del código.

No estoy muy seguro del código correspondiente a write y read

Código
  1. char sopa[20][20];
  2. arch.read(sopa[0], 20*20*sizeof(sopa));

Si sopa es un array bidimiensional... tu quieres sobreescribir dicho array al completo... ¿por qué accedes a sopa[0]? Si pretendes modificar "sopa"... el puntero que debes pasar es "sopa"... no "sopa[0]". Además, "20*20*sizeof(sopa)"... si sopa es un array de 20*20... entonces esa expresión es equivalente a "20*20*20*20*sizeof(char)"... y creo que no es tu intención leer semejante cantidad de información. Tienes que tener en cuenta que de la forma en la que has declarado el array, el compilador sabe en todo momento el tamaño de esa variable... que serán 400 bytes.

Dicho esto aquí tienes dos opciones:

Opción 1:

Código
  1. arch.read(sopa, sizeof(sopa));

Opción 2:

Código
  1. arch.read(sopa, 20*20*sizeof(char));

Yo, personalmente, prefiero la primera opción ya que si te da por cambiar el tamaño del array y te olvides de cambiar esta otra línea vas a tener errores en el código.

El resto de lecturas y escrituras presentan los mismos problemas.

Un saludo.
274  Programación / Programación C/C++ / Re: ayuda con registros y archivos .txt en C++ en: 4 Agosto 2014, 10:25 am
Si usas C++, mi consejo es que, salvo que sea una "obligación" o estés aprendiendo y quieras pasar por ello, tengas en cuenta lo siguiente:

No uses char* para la gestión de cadenas de texto. En su lugar usa la clase "string".

Porque es más bonito, más legible y da menos problemas esto:

Código
  1. std::string cadena = "algo";
  2. std::string otra_cadena = cadena;
  3.  
  4. cadena += "otra cosa";

que esto otro:

Código
  1. char cadena[ 40 ];
  2. char otra_cadena[ 40 ];
  3.  
  4. strcpy( cadena, "algo" );
  5. strcpy( otra_cadena, cadena );
  6.  
  7. strcat( cadena, "otra cosa" );

No uses variables globales, son más problemáticas de lo que te imaginas.

El problema de las variables globales es que no queda clara la forma en que se usan... además es fácil que puedan quedar "tapadas" por variables locales, lo que dificulta muchísimo la lectura del código y la búsqueda de errores. En serio, es mejor evitar las variables globales.

Puede que haya alguna rara excepción en la que sea mejor usarlas... pero no creo que te veas en esas mientras aprendes. Además siempre es mejor tener una clase estática o un singleton que tener variables globales.

Intenta marcarte una longitud máxima para cada línea de código.

Tener líneas de código con, por ejemplo 3000 caracteres no ayuda a que el código sea legible. Lo ideal es que el código entre en la pantalla sin necesidad de hacer scroll horizontal.

Antes, cuando los editores iban sobre shell, el límite aceptado eran 80 caracteres... hoy en día gracias a dios no hace falta ser tan estricto... pero aún así en serio, intenta evitar scroll horizontal en tu código:

Código
  1. // Linea dificil de leer
  2. cout<<"Usuario 1:"<<persona[1].cedula<<" , "<<persona[1].nombre<<" , "<<persona[1].correo<< " , "<<persona[1].telefono<<" , "<<persona[1].padres[1].cedula<<" , "<<persona[1].padres[1].nombre<<" , "<<persona[1].padres[1].cedula<<" , "<<persona[1].padres[1].nombre<<" , " <<endl;
  3.  
  4. // Linea mas legible
  5. cout << "Usuario 1:" << persona[1].cedula << " , "
  6.                     << persona[1].nombre << " , "
  7.                     << persona[1].correo << " , "
  8.                     << persona[1].telefono << " , "
  9.                     << persona[1].padres[1].cedula << " , "
  10.                     << persona[1].padres[1].nombre << " , "
  11.                     << persona[1].padres[1].cedula << " , "
  12.                     << persona[1].padres[1].nombre << " , " << endl;

Creo que la diferencia es evidente.

En C++ no uses includes de C

Los includes de la librería de C tienen TODOS el sufijo ".h", los includes de C++ carecen de dicho sufijo. Si en algún momento tienes que usar una función propia de C en C++, has de saber que estas funciones tienen un include tipo C++. Por ejemplo:

  • El include de math.h, en C++ es cmath
  • El include de stdio.h, en C++ es cstdio

Piensa que, aunque son compatibles, son lenguajes diferentes y no queda claro que vayan a ser compatibles eternamente... mejor diferenciar claramente cada lenguaje.

Tabula el codigo

Si todo el código es "plano", es decir, está todo al mismo nivel, resulta complicado saber qué código está dentro de un determinado bucle:

Código
  1. void func( )
  2. {
  3. int i=1, j=5;
  4. while(i++)
  5. {
  6. if (i==j)
  7. {
  8. std::cout << i << std::endl;
  9. j += 5;
  10. }
  11. if (i%30==0)
  12. {
  13. if (i==j)
  14. {
  15. std::cout << i << j << std::endl;
  16. }
  17. } // <<<
  18. }
  19. }

¿Está bien escrito el código de arriba?
¿A qué bucle o condición pertenece la llave que tiene el comentario?

Desde luego es complicado responder a estas preguntas sin estar un ratito mirando el código... sin embargo si tabulamos el código la cosa cambia:

Código
  1. void func( )
  2. {
  3.  int i=1, j=5;
  4.  while(i++)
  5.  {
  6.    if (i==j)
  7.    {
  8.      std::cout << i << std::endl;
  9.      j += 5;
  10.    }
  11.  
  12.    if (i%30==0)
  13.    {
  14.      if (i==j)
  15.      {
  16.        std::cout << i << j << std::endl;
  17.      }
  18.    } // <<<
  19.  }
  20. }

Ahora se entiende mejor, ¿no? pues eso mismo.

Intenta "abusar" de los bucles.

Un concepto básico de la programación es intentar reutilizar el código lo máximo posible (dentro, claro está, de unos límites aceptables).

En tu caso, estás sacando por pantalla 5 registros diferentes copiando, literalmente, el código 5 veces... si tienes un problema en ese código, o si necesitas hacer algún cambio, tendrás que aplicar el cambio 5 veces... lo cual es poco eficiente y bastante propenso a errores.

Para este tipo de tareas repetitivas se inventaron los bucles. Saca tus propias conclusiones:

Sin bucles:

Código
  1. cout<<"Usuario 1:"<<persona[1].cedula<<" , "<<persona[1].nombre<<" , "<<persona[1].correo<< " , "<<persona[1].telefono<<" , "<<persona[1].padres[1].cedula<<" , "<<persona[1].padres[1].nombre<<" , "<<persona[1].padres[1].cedula<<" , "<<persona[1].padres[1].nombre<<" , " <<endl;
  2. cout<<endl;
  3. cout<<"Usuario 2:"<<persona[2].cedula<<" , "<<persona[2].nombre<<" , "<<persona[2].correo<< " , "<<persona[2].telefono<<" , "<<persona[2].padres[2].cedula<<" , "<<persona[2].padres[2].nombre<<" , "<<persona[2].padres[2].cedula<<" , "<<persona[2].padres[2].nombre<<" , "<<endl;
  4. cout<<endl;
  5. cout<<"Usuario 3:"<<persona[3].cedula<<" , "<<persona[3].nombre<<" , "<<persona[3].correo<< " , "<<persona[3].telefono<<" , "<<persona[3].padres[3].cedula<<" , "<<persona[3].padres[3].nombre<<" , "<<persona[3].padres[3].cedula<<" , "<<persona[3].padres[3].nombre<<" , "<<endl;
  6. cout<<endl;
  7. cout<<"Usuario 4:"<<persona[4].cedula<<" , "<<persona[4].nombre<<" , "<<persona[4].correo<< " , "<<persona[4].telefono<<" , "<<persona[4].padres[4].cedula<<" , "<<persona[4].padres[4].nombre<<" , "<<persona[4].padres[4].cedula<<" , "<<persona[4].padres[4].nombre<<" , "<<endl;
  8. cout<<endl;
  9. cout<<"Usuario 5:"<<persona[5].cedula<<" , "<<persona[5].nombre<<" , "<<persona[5].correo<< " , "<<persona[5].telefono<<" , "<<persona[5].padres[5].cedula<<" , "<<persona[5].padres[5].nombre<<" , "<<persona[5].padres[5].cedula<<" , "<<persona[5].padres[5].nombre<<" , "<<endl;
  10. cout<<endl;

Con bucles ( y aplicando lo comentado anteriormente tambien ):

Código
  1. for ( int i = 0; i < 5; i++ )
  2. {
  3.  cout << "Usuario " << i << ": " << persona[ i ].cedula
  4.                                  << " , " << persona[ i ].nombre
  5.                                  << " , " << persona[ i ].correo
  6.                                  << " , " << persona[ i ].telefono
  7.                                  << " , " << persona[ i ].padres[ i ].cedula
  8.                                  << " , " << persona[ i ].padres[ i ].nombre
  9.                                  << " , " << persona[ i ].padres[ i ].cedula // duplicado
  10.                                  << " , " << persona[ i ].padres[ i ].nombre // duplicado
  11.                                  << endl;
  12. }

Por cierto, fíjate que ahora se aprecian varios errores:

* para cada "persona" solo imprimes un "padre"... eso huele mal.
* Para el "padre" estás sacando dos veces la misma información... líneas con comentario

Seguro que si intentas ver estos errores en tu código te va a costar más encontrarlos (sobretodo si no sabes que están ahí)

Y bueno, de momento creo que te he comentado bastantes cosillas, deberías repasar un poco tu código. Si después de eso sigues teniendo dudas aquí estamos.

Un saludo.
275  Programación / Programación C/C++ / Re: Leer Metadatos en: 3 Agosto 2014, 11:57 am
Suponiendo que tuvieses algo del tipo

Código
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <NewTable name="nueva_tabla">
  3.  <cols>
  4.    <col>
  5.      <name>columna1</name>
  6.      <dataType>int</dataType>
  7.     </col>
  8.  </cols>
  9. </NewTable>

Tendrías que leer el XML y, simplificando, seguir el siguiente esquema. Nota que el código es una especie de pseudocódigo... el código final dependerá de la clase que uses para leer el XML.

Código
  1. XmlReader reader( fichero );
  2.  
  3. while ( reader.NextNode( ) )
  4. {
  5.  if ( reader.CurrentNode( ).Name( ) == "NewTable" )
  6.    NewTable( reader );
  7. }
  8.  
  9. void NewTable( XmlReader& reader )
  10. {
  11.  std::string tableName = reader.CurrentNode( ).Attribute( "name" ); // Recuperamos 'nueva_tabla'
  12.  std::vector< DBCol > columns;
  13.  
  14.  while ( reader.NextNode( ) )
  15.  {
  16.    if ( reader.CurrentNode( ).Name( ) == "cols" )
  17.      columns = ReadColumns( reader );
  18.  }
  19.  
  20.  std::string sql = "CREATE TABLE " + tableName + " (";
  21.  
  22.  for ( const auto& col : columns )
  23.  {
  24.    sql += col.Name( ) + ...
  25.  }
  26.  sql += ")";
  27.  
  28.  // Solo falta ejecutar la sentencia SQL
  29. }
  30.  
  31. void ReadColumns( XmlReader& reader )
  32. {
  33.  std::vector< DBCol > columns;
  34.  
  35.  while ( reader.NextNode( ) )
  36.  {
  37.    if ( reader.CurrentNode( ).Name( ) == "col" )
  38.      columns.push_back( ReadColumn( reader );
  39.  }
  40.  
  41.  return columns;
  42. }
  43.  
  44. void ReadColumn( XmlReader& reader )
  45. {
  46.  DBCol column;
  47.  
  48.  while ( reader.NextNode( ) )
  49.  {
  50.    if ( reader.CurrentNode( ).Name( ) == "name" )
  51.      column.SetName( reader.CurrentNode( ).ReadText( ) ); // Nombre de la columna
  52.    else if ( reader.CurrentNode( ).Name( ) == "dataType" )
  53.      column.SetType( reader.CurrentNode( ).ReadText( ) );
  54.  }
  55.  
  56.  return column;
  57. }
276  Programación / Programación C/C++ / Re: Leer Metadatos en: 2 Agosto 2014, 12:05 pm
Crear una tabla es algo bastante más complejo. Hay que indicar también qué campos hay, que nombre tienen, de qué tipo es cada campo y ajustar algúnas configuraciones adicionales (longitud de los caracteres, si es clave primaria, campos que se autoincrementan ). Luego aparte también se suelen configurar reglas de acceso o disparadores ( para trabajar con tablas relacionales )....

Vamos, que por poder, sí prodrías conseguirlo, pero vas a tener que añadir más profundidad a esa etiqueta :)
277  Programación / Programación C/C++ / Re: [Solucionado] Problema para sacar factorial de un entero en: 1 Agosto 2014, 08:25 am
Si luego quieres subir un escalón... también lo puedes hacer con templates:

Código
  1. template< int N >
  2. struct Factorial
  3. {
  4.    enum { value = N * Factorial< N - 1 >::value };
  5. };
  6.  
  7. template<>
  8. struct Factorial< 0 >
  9. {
  10.    enum { value = 1 };
  11. };
  12.  
  13. int main( )
  14. {
  15.  std::cout << "Factorial de 4: " << Factorial< 4 >::value << std::endl;
  16.  std::cout << "Factorial de 5: " << Factorial< 5 >::value << std::endl;
  17. }
278  Programación / Programación C/C++ / Re: Como escribir puntero a objetos en el disco duro para posteriorment recuperarlo? en: 1 Agosto 2014, 08:21 am
readFloat( ) como  funciona? como avanzas en el stream(suponiendo que es un archivo binario) hacia adelante?

stream lo he puesto a modo de ejemplo. Cuando "serializas" un objeto, es decir, cuando extraes de el su estado para poder reconstruir el objeto en el futuro, forzosamente tienes que guardar esta información en algún sitio: un fichero, enviarlo por red, ... curiosamente todas estas opciones funcionan mediante streams.

Si vas a almacenar la información en disco entonces podrías usar "ofstream" para guardar y "ifstream" para leer... como ves no dejan de ser streams. Los métodos concretos que te permitan manejar cada una de estas clases los tienes en internet, buscando un poco se encuentran.

En cuanto al 'readFloat' no es más que un hipotético método que me permite obtener un float del stream... simplemente. Dependiendo de la interfaz del stream, este método puede llamarse así, o simplemente 'read' o vete tu a saber como... depende de la interfaz del stream.

Y tratando el tema de "avanzar en el stream", se supone que cada vez que tu haces una lectura de un stream el puntero de lectura que tiene interno avanza solo, por lo que, por norma general, no debes preocuparte de este aspecto.
279  Programación / Programación C/C++ / Re: como hacer una solicitud HTTP GET a una URL en C++? en: 31 Julio 2014, 11:19 am
gracias, como se añaden nuevas librerias al IDE?, uso VS.

No es por ser un rancio pero... ¿has probado a buscar en google? La mayoría de los enlaces que se acaban poniendo en este tipo de mensajes salen de ahí....

En este mundo es muy importante saber sacarse las castañas del fuego... y eso implica saber dónde buscar. Creo que este foro se desvirtúa si empezamos a pedir enlaces que se pueden encontrar fácilmente en google:

* Ejemplo1. Palabras clave "sockets c++ tutorial winsock". Salen varios tutoriales sólo mirando en la primera página...

* Ejemplo 2. Palabras clave "sockets c++ example winsock". Igualmente, salen varios ejemplos sólo en la primera página.
280  Programación / Programación C/C++ / Re: Como escribir puntero a objetos en el disco duro para posteriorment recuperarlo? en: 31 Julio 2014, 08:43 am
Dado que los objetos de C++ son bastante propensos a utilizar memoria dinámica: punteros internos, contenedores de la stl, ... no suele ser buena idea hacer una copia "a lo bestia" del contenido de la memoria, ya que así pierdes la información almacenada mediante punteros.

La mejor forma de guardar objetos ( para almacenarlos en disco, enviarlos por red, etc. ) es hacer el trabajo "a mano", es decir, extraer toda la información que permite reconstruir el objeto y almacenar dicha información:

Código
  1. class POO
  2. {
  3.  public:
  4.  
  5.    int Numero( ) const
  6.    { return numero; }
  7.  
  8.    std::string Nombre( ) const
  9.    { return nombre; }
  10.  
  11.    const std::vector< float >& Valores( ) const
  12.    { return valores; }
  13.  
  14.  private:
  15.    int numero;
  16.    std::string nombre;
  17.    std::vector< float > valores;
  18. }
  19.  
  20. void Serializar( POO* poo, Stream* stream )
  21. {
  22.  stream.write( poo->Numero( ) );
  23.  stream.write( poo->Nombre( ) );
  24.  
  25.  stream.write( poo->Valores( ).size( ) ); // Numero de elementos del array
  26.  for ( const auto& valor : poo->Valores( ) )
  27.    stream.write( valor );
  28. }
  29.  
  30. POO* Deserializar( Stream* stream )
  31. {
  32.  POO* poo = new POO( );
  33.  poo->SetNumero( stream->readNumber( ) );
  34.  poo->SetNombre( stream->readString( ) );
  35.  
  36.  int numValores = stream->readNumber( );
  37.  std::vector< float > valores;
  38.  for ( int i = 0; i < numValores; i++ )
  39.    valores.push_back( stream->readFloat( ) );
  40.  poo->SetValores( valores );
  41.  
  42.  return poo;
  43. }

El ejemplo es ambigüo ya que la forma concreta de "serializar" el objeto depende en gran medida del formato en el que se va a almacenar: archivo binario, XML, base de datos, ...

Faltan algunos métodos en "POO"... pero no deberían suponer ningún problema para entender el código.
Páginas: 1 ... 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ... 125
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines