Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - rir3760

#731
Cita de: Zodiak98 en 22 Julio 2013, 20:09 PM
Bueno es que estaba aburrido y me puse a programar un juego muy sencillo que trata sobre meter un numero entre el 1 y el 15 y tú compañero tiene que adivinarlo. Pero lo que quiero hacer es que no se puedan ingresar letras solo números
Con solo C++ estándar hay que limitarse a la validación una vez se genere el texto.

Debes leer una linea verificando que la lectura del entero sea exitosa y el siguiente carácter sea el avance de linea. Por ejemplo:
Código (cpp) [Seleccionar]
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <limits>
using std::numeric_limits;

int main()
{
   int num;
   bool ok = false;
   bool error_critico = false;
   
   do {
      cout << "Teclea un numero: ";
      if (cin >> num && cin.get() == '\n')
         ok = true;
      else if (cin.eof() || cin.bad())
         error_critico = true;
      else {
         cout << "Entrada no valida" << endl;
         cin.clear();
         cin.ignore(numeric_limits<int>::max(), '\n');
      }
   }while (!ok && !error_critico);
   
   cout << endl;
   
   if (ok)
      cout << "El numero es " << num << endl;
   else
      cout << "Error critico en la lectura" << endl;
   
   return 0;
}


Un saludo
#732
Programación C/C++ / Re: scanf y gets
21 Julio 2013, 19:29 PM
Si vas a publicar código fuente por favor publicalo completo ya que faltan las directivas del preprocesador. En la función "entrada" faltan los operadores de indireccion y multiplicación en la llamada a malloc, no es necesario con esta la conversión explicita como tampoco multiplicar por "sizeof(char)" ya que este ultimo siempre es igual a uno. Y algunos mas.

Con los cambios compila sin problemas:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 5

void entrada(char *nombre[]);

int main(void)
{
   char *nombre[MAX];
   
   entrada(nombre);
   
   return EXIT_SUCCESS;
}

void entrada(char *nombre[])
{
   char B[50];
   int i;
   
   for (i = 0; i < MAX; i++){
      printf("Dame la escuela numero %d: ",i);
      fflush(stdout);
      fgets(B, 50, stdin);
      *(nombre + i) = malloc(strlen(B) + 1);
      strcpy(nombre[i], B);
   }
}


Por ultimo no deberías utilizar la función gets, el porque y mas recomendaciones en el tema |Lo que no hay que hacer en C/C++. Nivel basico|

Un saludo
#733
Cita de: eferion en 20 Julio 2013, 23:53 PMPara dividir entre dos, es muuuucho más óptimo usar desplazamientos binarios:

// esto
variable = variable >> 1;

// es más óptimo que esto
variable = variable / 2;
En el desplazamiento si la variable es de un tipo entero con signo el valor del bit de relleno depende de la implementación, en otras palabras no esta garantizado que el resultado de ambas operaciones (división y desplazamiento) sea el mismo. Si es un tipo sin signo el bit de relleno siempre es cero, ahí no hay problema.

Cita de: eferion en 20 Julio 2013, 23:53 PMTambién creo recordar, no estoy 100% seguro, que para saber si un número es divisible entre 2 se puede optimizar también de la siguiente forma ( como no aprovechando desplazamientos binarios ):

// Sin optimizar
if(n % 2) //n impar y mayor que 2

// optimizado
if ( ( n >> 1 << 1 ) == n )
Ya que los números pares (positivos) tienen el bit menos significativo a cero se puede reducir la expresión a "!(n & 1)". Y si invertimos la condición (verificar impares) terminamos utilizando un operador:
if (n & 1){
   /* impares */
}else {
   /* pares */
}


Pero como ya se comento es mejor dejar ciertas mejoras (por ejemplo división vs desplazamiento) al compilador.

Un saludo
#734
Cita de: petita en 20 Julio 2013, 14:35 PMlo que quiero hacer es que el vector Clase sea de "n" componentes, de esta forma solo puedo crear una cantidad fija de alumnos. ¿Es posible hacer eso?¿Hacer que el vector clase sea dinámico?
Si, es posible. Solo hay que cambiar la aproximación en la función principal, en lugar de utilizar un array se utiliza un puntero para reservar un bloque de memoria (la tabla de direcciones).

La función main con los cambios:
int main(void)
{
   Alumno **Clase;
   int num_elem = 123; /* Solo un ejemplo */
   int i;
   
   Clase = malloc(num_elem * sizeof *Clase);
   
   Clase[0] = NuevoAlumno();
   Clase[1] = NuevoAlumno();
   /* ... */
   
   /* Algun proceso ... */
   
   /* Liberacion de memoria */
   for (i = 0; i < num_elem; i++){
      free(Clase[i]->nombre);
      free(Clase[i]);
   }
   free(Clase);

   return 0;
}


Un saludo
#735
Cita de: petita en 20 Julio 2013, 03:03 AMMi duda es la siguiente... En  el código de abajo me tira errores en:
Clase[0]=NuevoAlumno();
Clase[1]=NuevoAlumno();
Ello se debe a que los tipos son diferentes: "Clase[0]" y "Clase[1]" son de tipo "Alumno" mientras que la función "NuevoAlumno" retorna un puntero de tipo "Alumno *".

Cita de: petita en 20 Julio 2013, 03:03 AMEstá mal reservar memoria para el vector clase,  luego crear las estructuras necessarias y guardar las direcciones de memoria de dichas estructuras en la memoria reservada??
El problema es que no estas haciendo eso en el programa, el error principal en este es reservar en dos ocasiones la memoria para las estructuras: primero en la función principal y después en la función "NuevoAlumno".

Para realizar lo que mencionas se debe utilizar un array de punteros a estructuras en la función main almacenando en este las direcciones que retorna la función "NuevoAlumno". De esta forma:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Dato {
   char *nombre;
   int dni;
} Alumno;

Alumno *NuevoAlumno(void);

int main(void)
{
   Alumno *Clase[2];
   
   Clase[0] = NuevoAlumno();
   Clase[1] = NuevoAlumno();
   
   /* Algun proceso ... */
   
   /* Liberacion de memoria */
   free(Clase[0]->nombre);
   free(Clase[0]);
   free(Clase[1]->nombre);
   free(Clase[1]);
   
   return 0;
}

Alumno *NuevoAlumno(void)
{
   Alumno *a = malloc(sizeof *a);
   char aux[50];
   
   printf("Ingrese el nombre del alumno: ");
   fflush(stdout);
   scanf("%49s", aux);
   a->nombre = malloc(strlen(aux) + 1);
   strcpy(a->nombre, aux);
   
   printf("Ingrese el numero de dni del alumno: ");
   fflush(stdout);
   scanf("%d", &a->dni);
   
   return a;
}


Falta agregar la verificación de errores en la función "NuevoAlumno" de las llamadas a malloc, eso te toca a ti.

Un saludo
#736
Es la definicion de la funcion main para procesar los argumentos pasados mediante la linea de comandos:

* argc es el numero de estos
* argv[0] es el nombre de la aplicacion o NULL.
* argv[1] .. argv[argc - 1] cada uno de los argumentos.
* argv[argc] siempre es NULL.

Esa lista se puede procesar de varias formas, dos de ellas una utilizando el parametro argc y otra mediante aritmetica de punteros:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
   int i;
   char **p;
   
   puts("Lista de argumentos (Forma 1):");
   for (i = 0; i <= argc; i++)
      printf(
         "argv[%d] == \"%s\"\n",
         i,
         argv[i] != NULL ? argv[i] : "NULL"
      );
   
   puts("----");
   
   puts("Lista de argumentos (Forma 2):");
   for (p = argv; p <= argv + argc; p++)
      printf(
         "argv[%ld] == \"%s\"\n",
         (long int) (p - argv),
         *p != NULL ? *p : "NULL"
      );
   
   return EXIT_SUCCESS;
}


Un saludo
#737
Programación C/C++ / Re: scanf y gets
19 Julio 2013, 17:24 PM
Cita de: m@o_614 en 17 Julio 2013, 21:25 PMeferion como es eso de que *arreglo[10] es equivalente a **arreglo???
Porque en C en la mayoría de los casos el uso de un array resulta en la dirección en memoria de su primer elemento. El caso usual es la llamada a funcion. Por ejemplo:
#include <stdio.h>
#include <stdlib.h>

void imprimir(char const *texto);

int main(void)
{
   char linea[] = "Texto de prueba\n";
   
   imprimir(linea);
   
   return EXIT_SUCCESS;
}

void imprimir(char const *texto)
{
   int i;
   
   for (i = 0; texto[i] != '\0'; i++)
      putchar(texto[i]);
}


Tu caso es similar: si el array se declara como "char *arreglo[10]" en expresiones su nombre resulta en un puntero al primer elemento del array ("char *arreglo[10]" ==> "char **")

----

Cita de: m@o_614 en 18 Julio 2013, 20:23 PMUna ultima pregunta cuando yo declaro un arreglo de punteros char *a[5]; para despues con un for ingresarle cada uno de los elementos (a+1),(a+2),etc..., primero tengo que asignarle memoria dinamica con malloc, calloc?
No exactamente.

Antes de utilizar una variable de tipo puntero debes almacenar en esta una dirección de memoria valida, esta puede ser la retornada por la función malloc, la dirección de algún objeto o una cadena literal. Por ejemplo:
#include <stdio.h>
#include <stdlib.h>

void imprimir(char const *texto);

int main(void)
{
   char *nombre[3];
   int i;
   
   nombre[0] = "Jesus\n";
   nombre[1] = "Maria\n";
   nombre[2] = "Jose\n";
   
   for (i = 0; i < 3; i++)
      imprimir(nombre[i]);
   
   return EXIT_SUCCESS;
}

void imprimir(char const *texto)
{
   int i;
   
   for (i = 0; texto[i] != '\0'; i++)
      putchar(texto[i]);
}

Pero en este caso con el detalle de que las cadenas literales son de solo lectura, no se puedes hacer mas con ellas ademas de imprimirlas.

----

Cita de: m@o_614 en 19 Julio 2013, 06:48 AM
entonces si por ejemplo quiero ingresarle no se... 5 nombres cualquieras:

char *a[5]

*(a+0)="Maria";
*(a+1)="Jose";
etc...

pero no quiero estar contando el numero de letras cada vez que tenga que asignar memoria para cada nombre, como se le asignaria la memoria??
A priori no hay forma. Lo mas sencillo es utilizar un array de caracteres para leer ahí cada una de las cadenas tomando nota de su longitud. Lees una cadena, reservas el espacio justo para ella y la copias ahí. Un programa de ejemplo lo puedes revisar en el tema Duda Punteros Dobles/Array de punteros.

Un saludo
#738
Cita de: Caster en 18 Julio 2013, 16:43 PMA ver que no me entero de una, entonces si hacemos esto:

int* ptr1,ptr2,ptr3;

El unico puntero que hay aqui es ptr1, no?
Correcto. El estándar de C define al lenguaje como uno de formato libre donde el espacio blanco (espacio, tabulador, etc.) solo es significativo en tres casos:
1) Directivas del preprocesador.
2) Cadenas literales.
3) Cuando este indica el final de un token (la unidad mínima que reconoce el lenguaje). Por ejemplo el espacio en "int i;" es significativo mientras que en "int * i;" no lo es (esta ultima se puede separar sin ambigüedades en los tokens 'int', '*', 'i' y ';').

En el ejemplo que mencionas si eliminamos el espacio, los separadores (las comas) y el indicador de fin de sentencia (el punto y coma) los tokens se agrupan así:
int
*ptr1
ptr2
ptr3

Resultando en la declaración de tres variables donde solo la primera es un puntero.

----

Cita de: jednak en 18 Julio 2013, 23:47 PMQueria saber si esta bien lo q afirmo. Es decir , si esta bien de que son las direcciones de memoria de las funciones y no del array. (Supuse que estan bien porque no son consecutivas , pero por las  dudas pregunto).
Es correcto, solo un comentario: en el bucle no necesitas aplicar indireccion en la llamada a función y, siendo pesados, no es posible imprimir (de forma portable) la dirección de una función.

La mejor forma en el caso del bucle es:
for (i = 0; i < 3; i++){
   f[i](i);
   printf("La direccion en memoria es %p\n", (void *) f[i]);
}


Un saludo
#739
Cita de: Puntoinfinito en 17 Julio 2013, 18:30 PMNecesito una función que lea unos numeros de un archivo de texto que luego los cojera y los ordenara para añadirlos por orden a un miembro de una clase (dat.topScore)
El problema me parece que ya esta resuelto.

Otras dos recomendaciones son:

Si quieres que todos los elementos de un array se inicializen a cero:
Código (cpp) [Seleccionar]
int _temp[128]; // temporal para ordenar
for (int i = 0; i < 128; i++) {
   _temp[i] = 0; // añado inicializador
}

Puedes hacerlo de una forma mas breve, indicando el valor del primer elemento:
Código (cpp) [Seleccionar]
int _temp[128] = {0}; // _temp[0] es cero, los elementos restantes se inicializan a cero

Y para controlar la lectura de datos en un bucle no se recomienda el uso de la función miembro eof:
Código (cpp) [Seleccionar]
while (!dataFile_o.eof()) {
   dataFile_o.getline(linea,sizeof(linea));
   temp[lineas] = atoi(linea);
   lineas++;
}

Ello porque eof resultara en el valor verdadero solo después del fallo de una operación de lectura. En su lugar puedes utilizar el resultado de getline directamente (y de paso reduces el numero de sentencias):
Código (cpp) [Seleccionar]
while (dataFile_o.getline(linea,sizeof(linea))){
   temp[lineas] = atoi(linea);
   lineas++;
}


Un saludo
#740
¿C o C++?

----

En el caso de C cuando una función se declara en cualquiera de las dos formas:
int fn(int a[]);

/* O bien: */
int fn(int a[123]);

En realidad se procesa así:
int fn(int *a);

Y cuando se llama a la función pasando como argumento el nombre de un array este se sustituye por la dirección en memoria de su primer elemento. Por ello no es necesario (ni se recomienda) indicar el numero de elementos del array (no tiene caso).

----

Lo que tu llamas "matriz" solo es un array y por ende no debes indicar el numero de elementos (filas), debes indicar el numero de columnas porque ello es parte del tipo de cada elemento del array.

Para explicarlo mejor un ejemplo en C utilizando alias:
#include <stdio.h>
#include <stdlib.h>

/* array_10_int == array de 10 elementos de tipo int */
typedef int array_10_int[10];

void fn(array_10_int array[1000], size_t num_elem);

int main(void)
{
   array_10_int a[10];
   size_t num_elem = sizeof a / sizeof a[0];
   int i;
   int j;
   
   for (i = 0; i < num_elem; i++)
      for (j = 0; j < 10; j++)
         a[i][j] = i * 10 + j;
   
   fn(a, num_elem);
   
   return EXIT_SUCCESS;
}

void fn(array_10_int array[], size_t num_elem)
{
   size_t i;
   size_t j;
   
   for (i = 0; i < num_elem; i++){
      for (j = 0; j < 10; j++)
         printf("%4d", array[i][j]);
     
      putchar('\n');
   }
}


Un saludo