/* Si les sale un mensaje como el siguiente en linux*/
Hay que modificar /etc/resolv.conf y poner nameserver 8.8.8.8 agregandolo al final del archivo
/* Si les sale un mensaje como el siguiente en linux*/
Hay que modificar /etc/resolv.conf y poner nameserver 8.8.8.8 agregandolo al final del archivo
/*Este texto no es de mi autoria*/
Hola Gente!!
BUENO ESTO ES UNA EXPLICACIÓN DE PORQUE AVECES EL SCANF SE COMPORTA DE MANERA EXTRAÑA. ESPERO QUE SE ENTIENDA,
voy explico porque el uso de scanf no es recomendable..
para empezar es un error decir que un programa lee del teclado en verdad lo que hace es leer de un area de memoria llamado "buffer de teclado" (no
siempre es así, esto se puede manipular mediante la función setvbuf y
el modo _IOFBF, que especifica que lea hasta que el buffer esté lleno.) y el buffer del teclado es "buffer de linea"
esto quiere decir que los datos que provienen del teclado se insertan
linea por linea y no caracter a caracter . Es por eso que cuando leemos
de ahí, por más que ingresemos muchos caracteres, hasta que no
ingresamos el fin de línea (enter) el programa no lee nada y se queda
trabado esperando que haya algo en el buffer.
si el buffer no está vacío, sí o sí hay al menos un fin de línea;
el buffer siempre tiene un carácter de fin de línea al final.
El gran problema con scanf
es que no siempre leerá el fin de linea lo que nos lleva a que el
buffer quede con basura, osea con caracteres no leídos los cuales la
próxima vez que invoquemos a scanf los leerá e intentara limpiar el
buffer ocasionando un salto de linea e impediendonos ingresar el dato
requerido. de mas esta decir que esto podría causar algunos problemas
al programador.
scanf solo lee hasta que encuentre el formato
que le especificamos, esto conlleva a otro gran problema ya que si
nosotros le decimos que lea un entero (%i") y se le ingresan 2 enteros
separados por un espacio scanf solo leerá hasta encontrar el formato especificado dejando al buffer sucio con ese entero de mas.
Otro
problema que tenemos es que no hace casi ningún tipo de chequeo a la
hora de verificar los datos ingresados si se le indica que se ingresara
un entero y el usuario ingresa una letra esté hace una conversión a
entero lo cual genera un problema.
en el siguiente segmento de programa intenten lo siguiente cuando les piede ingresar los datos pongan algo así como "50 10" (sin las comillas) y veran como el buffer quedara sucio con con el entero 10 entonces cuando se llama de nuevo a scanf "asimila" que 10 es lo que se ingreso y por eso no nos deja ingresar el dato e imprime el nuevo valor de i
Siempre se puede usar
setbuf(stdin,NULL);
Aunque se recomienda usar fgets y sscanf:
fgets(buffer o variable donde se guarda,cantidad de caracteres,stdin);
stdin significa entrada por teclado.buffer es un campo para reservar temporalmente algo, como puede ser una cadena.
fgets(buffer, 11,stdin); y fgets leera 11-1 caracteres siendo mas seguro que scanf. Scanf no comprueba lo que se ingresa, lo cual le hace vulnerable al buffer overflow. Se puede cambiar 11 por sizeof(buffer).
De igual manera hay que ser cauteloso con strcat y strcopy,debe usarse strncat y strncpy con el 3er parametro que controla el ingreso de caracteres.
//con sscanf introducimos lo que tenemos en el buffer tanto en nombre como en edad PARA LEER ENTERO#include <stdio.h>#include <string.h>int main(){char buffer[13]={0};short int edad=0;setbuf(stdin,NULL); printf("Ingrese un numero: \n");fgets(buffer,sizeof(buffer),stdin);sscanf(buffer , %u", &edad );printf("El numero es: %d\n",edad); return 0;}
typedef struct Ficha Fichas;
int main(int argc, char** argv)
{
Fichas Cliente[100];
int i;
char nombre[80];
for (i = 0; i < 99; i++) {
if (nombre == Cliente[i].Nombre) {
printf ("%s", Cliente[i].Nombre);
printf ("%i",Cliente[i].Num_unidades);
printf ("%i", Cliente[i].Precio_unidad);
else if (movimiento == '2' && c2 == '2'){c2 = marcajugador;} else if (movimiento == '3' && c3 == '3'){c3 = marcajugador;} else if (movimiento == '4' && c4 == '4'){c4 = marcajugador;} else if (movimiento == '5' && c5 == '5'){c5 = marcajugador;} else if (movimiento == '6' && c6 == '6'){c6 = marcajugador;} else if (movimiento == '7' && c7 == '7'){c7 = marcajugador;} else if (movimiento == '8' && c8 == '8'){c8 = marcajugador;} else if (movimiento == '9' && c9 == '9'){c9 = marcajugador;} else {printf("Movimiento Invalido, Intenta Otra Vez\n");} movalido = false;}while(!movalido); juegoterminado=false; juego_ganado=true; if (c1 != '1') { if (c2 == c1 && c3 == c1){juegoterminado = true;} if (c4 == c1 && c7 == c1) {juegoterminado = true;}} if (c5 != '5'){ if (c1 == c5 && c9 == 5) {juegoterminado = true;} if (c2 == c5 && c8 == c5) {juegoterminado = true;} if (c4 == c5 && c6 == c5) {juegoterminado = true;} if (c3 == c5 && c7 == c5){juegoterminado = true;}} if (c9 != '9') { if (c3 == c9 && c6 == c9){juegoterminado = true;} if (c7 == c9 && c8 == c9){juegoterminado = true;}} if (c1 != '1' && c2 != '2' && c3 != '3' && c4 != '4' && c5 != '5' && c6 != '6' && c7 != '7' && c8 != '8' && c9 != '9' && !juegoterminado){ juegoterminado = true; juego_ganado = false;} if (juegoterminado){ if (juego_ganado) {printf("Juagador: %d Gana!",turno_jugador);} // Imprimir Tablero printf("\t\t\t\t||%c||%c||%c||\n",c1,c2,c3); printf("\t\t\t\t||+||+||+||\n"); printf("\t\t\t\t||%c||%c||%c||\n",c4,c5,c6); printf("\t\t\t\t||+||+||+||\n"); printf("\t\t\t\t||%c||%c||%c||\n",c7,c8,c9); printf("\t\t\t\t||+||+||+||\n\n"); printf("Juego Terminado!"); printf("Jugar De Nuevo (Y/N)?"); scanf("%d",&jugar_otra); if (jugar_otra == 'y'||jugar_otra == 'Y'){ juegoterminado = false; c1='1';c2='2';c3='3';c4='4';c5='5';c6='6';c7='7';c8='8';c9='9'; } turno_jugador=1; } else { if (turno_jugador == 1){turno_jugador = 2;} else {turno_jugador = 1;} } } while (!juegoterminado); }
/***********************************************
Nombre: Simulador Descripción: Primera parte de la creación de un simulador de sistema operativo RR. Fecha:13-01-09 Autor:Bruno Kröller da Silva ************************************************/
// Cabecera de librerías
#include <stdio.h> // Uso de printf,...
#include <stdlib.h> //Uso de atoi,...
#include <unistd.h> //Uso de waitpid,...
#include <sys/types.h> // Uso de rand,...
#include <string.h> // Uso de //VARIABLES GLOBALES #define N_MAX 15
#define T_MAX 30
#define T_MIN 5
//FUNCIONES int hijos(int n_maximo,int quantum,int tiempo);
// Función main que recive parametros de entrada int main (int argc, char *argv[]){
// Variables de entorno. int resultado; // 0 error 1 correcto int tiempo;int n_maximo;int quantum; //Valores predefinidos de las variables. n_maximo=5;quantum=80;resultado=0; /* Controlamos que el número de argumentos sea correcto, en caso contrario no empezamos a ejecutar las funciones principales.*/ if(argc==1 || argc==3 || argc==5 || argc>6){ printf("\t\n Error, el formato es n p m q t");} else{ /*Si entran dos argumentos, nombre + tiempo*/ if(argc==2){ tiempo=atoi(argv[2]); if(1<=tiempo<=120){resultado=1;}} /*Si entran 4 argumentos, nombre+ numero+ p + tiempo o nombre+ quantum+ q + tiempo*/ else if(argc==4){ tiempo=atoi(argv[4]); if(*argv[2]=='p' && 1<=tiempo<=120) { n_maximo=atoi(argv[1]); resultado=1; } if(*argv[2]=='q' && 1<=tiempo<=120){ quantum=atoi(argv[1]); resultado=1; }} /*Si entran argumentos, nombre+ numero+ p+ quantum+ q + tiempo*/ else if(argc==6){ tiempo=atoi(argv[6]); if(*argv[2]=='p' && *argv[4]=='q' && 1<=tiempo<=120){ n_maximo=atoi(argv[1]); quantum=atoi(argv[3]); resultado=1;}} // SAlIDA DEl PROGRAMA if(resultado==1){ printf("\t\n Simulador: "); printf("\t\n Numero maximo de programas: %d ",n_maximo); printf("\t\n Quantum : %d",quantum); printf("\t\n Tiempo de ejecución: %d ",tiempo); } else{ printf("\t\n Error al introducir los parametros:"); printf("\t\n [numero_prog] [p] [quantum] [q] [tiempo] ");} } return 0;} int hijos(int n_maximo,int quantum,int tiempo){ int error; // 1 correcto, 0 error. pid_t pid_h; // Variable donde almacenaremos el pid del hijo int numero;int i;int tiempo_max; //INICIALIZACIÓN DE VALORES i=0;error=1; /*LANZAMIENTO DEL SISTEMA OPERATIVO*/ //Creamos un hijo pid_t fork(); //Pedimos que nos diga su pid pid_h=getpid(); //Comprobamos que el hijo se ha creado if(pid_h==-1){error=0;} else{ //Ejecutado por el padre if(pid_h!=0){waitpid(pid_h,NULL,0);} //Ejecutado por el hijo else{ //Ejecutar el S.O. //Aquí termina el hijo exit(0);} } /*LANZAMIENTO DE LA TEMPORIZACIÓN.*/ //Creamos un hijo pid_t fork(); //Pedimos que nos diga su pid pid_h=getpid(); //Comprobamos que el hijo se ha creado if(pid_h==-1){error=0;} else{ //Ejecutado por el padre if(pid_h!=0){waitpid(pid_h,NULL,0);} //Ejecutado por el hijo else{ sleep(tiempo); printf("\t\n Temporizador: "\ "Finalizado el tiempo de simulación "); //Aquí termina el hijo exit(0);} } /*LANZAMIENTO DE LA TEMPORIZACIÓN.*/ //CREARCIÓN DE LOS 10 HIJOS while(i<10){ srand(time(0)); //Generamos un numero no mayor que N_MAX //Le sumamos 1 para que empiece en 1. numero=1+rand()%(N_MAX); //Generamos el tiempo de espera de cada hijo. //Crea números en un intervalo de 5 a 30. tiempo_max=5+rand()%21; //Tiempo de espera para crear el siguiente hijo. sleep(numero); //CREAR HIJO pid_t fork(); } pid_h=getpid(); if(pid_h==0){ sleep(tiempo_max); printf("\n\t Simulador: "\ "Lanzando programa- Tiempo ejecución %d ",tiempo_max); exit(0);} //El padre espera a que todos los hijos mueran. wait(); return(error);} /*CHULETA DE VARIABLES Valores mínimos y máximos de: mínimo máximo Tiempo : 1 120 Quantum : 20 200 Programas : 1 5 numero esta entre [1,30]*/
/*Este tutorial cubre los primeros conceptos previos a la
creación de aplicaciones con OpenGL y en general a la
creación de contenido 3d. Es necesario aclarar que el
tutorial, por simplicidad y extensión se enfoca sobre la
especificación 1.1 de OpenGL, es decir, solo se menciona la
funcionalidad de la llamada “Fixed Pipeline” (ahora con la
entrada de OpenGL 2.0 y la introducción de los shader al
estándar, la estructura cambio).
En el tutorial se mencionan algunas palabras en ingles,
acompañadas de su traducción al español, solo para conservar
el término original (en ingles) y facilitar la búsqueda
posterior del término, tanto en español, como en inglés.
¿Qué es OpenGL? : OpenGL (Open Graphics Library) es un API
(de Aplication Programming Interface, Interfaz de
Programación de Aplicaciones) libre, multiplataforma,
orientado a la creación de contenido 3d. A un nivel más
simple se puede decir que es una librería que permite hacer
software con gráficos 3d sin preocuparse por el hardware en
que se va a ejecutar y que tiene un gran soporte en diferentes
sistemas operativos como Windows, OS/2, UNIX, FreeBSD , Linux,
etc.
Hay que hacer una diferencia clara, OpenGL no es un lenguaje
de programación, pero se puede trabajar con él desde
diferentes lenguajes como c++, c#, java y Visual Basic.
¿Para que puedo usar OpenGL? : OpenGL puede ser usado para
todo tipo de aplicaciones que necesiten visualización 3d en
tiempo real de alto rendimiento y calidad, en esto están
incluido los videojuegos, CAD, aplicaciones científicas,
médicas, militares, simuladores, etc.
¿Qué necesito para utilizar OpenGL en mis programas? Es buena
idea utilizar un IDE como Visual Studio, Eclipse o DevCpp
para realizar los programas, ya que facilita mucho el trabajo,
adicionalmente, en los archivos fuente donde se utilicen
funciones de OpenGL es necesario incluir las bibliotecas de
prototipos gl.h y glu.h, que generalmente se encuentran
preinstaladas no solo en Visual Studio, sino en otros entornos
donde se soporta el uso de OpenGL. También es necesario hacer
un link con las librerías binarias, en Visual Studio las dos
cosas se verían como:
*/
//Inclusión de las librerías prototipo
#include <gl/gl.h>
#include <gl/glu.h>
//Link con las librerías binarias
#pragma comment(lib, “opengl32.lib”)
#pragma comment(lib, “glu32.lib”)
/*es necesario pasar a algunos conceptos fundamentales del 3d.
SISTEMAS DE COORDENADAS
Para trabajar gráficos bien sea 2d o 3d es necesario tener una
forma de describir la posición de un objeto cualquiera en el
espacio. Para esto es necesario establecer un patrón de
referencia, lo cual se hace generalmente a través de un
sistema de coordenadas y el sistema al que mas estamos
acostumbrados es el de coordenadas cartesianas, en el cual un
punto puede ser expresado como una distancia a través uno (x),
dos (x,y) o tres ejes (x,y,z) mutuamente perpendiculares que
se intersecan en el punto (0,0) en el caso de dos dimensiones
y (0,0,0) en el caso de tres.
OpenGL maneja los sistemas 2d y 3d, aunque el sistema de 2d
sobre píxeles en pantalla es bastante ineficiente, por lo que
en la mayoría de los casos mejor utilizar 3d y simular el 2d
con una proyección ortográfica de la escena.
Si bien la forma en que se representan las coordenadas
cartesianas en matemáticas es bastante estándar (‘x’ positivo
a la derecha y ‘y’ positivo arriba), en los sistemas de dibujo
en el computador hay variaciones dependiendo del sistema de
dibujo sobre el cual se esté trabajando y el caso del 3d es
totalmente dependiente de desde donde, hacia donde y que es
“arriba”. Esto quiere decir que las coordenadas del sistema
abstracto no tienen que ser concordantes con el sistema de
coordenadas sobre la pantalla, por lo que se deber realizar
un proceso llamado mapeo de coordenadas. En este caso el
mapeo debe hacerse del sistema abstracto de coordenadas de
OpenGL al sistema de coordenadas en ventana del sistema
operativo (window, UNIX, linux, mac, etc). El siguiente
esquema muestra tres posibles formas de realizar el mapeo de
coordenadas
El grafico muestra tres de las posibles formas de realizar el
mapeo las coordenadas. En el Modo 1, el punto (0,0) en
coordenadas de dibujo es el correspondiente al extremo
inferior izquierdo de la ventana y el punto (200,200) estará
en el extremo superior derecho. Tal vez es uno de los modos
que parece más “natural”
En el Modo 2, el punto (0,0) en coordenadas de dibujo es el
centro de la ventana y los puntos extremos estarán situados en
los cuatro cuadrantes, en (100,100) superior derecha,
(-100,100) superior izquierda, (-100.-100) inferior izquierda
y (100,-100) inferior derecha. Este modo es similar a la forma
en que lo muestra la cámara por defecto de OpenGL, con el
agregado del eje ‘z’ positivo “saliendo” de la pantalla.
En el Modo 3, el punto (0,0) en coordenadas de dibujo se
encuentra en el extremo superior izquierdo de la ventana y el
punto (200,200) corresponde al extremo inferior derecho. Hay
que notar, que en este modo el eje ‘y’ positivo se encuentra
“cabeza abajo”, es decir, cuando un punto aumenta su
coordenada ‘y’ va hacia abajo, no hacia arriba. Este modo es
usado generalmente por los dispositivos de hardware y es la
forma por defecto de GDI.
Estas son solo algunas formas de mapeo de coordenadas y en
cualquier caso y con un poco de matemáticas (matrices de
transformación) se puede pasar de cualquier modo de mapeo a
otro.
PROYECCION
Los monitores actuales de PC, los televisores, las pantallas
de PDA, de celulares y consolas portátiles son todos
dispositivos bidimensionales, la percepción 3d sobre estos
dispositivos se debe a un conjunto de “trucos” para engañar al
ojo humano y hacerle ver objetos “tridimensionales” sobre un
dispositivo bidimensional, el primero de estos trucos es la proyección. La proyección consiste en generar una imagen bidimensional de una escena tridimensional, algo así como sacarle una foto, o pintar un cuadro de la escena. Tal vez las dos mas conocidas y las que permite trabajar OpenGL directamente son la ortográfica y la perspectiva.
Proyección Ortográfica: En este tipo de proyección se trazan rayos paralelos al plano de proyección (son paralelos porque se considera la fuente de “luz”o centro de proyección en el infinito) y la imagen se forma con aquellos rayos que intersequen al objeto. Esto se ve mas claro en el diagrama
Proyección en Perspectiva: La fuente de rayos en este caso no
se encuentra en el infinito, sino que es un punto localizado
llamado punto de fuga. Los rayos que parten del punto de
fuga e intersecan al objeto son entonces los que formaran la
imagen sobre el plano de proyección
En la proyección en perspectiva los objetos sufren una
deformación por la distancia, a medida que los objetos se
alejan del plano de proyección “disminuyen” su tamaño justo de
la forma en que ocurre cuando un objetos se aleja de nuestros
ojos ( en la figura se muestra como los dos objetos a pesar de
ser de diferentes tamaños producen una imagen casi del mismo
tamaño sobre el plano de proyección, debido a la diferencia de
distancias), es por eso, que esta perspectiva es la mas
utilizada para dar una sensación de realismo, como la que se
necesitan en los juegos, simulaciones y animaciones.
En el caso de OpenGL, tanto en el modo de perspectiva como en
el ortográfico se limita la región del espacio sobre la que se
realizan los cálculos, a esta región se le llama volumen de
vista o volumen de recorte (clipping volume) y en el caso de
la perspectiva también se la llama frustrum por la forma que
tiene. Dicha región se especifica, ya que los objetos por
fuera de este campo a derecha o izquierda no aparecerán en
pantalla y aquellos muy lejanos generarán pocos rasgos, por lo
que de calcularse consumirían recursos innecesariamente (la
consideración de “lejano” depende del programador).
En el caso de la proyección ortográfica el volumen de vista
tiene forma de caja rectangular, por lo que se determina
fácilmente mediante 6 medidas: near, far, top, bottom, left,
right (cerca, lejos, arriba, abajo, izquierda, derecha) y en
el caso de proyección, tiene forma de pirámide truncada de
base rectangular, que puede ser determinada por el field of
view (campo de visión), el aspect ratio ( el alto del plano
mas cercano dividido el ancho), near y far.
Hay que anotar que ambos volúmenes se calculan a partir de la
posición del observador, que en el caso de OpenGL es la cámara.
También hay que observar que las dimensiones del plano más
cercano a la cámara pueden ser mayores o menores a las de la
ventana, por lo el mapeo de las condenadas no será con
relación uno a uno, adicionalmente OpenGL permite definir el
viewport (vista), es decir la región sobre la ventana en la
que se va a realizar el dibujado, que puede ser menor al
tamaño de la ventana.
Hasta este punto el tutorial ha mostrado algunos conceptos
básicos relacionados con la forma en que OpenGL trabaja los
gráficos tridimensionales, conceptos que posteriormente se
verán reflejados en las primeras aplicaciones que se realicen
con OpenGL. Es importante tomar en cuenta que un buen manejo
del álgebra lineal, los TDA como las pilas y conocimientos en
un lenguaje de programación como c++ permitirán avanzar más
rápidamente en el aprendizaje del API OpenGL