Etiquetas

C (31) Cpp (28) Linux (14) asm (8) Telegram (5) bot (5) libreria (5) Algoritmo (3) Errores comunes (3) python (3) Opengl (2) kali (2) Android (1) Snippet (1) nano (1) recursividad (1)

martes, 26 de diciembre de 2023

No se puede usar apt-get update

 /* Si les sale un mensaje como el siguiente en linux*/

W: Failed to fetch https://http.kali.org/kali/dists/kali-rolling/InRelease  Temporary failure resolving 'http.kali.org'

Hay que modificar /etc/resolv.conf y poner nameserver 8.8.8.8 agregandolo al final del archivo

jueves, 21 de diciembre de 2023

Hay que evitar el uso de scanf()


/*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

#include <stdio.h>

int main(){
int i=0;
//pongan algo como 50 10
scanf("%d",&i); printf("%d\n",i);
scanf("%d",&i); printf("%d\n");//este numero sera 10 sin preguntar
return 0;}
scanf("%d",&i);printf("%d\n);


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;}

sábado, 16 de diciembre de 2023

Estructura con Switch

#include <stdio.h>     
struct Ficha {   
char Nombre[80];
int  Num_unidades;  
int Precio_unidad;  
int Estado;  // 0 = moroso; 1 = atrasado; 2 = pagado };     

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);   

 switch  (Cliente[i].Estado)     {    
case 0 : printf ("Moroso");         break;    
case 1 : printf ("Atrasado");         break;
case 2 : printf ("Pagado");         break;    };     
  }   }      return 0; } 

copiar matriz a otra(sin resolver)

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

void gen_matriz (int** nuevo, int matriz[20] [20]){
int j, k, y;int dup;int num_elem[20];
nuevo = (int**) calloc(20, sizeof(int*));

for (y = 0; y < 20; y++){
num_elem[y] = 0;

for (k = 0; k < 20; k++){
dup = 0;j = 0;

while ((j < 20) && !dup){
if (k != j){
dup = matriz[y][k] == matriz[y][j];
printf ("y=%i %i %i\n",y, j, dup);}
j++;}

printf ("dup %i\n", dup);

if (!dup){
num_elem[y]++;
if (nuevo[y] == NULL) nuevo[y] = (int*) malloc(sizeof (int));
else
nuevo[y] = (int*) realloc(nuevo[y], num_elem[y] * sizeof (int));
int indice = num_elem[y] - 1;
nuevo[y][indice] = matriz[y][k];
printf (" posicion %i %i : %i\n", y, k, nuevo [y] [indice]);}
                }

        }

for(y = 0; y < 20; y++)
for(k = 0; k < num_elem[y]; k++)
printf("nuevo[%i][%i] = %i\n", y, k, nuevo[y][k]);
}

Tres en raya

 #include <stdio.h> int main(){ char c1,c2,c3,c4,c5,c6,c7,c8,c9,movimiento,marcajugador; char jugar_otra; int turno_jugador; c1='1';c2='2';c3='3';c4='4';c5='5';c6='6';c7='7';c8='8';c9='9'; turno_jugador=1; bool juegoterminado(true),juego_ganado(true),movalido; do{ 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");  if(turno_jugador==1)//Marca Jugador {marcajugador= 'X';} else{marcajugador= 'O';} printf("Jugador: %d Movimiento: ",turno_jugador);  do{ scanf("%c",&movimiento); movalido=true; //Checar movimientos if (movimiento == '1' && c1 == '1') {c1 = marcajugador;} 

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); }

Simulador Sistema Operativo

 /***********************************************

 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]*/

domingo, 10 de diciembre de 2023

Primeros pasos en Opengl

/*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