Ordenar un arreglo de objetos con base en un campo específico en Ruby

julio 3, 2018

Decidí hacer este post a raíz de algo que tuve que hacer cuando desarrollé el sistema Clepsidra. Lo que aquí muestro no es exactamente lo mismo, aquí está el concepto básico esperando que pueda servir para solucionar casos similares que se le puedan presentar a alguien más.

Supongamos que tenemos la siguiente información en formato json:

'[
  {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P210","nombre_profesor":"Dennis Ritchie"},
  {"clave_asignatura":"U-101","nombre_asignatura":"Unix avanzado","clave_profesor":"P210","nombre_profesor":"Dennis Ritchie"},
  {"clave_asignatura":"DB-101","nombre_asignatura":"Introducción a las bases de datos relacionales","clave_profesor":"P205","nombre_profesor":"Edgar Frank Codd"},
  {"clave_asignatura":"SO-101","nombre_asignatura":"Sistemas operativos","clave_profesor":"P225","nombre_profesor":"Linus Torvalds"},
  {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P235","nombre_profesor":"Brian Kernighan"},
  {"clave_asignatura":"SL-101","nombre_asignatura":"Introducción al software libre","clave_profesor":"P215","nombre_profesor":"Richard M. Stallman"},
  {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P230","nombre_profesor":"Ken Thompson"},
  {"clave_asignatura":"SO-101","nombre_asignatura":"Sistemas operativos","clave_profesor":"P220","nombre_profesor":"Andrew S. Tanenbaum"},
  {"clave_asignatura":"L-101","nombre_asignatura":"Linux básico","clave_profesor":"P225","nombre_profesor":"Linus Torvalds"},
  {"clave_asignatura":"U-101","nombre_asignatura":"Unix avanzado","clave_profesor":"P230","nombre_profesor":"Ken Thompson"}
 ]'

Son 10 registros, cada uno con 4 campos: clave_asignatura, nombre_asignatura, clave_profesor y nombre_profesor.

Esta información en formato json la pudimos haber obtenido desde un archivo o desde una base de datos, etc. eso es irrelevante. Como se puede observar, hay asignaturas que aparecen más de una vez, ya que una misma asignatura puede ser impartida por diferentes profesores, y debido a que un profesor puede impartir diferentes asignaturas, también hay profesores que aparecen más de una vez.

Supongamos que a partir de esta información tenemos que obtener una lista de las diferentes asignaturas ordenada por clave de asignatura. Es decir, en la lista ordenada, cada asignatura debe aparecer sólo una vez.

Lo primero que tenemos que hacer es convertir la información a un arreglo de hashes.

@json_data = '[
               {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P210","nombre_profesor":"Dennis Ritchie"},
               {"clave_asignatura":"U-101","nombre_asignatura":"Unix avanzado","clave_profesor":"P210","nombre_profesor":"Dennis Ritchie"},
               {"clave_asignatura":"DB-101","nombre_asignatura":"Introducción a las bases de datos relacionales","clave_profesor":"P205","nombre_profesor":"Edgar Frank Codd"},
               {"clave_asignatura":"SO-101","nombre_asignatura":"Sistemas operativos","clave_profesor":"P225","nombre_profesor":"Linus Torvalds"},
               {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P235","nombre_profesor":"Brian Kernighan"},
               {"clave_asignatura":"SL-101","nombre_asignatura":"Introducción al software libre","clave_profesor":"P215","nombre_profesor":"Richard M. Stallman"},
               {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P230","nombre_profesor":"Ken Thompson"},
               {"clave_asignatura":"SO-101","nombre_asignatura":"Sistemas operativos","clave_profesor":"P220","nombre_profesor":"Andrew S. Tanenbaum"},
               {"clave_asignatura":"L-101","nombre_asignatura":"Linux básico","clave_profesor":"P225","nombre_profesor":"Linus Torvalds"},
               {"clave_asignatura":"U-101","nombre_asignatura":"Unix avanzado","clave_profesor":"P230","nombre_profesor":"Ken Thompson"}
              ]'

@materias_profesores = JSON.parse(@json_data)

En el código anterior, la información en formato json la tenemos en la variable @json_data y ya como un arreglo de hashes la tenemos en la variable @materias_profesores

Si lo deseamos, podemos recorrer nuestro arreglo de hashes con el siguiente código para mostrar la información

@materias_profesores.each do |registro|
   puts registro["clave_asignatura"]+": "+registro["nombre_asignatura"]
   puts registro["clave_profesor"]+": "+registro["nombre_profesor"]
end

Para obtener la lista de asignaturas sin repetir lo que vamos a hacer es recorrer nuestro arreglo de hashes e ir agragando la clave de asignatura y su nombre a otro arreglo. Este nuevo arreglo será un arreglo de objetos en donde cada objeto sólo tendra dos campos, la clave de asignatura y el nombre de asignatura. Así que creamos la siguiente clase

class Materia
   attr_accessor :clave_asignatura, :nombre_asignatura
   
   def initialize(clave, nombre)
       @clave_asignatura = clave
       @nombre_asignatura = nombre
   end
end

Crearemos un arreglo llamado @asignaturas, en éste arreglo iremos agregando objetos de la clase Materia.

Como ya comenté antes, recorreremos nuestro arreglo @materias_profesores y antes de crear e insertar un objeto de la clase Materia a nuestro arreglo llamado @asignaturas, verificamos que no exista ya un objeto con esa información, así garantizamos que cada asignatura sólo aparezca una vez.

@asignaturas = []
@materias_profesores.each do |registro|
    # Sólo agrega la asignatura si no se encuentra ya en el arreglo @asignaturas
    if @asignaturas.all? {|asignatura| asignatura.clave_asignatura != registro["clave_asignatura"]}
       @asignaturas.push(Materia.new(registro["clave_asignatura"],registro["nombre_asignatura"]))
    end
end

Hasta ahora ya tenemos un arreglo de objetos de la clase Materia (nuestro arreglo llamado @asignaturas) en donde existe un objeto por cada una de las diferentes asignaturas.

Podemos usar el siguiente código si queremos mostrar el contenido de nuestro arreglo @asignaturas

puts "\n"
puts "="*20
puts "ASIGNATURAS"
puts "="*20
@asignaturas.each do |asignatura|
   puts asignatura.clave_asignatura+": "+asignatura.nombre_asignatura
end

Ahora sólo falta ordenar nuestro arreglo de objetos por el campo clave_asignatura

@asignaturas.sort! {|a, b| a.clave_asignatura <=> b.clave_asignatura}

Programa completo

#encoding: utf-8
require 'json'

class Materia
   attr_accessor :clave_asignatura, :nombre_asignatura
   
   def initialize(clave, nombre)
       @clave_asignatura = clave
       @nombre_asignatura = nombre
   end
end

@json_data = '[
               {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P210","nombre_profesor":"Dennis Ritchie"},
               {"clave_asignatura":"U-101","nombre_asignatura":"Unix avanzado","clave_profesor":"P210","nombre_profesor":"Dennis Ritchie"},
               {"clave_asignatura":"DB-101","nombre_asignatura":"Introducción a las bases de datos relacionales","clave_profesor":"P205","nombre_profesor":"Edgar Frank Codd"},
               {"clave_asignatura":"SO-101","nombre_asignatura":"Sistemas operativos","clave_profesor":"P225","nombre_profesor":"Linus Torvalds"},
               {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P235","nombre_profesor":"Brian Kernighan"},
               {"clave_asignatura":"SL-101","nombre_asignatura":"Introducción al software libre","clave_profesor":"P215","nombre_profesor":"Richard M. Stallman"},
               {"clave_asignatura":"C-101","nombre_asignatura":"Introducción al lenguaje de programción C","clave_profesor":"P230","nombre_profesor":"Ken Thompson"},
               {"clave_asignatura":"SO-101","nombre_asignatura":"Sistemas operativos","clave_profesor":"P220","nombre_profesor":"Andrew S. Tanenbaum"},
               {"clave_asignatura":"L-101","nombre_asignatura":"Linux básico","clave_profesor":"P225","nombre_profesor":"Linus Torvalds"},
               {"clave_asignatura":"U-101","nombre_asignatura":"Unix avanzado","clave_profesor":"P230","nombre_profesor":"Ken Thompson"}
              ]'

@materias_profesores = JSON.parse(@json_data)

@materias_profesores.each do |registro|
   puts registro["clave_asignatura"]+": "+registro["nombre_asignatura"]
   puts registro["clave_profesor"]+": "+registro["nombre_profesor"]
end

@asignaturas = []
@materias_profesores.each do |registro|
   # Sólo agrega la asignatura si no se encuentra ya en el arreglo @asignaturas
   if @asignaturas.all? {|asignatura| asignatura.clave_asignatura != registro["clave_asignatura"]}
      @asignaturas.push(Materia.new(registro["clave_asignatura"],registro["nombre_asignatura"]))
   end
end

puts "\n"
puts "="*20
puts "ASIGNATURAS"
puts "="*20
@asignaturas.each do |asignatura|
   puts asignatura.clave_asignatura+": "+asignatura.nombre_asignatura
end

# Ordena el arreglo @asignaturas por el campo clave_asignatura
@asignaturas.sort! {|a, b| a.clave_asignatura <=> b.clave_asignatura}

puts "\n"
puts "="*20
puts "ASIGNATURAS ORDENADAS POR CLAVE"
puts "="*20
@asignaturas.each do |asignatura|
   puts asignatura.clave_asignatura+": "+asignatura.nombre_asignatura
end

Quien quiera practicar, puede hacer una versión de este programa en donde utilizando la misma información en formato json, obtenga una lista de los diferentes profesores ordenada por el campo nombre_profesor

 

Anuncios

Creación de un calendario en HTML usando Ruby

junio 22, 2018

En este post voy a mostrar un programa que desarrollé en Ruby que recibe por teclado un año y genera un archivo html que contiene el calendario correspondiente a dicho año.

Saber si un año es bisiesto

Para generar el calendario necesitamos saber si el año en cuestión es bisiesto o no para tomar en cuenta 28 o 29 días en el mes de Febrero.

Hay dos casos en los que un año es bisiesto:

  1. Si es divisible entre 4 pero no entre 100 (es decir, si dividimos el año entre 4 y el residuo es cero, pero si lo dividimos entre 100 y el residuo no es cero)
  2. Si es divisible entre 400

La siguiente función recibe como parámetro un año; regresa verdadero si dicho año es bisiesto y regresa falso en caso contrario.

def Bisiesto(year)
    es_bisiesto = nil
    
    if (year%4 == 0 and year%100 !=0) or year%400 == 0
        es_bisiesto = true
    else
        es_bisiesto = false
    end
    
    return es_bisiesto
end

A continuación muestro una función que recibe como parámetro un año y un número de mes (considerando Enero = 1, Febrero = 2, etc.) y regresa el número de días que contiene ese mes en ese año. Cuando el mes es Febrero, utiliza la función Bisiesto descrita anteriormente para saber si regresa 28 o 29.

def DiasMes(mes, year)
    dias = 30
    
    case mes
         when 1,3,5,7,8,10,12 then dias = 31
         when 2 then
                if Bisiesto(year)
                   dias = 29
                else
                    dias = 28
                end
    end

    return dias
end

Saber que día de la semana es una fecha específica

Con las dos funciones descritas hasta ahora, ya podemos crear un programa que solicite al usuario que teclee un año y mediante un ciclo del 1 al 12 (los meses del año) obtener el número de días que contiene cada mes en ese año (realmente para cualquier año el único mes que puede tener diferentes días es Febrero dependiendo de si es bisiesto o no). Pero necesitamos saber que día de la semana es el primer día de cada mes para ese año; para eso haremos un función en donde implementaremos la regla de Zeller.

Para saber más sobre los casos en que se da un año bisiesto y sobre la regla de Zeller les recomiendo consultar este enlace The Calendar and the Days of the Week

La función recibe como parámetros un número de día, número de mes y un año. Utilizando la regla de Zeller regresa el número del día de la semana empezando con Domingo = 0

def DiaSemana(dia, mes, year)   
    ajuste = (14-mes)/12
    mm = mes+(12*ajuste)-2
    yy = year-ajuste
    
    return (dia+(((13*mm)-1)/5)+yy+(yy/4)-(yy/100)+(yy/400))%7
end

Si a la función DiaSemana le paso como parámetros la fecha de hoy (22, 6, 2018) me regresa el número 5, lo que significa que el 22 de Junio del año 2018 es Viernes.

El archivo html que generará nuestro programa contendrá una tabla para cada uno de los meses; para tener como encabezado de cada tabla el nombre del mes, haremos una función más que reciba como parámetro el número del mes y regrese el nombre considerando 1 = Enero, 2 = Febrero, etc.

Convertir un número de mes a su nombre correspondiente

def MesNumero(numero)
    mes = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
    
    if (1..12).include?(numero)
        return mes[numero-1]
    else
        return "Número inválido"
    end
end

Programa completo

Con eso tenemos todas las funciones que necesitamos. A continuación muestro el programa completo. Después de las funciones está el código en donde se pide al usuario que teclee un año y después genera el archivo html que contendrá el calendario correspondiente a ese año.

Programa calendar.rb

#encoding: utf-8

# Recibe como parámetro un año
# Regresa verdadero si dicho año es bisiesto y regresa falso en caso contrario
# Hay dos casos en que un año es bisiesto:
# caso 1: Si es divisible entre 4 pero no entre 100
# caso 2: Si es divisible entre 400
def Bisiesto(year)
    es_bisiesto = nil

    if (year%4 == 0 and year%100 !=0) or year%400 == 0
        es_bisiesto = true
    else
        es_bisiesto = false
    end
    
    return es_bisiesto
end

# Recibe como parámetros un mes y año
# Regresa el número de días que contiene ese mes en ese año tomando en cuenta si es año bisiesto o no
def DiasMes(mes, year)
    dias = 30
    
    case mes
         when 1,3,5,7,8,10,12 then dias = 31
         when 2 then
              if Bisiesto(year)
                 dias = 29
              else
                  dias = 28
              end
         end
    
    return dias
end

# Recibe como parámetros un número
# Regresa el nombre del mes correspondiente al número que recibe (1 = Enero, 2 = Febrero, etc.)
def MesNumero(numero)
    mes = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
    
    if (1..12).include?(numero)
        return mes[numero-1]
    else
        return "Número inválido"
    end
end

# Recibe como parámetros un día, mes y año
# Utiliza la regla de Zeller para regresar el número del día de la semana empezando con Domingo = 0
def DiaSemana(dia, mes, year)
    ajuste = (14-mes)/12
    mm = mes+(12*ajuste)-2
    yy = year-ajuste
    
    return (dia+(((13*mm)-1)/5)+yy+(yy/4)-(yy/100)+(yy/400))%7
end

puts "Año:"
anio = gets.chomp.to_i

File.open('calendario'+anio.to_s+'.html','w') do |linea|
     dia_semana = nil
     dias_mes = nil
     
     linea.puts '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
     linea.puts '<html xmlns="http://www.w3.org/1999/xhtml">'
     linea.puts '<head>'
     linea.puts '<title>Calendario</title>'
     linea.puts '</head>'
     linea.puts '<body>'
     linea.puts '<h2>Calendario '+anio.to_s+'</h2>'
     (1..12).each do |mes|
             dia_semana = DiaSemana(1,mes,anio)
             dias_mes = DiasMes(mes, anio)
             
             linea.puts ' <table>'
             linea.puts ' <thead>'
             linea.puts ' <tr>'
             linea.puts ' <th colspan="7">'+MesNumero(mes)+'</th>'
             linea.puts ' </tr>'
             linea.puts ' <tr>'
             linea.puts ' <th>D</th>'
             linea.puts ' <th>L</th>'
             linea.puts ' <th>M</th>'
             linea.puts ' <th>M</th>'
             linea.puts ' <th>J</th>'
             linea.puts ' <th>V</th>'
             linea.puts ' <th>S</th>'
             linea.puts ' </tr>'
             linea.puts ' </thead>'
             linea.puts ' <tbody>'
             linea.puts ' <tr>'
             if dia_semana > 0
                for i in 1..dia_semana
                    linea.puts ' <td></td>'
                end
             end
             j = dia_semana
             for dia in 1..dias_mes
                 linea.puts ' <td style="text-align: right;">'+dia.to_s+'</td>'
                 j += 1
                 if j == 7
                    linea.puts ' </tr>'
                    j = 0
                    if dia < dias_mes
                       linea.puts ' <tr>'
                    end
                 end
             end
             if j != 0
                linea.puts ' </tr>'
             end
             linea.puts ' </tbody>'
             linea.puts ' </table>'
             linea.puts ' <br>'
     end
     linea.puts '</body>'
     linea.puts '</html>'
end

puts "\nSe generó el archivo calendario#{anio}.html"

 

El operador condicional en C

junio 20, 2018

El operador condicional ?: tiene tres operandos, lo que significa que es un operador ternario.

La forma general de éste operador es:

expresion1 ? expresion2 : expresion3

Funciona de la siguiente forma:

Se evalúa expresion1, si el resultado de la evaluación es verdadero (diferente de cero), se ejecuta expresion2; si el resultado de la evaluación de expresion1 es falso (igual a cero), se ejecuta expresion3.

Ejemplo:

printf("%s\n", calificacion >=70 ? "Aprobado" : "Reprobado");

En la instrucción anterior, si el valor de la variable calificacion es mayor o igual a 70, se imprime la cadena “Aprobado”, en caso contrario se imprime la cadena “Reprobado”.

El siguiente programa muestra otro ejemplo del uso del operador condicional

#include <stdio.h>
int main()
{
 int num1=0, num2=0, mayor=0;
 
 printf("Introduzca dos números enteros\n");
 scanf("%d%d",&num1,&num2);
 mayor = (num1 >= num2 ? num1 : num2);
 printf("El número mayor es %d\n",mayor);
 
 return 0;
}

 

FreeBSD como servidor web en una PC con pocos recursos

abril 20, 2018

Dentro de la gran cantidad de software libre que existe hoy en día, se encuentran algunos sistemas operativos bastante eficientes y poderosos como los de la familia BSD (FreeBSD, OpenBSD, NetBSD, etc.) y las distribuciones GNU/Linux. Es bien sabido que con este tipo de sistemas operativos podemos aprovechar computadoras con bajas prestaciones en las cuales los sistemas operativos privativos más conocidos no pueden instalarse.

Muchos creen que el único uso que se le podría dar a una PC con procesador Pentium 4 o inferior sería como firewall, router, o algo parecido.

Aquí les dejo un video en donde muestro una PC con procesador Pentium II a 400 Mhz con sólo 128 Mb de RAM en la que instalé FreeBSD 11.1 (la última versión al momento), nginx, y el sistema ANI (Administración de Negocios Inteligente).

Cuidado con el phising

febrero 23, 2018

Por si algún lector no sabe qué es el “phising”, aquí lo pueden checar http://www.phishing.org/what-is-phishing.

En esta ocasión voy a escribir sobre un correo que llegó a una de mis cuentas de correo electrónico y que simulaba provenir de Facebook. El título del correo decía “406045 es el código de recuperación de tu cuenta de Facebook“.

Obviamente a Ud. le puede llegar un número diferente como supuesto código de recuperación.

Les dejo una imágen del contenido del correo

Si Ud. no solicitó recuperar su contraseña de Facebook (al igual que en mi caso), haga lo siguiente.

En el correo aparecen tres enlaces:

  1. Haz clic aquí para cambiar tu contraseña (si, está mal escrito, no dice click, sino clic)
  2. Infórmanos
  3. Cambiar contraseña

No haga click en ningún enlace que viene en el correo, vaya directamente a su navegador web y teclee la url http://www.facebook.com e intente ingresar a su cuenta de Facebook con su contraseña y verá que entra sin problema.

Elimine ese correo.

Dicen por ahí que el sentido común es el menos común de los sentidos; ¿será?.

Cuando las buenas intenciones no bastan

febrero 7, 2018

Soy un entusiasta del software libre (por si no se han dado cuenta) y me da gusto ver cuando otras personas u organizaciones intentan difundir el software libre.  En Facebook vi una publicidad de una organización (no voy a decir cual para no quemarlos, ya que esa no es mi intención) que anunciaba un curso de GNU/Linux (aunque ellos pusieron sólamente Linux) y entre otras cosas, escribieron textualmente lo siguiente:

“Aprende a manejar un sistema operativo con las mejores características:
Es gratis (no pagas licencias/software libre) ,seguro, rápido, estable.”

Cuando escribí un comentario en su publicación haciendoles la observación de que su publicidad insinuaba que software libre es sinónimo de software gratis y que eso era falso, que sería bueno que lo corrigieran y les sugerí que leyeran un post en donde estaba una explicación más detallada sobre esto (me refiero al post Libre no significa “gratis” ni “sin licencia”, escrito por mi, pero eso no lo dije en ese momento), marcaron mi comentario como spam.

Voy a poner textualmente la conversación omitiendo su identidad así que los llamaré ELLOS

Salomón Rincón Sería bueno que modificaran su publicidad porque así como está insinúa que software libre es sinónimo de software gratis, y eso es falso, si bien la mayoría de las distribuciones GNU/Linux son gratis, hay algunas que no lo son, y no por eso dejan de ser software libre. Lean este post para que quede completamente claro https://salomonrt.wordpress.com/…/libre-no-significa…/

Salomón Rincón jaja, si uno los corrige marcan el comentario como spam, que lástima

Salomón Rincón Enterense bien de qué es el software libre antes de insinuar que software libre significa software gratis por favor y tengan la suficiente humildad para aceptar que alguien más les haga un comentario haciendoles una observación de que están equivocados en algo y no lo marquen como spam.

ELLOS: Hola Salomon… me parece prudente que tus comentarios puedan ser puntualizados con voz y en persona…dejar seudo-aclaraciones en un post en facebook no aclara y mucho menos se puede considerar una “corrección”…lamentamos que tu fuente de información tan solo sea un blog…te invitamos a realizar una investigacion metodologica mas profunda con el unico objetivo de conocer el tema ampliamente y poder opinar adecuadamente como una persona reflexiva…esperamos que podamos platicar al respecto en una conversación con mayor profundidad…saludos Salomón…excelente día

Salomón Rincón Tengo una maestría en Software Libre, así que se de “investigación metodológica” (algo que aparentemente Uds. desconocen) y ese blog es el que yo escribo, con la única intención de difundir el software libre y combatir la desinformación que posts como el suyo propagan, que tengan excelente día también y realmente les sugiero que lean qué es el software libre, si no quieren leer mi post, pueden leer la definición en la página de la Free Software Foundation, organización creada por Richard Stallman.

ELLOS: Lamentamos que lo primero que respondes sea tu nivel de estudios…preferimos omitir nuestro nivel de estudios para no parecer personas que intentan ser superiores en pensamiento y habilidades…insistimos discutir estas cuestiones en el post no abona a una investigacion cientifica formal…solicitamos una conversación presencial para que conozcas el proyecto de ELLOS y no lo juzgues sin conocerlo…excelente dia Salomón..

Salomón Rincón Mencioné mi nivel de estudios porqué intentaron descalificarme con “lamentamos que tu fuente de información tan solo sea un blog”, espero que mencionando mi nivel de estudios quede claro que mis fuentes de información no son blogs. No hace falta una investigación científica formal para reconocer que Software Libre no es sinónimo de software gratis.

Yo no estoy juzgando “el proyecto de ELLOS“, sólo hice la observación de que su publicidad insinúa que el termino software libre significa que dicho software es gratis, y que eso no es asi, y que sería bueno que lo corrigieran, sólo eso, y que podían leer una explicación más detallada en un post de un blog, ni siquiera dije que era mi blog, ni mencioné mi nivel de estudios, pero marcaron mi comentario como spam porque al parecer no les gustó que les hiciera dicha observación y después de que les dije que qué lástima que marquen como spam un comentario que les hace una observación de que software libre no es sinónimo de software gratis empezaron a atacarme

ELLOS: Una disculpa si te has sentido atacado…la argumentación seria muchas veces puede hacernos sentir confrontados…no seguiremos comentando y te volvemos a invitar para platicar sobre este gran tema del software libre…saludos Salomón

Salomón Rincón Como ya lo dije, en lugar de enojarse porque alguien les hace una corrección, deberían reconocerla, aceptarla y enmendar el error, no atacar a la persona que les hizo la observación. Pero como también ya dije, eso requiere humildad, y también madurez, cosa que al parecer no tienen

ELLOS: Nosotros no pretendemos que enmiendes tu “error”…al parecer la definición de humildad y madurez no se lleva con personas que insisten en que las demás personas estan en un “error” sin platicar el tema…saludos Salomón

Salomón Rincón Pensé que estabamos platicando el tema, sería interesante que expusieras tus argumentos para defender tu postura de que software libre es sinónimo de software gratis, yo si tengo argumentos y fuentes de información, ya mencioné la Free Software Foundation, que respaldan mi aseveración de que software libre no es sinónimo de software gratis.

Y de paso, por favor dime cual es mi error del que hablas, y si estoy en un error lo aceptaré al contrario de Uds.

ELLOS: Ya te hemos contestado al respecto..saludos Salomón. Te esperamos en ELLOS!!!!

Salomón Rincón Ok, pues parece que al no tener argumentos decidieron “no seguir comentando”

ELLOS: Pffff…sin palabras…

Como pueden ver, como no tuvieron argumentos ni fuentes con que respaldar su información dijeron que no iban a seguir comentando, en pocas palabras me iban a ignorar, que me invitaban a sus instalaciones a discutir sobre Software Libre.

Comparto esto para hacer incapié en que el tipo de desinformación de la publicidad de este curso más que ayudar al software libre, le hace daño. Que bueno que den un curso sobre GNU/Linux, pero que mal que desinformen a las personas insinuando que software libre es sinónimo de software gratis, y todavía peor que lejos de reconocer su ignorancia, aceptar su error y enmendarlo, ataquen a quien en buena onda les hace la observación, están graves.

Así que cuidado con lo que leemos en Facebook y si vamos a debatir sobre un tema, hay que aegurarse de que lo conocemos lo suficiente, no sea que con quien vamos a debatir si sepa del tema y el querer descalificarlo con argumentos como “lamentamos que tu fuente de información tan solo sea un blog…te invitamos a realizar una investigacion metodologica mas profunda con el unico objetivo de conocer el tema ampliamente y poder opinar…” no convenza a quienes puedan leer o escuchar el debate, tampoco el insinuar que tenemos estudios superiores a los que tiene la persona con quien debatimos pero por no presumir no los mencionamos, cuando los que leen lo que escribimos ven que no ponemos acentos en “investigación”, “único”, etc.

Hay que reconocer cuando no tenemos la razón :)

Manejo de verdadero y falso en C

enero 24, 2018

En ANSI C e incluso en ISO C90, no existe el tipo bool (en ISO C99 y posteriores ya está definido y para utilizarlo hay que incluir la biblioteca stdbool.h); así que el compilador maneja verdadero y falso de la siguiente forma:

Cero es falso y cualquier valor diferente de cero es verdadero.

Tomaré el siguiente programa como base para que quede claro

#include <stdio.h>

int main()
{
 int x=0;
 
 if (x)
     printf("La expresión se evaluó como verdadera\n");
 else
     printf("La expresión se evaluó como falsa\n");
 
 return 0;
}

Al ejecutar este programa, se mostrará la leyenda “La expresión se evaluó como falsa”, ya que se está asignando a x el valor cero; si en lugar de int x=0 ponemos int x=1, entonces al ejecutar el programa se mostrará la leyenda “La expresión se evaluó como verdadera”, y lo mismo sucederá si ponemos int x=-4 ó int x=200, ya que 1, -4 y 200 son diferentes de cero (y anteriormente expliqué que en C, cero es falso y cualquier valor diferente de cero es verdadero).

Si queremos manejar en nuestros programas cero como falso y uno como verdadero (ya no culaquier valor diferente de cero, sino específicamente uno) podemos definir unas constantes llamadas FALSE y TRUE por ejemplo y nuestro programa podría quedar de la siguiente forma:

#include <stdio.h>
#define FALSE 0
#define TRUE 1

int main()
{
 int x=TRUE;
 
 if (x==TRUE)
     printf("x es verdadera\n");
 else
     if (x==FALSE)
         printf("x es falsa\n");
     else
         printf("x tiene un valor diferente a TRUE y a FALSE\n");
 
 return 0;
}

En el programa estamos verificando explícitamente si x tiene asignado el valor FALSE, con lo que nos aseguramos que no asuma que x es falsa si no tiene asignado el valor TRUE ya que podemos tener int x=-2 o int x=400 por ejemplo; casos en donde no queremos que se imprima la leyenda “x es falsa”.

Otra opción es que creemos el tipo boolean con un enum como se muestra en el siguiente programa:

#include <stdio.h>

typedef enum {FALSE, TRUE} boolean;
int main()
{
 boolean x=FALSE;
 
 if (x==TRUE)
     printf("x es verdadera\n");
 else
     if (x==FALSE)
         printf("x es falsa\n");
     else
         printf("x tiene un valor diferente a TRUE y a FALSE\n");
 
 return 0;
}

Ya definido el tipo boolean de la forma en que lo hicimos en este último programa, x=FALSE es equivalente a poner x=0, y x=TRUE es equivalente a poner x=1.

El operador % en C

noviembre 29, 2017

A los que están iniciando con la programación en C, les dejo un video sobre el uso del operador mod (módulo) en C.

Curso de arreglos en C usando Linux

noviembre 25, 2017

Un tema que muchas veces es complicado para quienes están aprendiendo a programar en C es el manejo de arreglos. Aquí les dejo un enlace a un curso que tiene un precio en pesos mexicanos bastante accesible (menos de 10 dólares americanos) y ofrece acceso a los primeros dos capítulos de forma gratuita, chequenlo

Curso de arreglos en C

Este es uno de los videos del curso