Changed c-es to utf8

This commit is contained in:
Adam 2013-08-05 08:33:24 -07:00
parent aef1608362
commit c10f6a6888

View File

@ -4,23 +4,23 @@ filename: learnc.c
contributors: contributors:
- ["Adam Bard", "http://adambard.com/"] - ["Adam Bard", "http://adambard.com/"]
translators: translators:
- ["Francisco García", "http://flaskbreaker.tumblr.com/"] - ["Francisco García", "http://flaskbreaker.tumblr.com/"]
lang: es-es lang: es-es
--- ---
¡Ah!, C. Aun hoy en día sigue siendo el lenguaje por excelencia de la ¡Ah!, C. Aun hoy en día sigue siendo el lenguaje por excelencia de la
computación moderna de alto rendimiento. computación moderna de alto rendimiento.
C es el lenguaje de más bajo nivel que la mayoría de los programadores C es el lenguaje de más bajo nivel que la mayoría de los programadores
llegarán a usar, pero lo compensa de sobra con pura velocidad. Solo llegarán a usar, pero lo compensa de sobra con pura velocidad. Solo
ten en cuenta el manejo manual de memoria y te llevará tan lejos como ten en cuenta el manejo manual de memoria y te llevará tan lejos como
necesites. necesites.
```c ```c
// Los comentarios de una sola línea comienzan con // // Los comentarios de una sola línea comienzan con //
/* /*
Los comentarios multilínea tienen este aspecto. Los comentarios multilínea tienen este aspecto.
*/ */
// Importa cabeceras con #include // Importa cabeceras con #include
@ -33,12 +33,12 @@ Los comentarios multil
void function_1(); void function_1();
void function_2(); void function_2();
// El punto de entrada de tu programa es una función llamada main con // El punto de entrada de tu programa es una función llamada main con
// retorno de tipo entero (integer). // retorno de tipo entero (integer).
int main() { int main() {
// Muestra la salida usando printf, para el "formato print" // Muestra la salida usando printf, para el "formato print"
// %d es un entero, \n es una nueva línea // %d es un entero, \n es una nueva línea
printf("%d\n", 0); // => Muestra 0 printf("%d\n", 0); // => Muestra 0
// Todas las sentencias deben terminar con un punto y coma. // Todas las sentencias deben terminar con un punto y coma.
@ -46,9 +46,9 @@ printf("%d\n", 0); // => Muestra 0
// Tipos // Tipos
/////////////////////////////////////// ///////////////////////////////////////
// Tienes que declarar una variable antes de usarla. La declaración de una // Tienes que declarar una variable antes de usarla. La declaración de una
// variable necesites que especifiques su tipo; el tipo de una variable // variable necesites que especifiques su tipo; el tipo de una variable
// determina su tamaño en bytes. // determina su tamaño en bytes.
// 'ints' (enteros) son normalmente de 4 bytes // 'ints' (enteros) son normalmente de 4 bytes
int x_int = 0; int x_int = 0;
@ -65,53 +65,53 @@ char y_char = 'y'; // Los caracteres literales se entrecomillan con ''
long x_long = 0; long x_long = 0;
long long x_long_long = 0; long long x_long_long = 0;
// 'floats' son normalmente números de coma flotante de 32 bits // 'floats' son normalmente números de coma flotante de 32 bits
float x_float = 0.0; float x_float = 0.0;
// 'doubles' son normalmente números de coma flotante de 64 bits // 'doubles' son normalmente números de coma flotante de 64 bits
double x_double = 0.0; double x_double = 0.0;
// Todos los tipos enteros pueden ser 'unsigned'. Esto significa que no // Todos los tipos enteros pueden ser 'unsigned'. Esto significa que no
// pueden ser negativos, pero el valor máximo de una variable 'unsigned' // pueden ser negativos, pero el valor máximo de una variable 'unsigned'
// es mayor que el de una no 'unsigned' del mismo tamaño. // es mayor que el de una no 'unsigned' del mismo tamaño.
unsigned char ux_char; unsigned char ux_char;
unsigned short ux_short; unsigned short ux_short;
unsigned int ux_int; unsigned int ux_int;
unsigned long long ux_long_long; unsigned long long ux_long_long;
// Todos menos 'char', que es siempre de 1 byte, varían el tamaño // Todos menos 'char', que es siempre de 1 byte, varían el tamaño
// dependiendo de tu máquina. sizeof(T) te dice el tamaño de una variable // dependiendo de tu máquina. sizeof(T) te dice el tamaño de una variable
// de tipo T en bytes por lo que podemos expresar el tamaño de estos tipos // de tipo T en bytes por lo que podemos expresar el tamaño de estos tipos
// portatilmente. // portatilmente.
// Por ejemplo, // Por ejemplo,
printf("%lu\n", sizeof(int)); // => 4 (en máquinas con 'words' de 4 bytes) printf("%lu\n", sizeof(int)); // => 4 (en máquinas con 'words' de 4 bytes)
// Los arrays deben ser inicializados con un tamaño concreto. // Los arrays deben ser inicializados con un tamaño concreto.
char my_char_array[20]; // Este array ocupa 1 * 20 = 20 bytes char my_char_array[20]; // Este array ocupa 1 * 20 = 20 bytes
int my_int_array[20]; // Este array ocupa 4 * 20 = 80 bytes int my_int_array[20]; // Este array ocupa 4 * 20 = 80 bytes
// (suponiendo que tenemos 'words' de 4-byte) // (suponiendo que tenemos 'words' de 4-byte)
// Puedes inicializar un array a 0 así: // Puedes inicializar un array a 0 así:
char my_array[20] = {0}; char my_array[20] = {0};
// Indexar un array es como en otros lenguajes -o, más bien, otros // Indexar un array es como en otros lenguajes -o, más bien, otros
// lenguajes son como C- // lenguajes son como C-
my_array[0]; // => 0 my_array[0]; // => 0
// Los arrays varían; ¡son sólo memoria! // Los arrays varían; ¡son sólo memoria!
my_array[1] = 2; my_array[1] = 2;
printf("%d\n", my_array[1]); // => 2 printf("%d\n", my_array[1]); // => 2
// Las cadenas (strings) son sólo arrays de 'chars' (caracteres) // Las cadenas (strings) son sólo arrays de 'chars' (caracteres)
// terminados en un byte NUL (0x00), representado en las cadenas como el carácter especial '\0'. // terminados en un byte NUL (0x00), representado en las cadenas como el carácter especial '\0'.
// (No tenemos porqué añadir el byte nulo en cadenas literales; el // (No tenemos porqué añadir el byte nulo en cadenas literales; el
// compilador lo añade al final por nosotros.) // compilador lo añade al final por nosotros.)
char a_string[20] = "Esto es una cadena"; char a_string[20] = "Esto es una cadena";
printf("%s\n", a_string); // %s se sutituye por una cadena. printf("%s\n", a_string); // %s se sutituye por una cadena.
/* /*
Te habrás dado cuenta de que a_string es solo de 18 caracteres. Te habrás dado cuenta de que a_string es solo de 18 caracteres.
El 'char' #19 es el byte nulo. El 'char' #19 es el byte nulo.
El 'char' #20 es de valor indefinido. El 'char' #20 es de valor indefinido.
*/ */
@ -122,22 +122,22 @@ printf("%d\n", a_string[18]); // => 0
// Operadores // Operadores
/////////////////////////////////////// ///////////////////////////////////////
int i1 = 1, i2 = 2; // Forma corta de declaración múltiple int i1 = 1, i2 = 2; // Forma corta de declaración múltiple
float f1 = 1.0, f2 = 2.0; float f1 = 1.0, f2 = 2.0;
// La aritmética es sencilla // La aritmética es sencilla
i1 + i2; // => 3 i1 + i2; // => 3
i2 - i1; // => 1 i2 - i1; // => 1
i2 * i1; // => 2 i2 * i1; // => 2
i1 / i2; // => 0 (0.5, pero es truncado tras el 0) i1 / i2; // => 0 (0.5, pero es truncado tras el 0)
f1 / f2; // => 0.5, más o menos épsilon f1 / f2; // => 0.5, más o menos épsilon
// Módulo está también // Módulo está también
11 % 3; // => 2 11 % 3; // => 2
// Los operadores de comparación te resultaran familiares, pero no hay // Los operadores de comparación te resultaran familiares, pero no hay
// booleanos en C. Usamos enteros (ints) en su lugar. 0 es falso, // booleanos en C. Usamos enteros (ints) en su lugar. 0 es falso,
// cualquier otra cosa es verdadero. (Los operadores de comparación // cualquier otra cosa es verdadero. (Los operadores de comparación
// siempre devuelven 0 o 1) // siempre devuelven 0 o 1)
3 == 2; // => 0 (Falso) 3 == 2; // => 0 (Falso)
3 != 2; // => 1 (Verdadero) 3 != 2; // => 1 (Verdadero)
@ -146,16 +146,16 @@ f1 / f2; // => 0.5, m
2 <= 2; // => 1 2 <= 2; // => 1
2 >= 2; // => 1 2 >= 2; // => 1
// La lógica funiona en enteros // La lógica funiona en enteros
!3; // => 0 (not lógico) !3; // => 0 (not lógico)
!0; // => 1 !0; // => 1
1 && 1; // => 1 (and lógico) 1 && 1; // => 1 (and lógico)
0 && 1; // => 0 0 && 1; // => 0
0 || 1; // => 1 (or lógico) 0 || 1; // => 1 (or lógico)
0 || 0; // => 0 0 || 0; // => 0
// ¡Operadores de bits! // ¡Operadores de bits!
~0x0F; // => 0xF0 (Negación) ~0x0F; // => 0xF0 (Negación)
0x0F & 0xF0; // => 0x00 (AND) 0x0F & 0xF0; // => 0x00 (AND)
0x0F | 0xF0; // => 0xFF (OR) 0x0F | 0xF0; // => 0xFF (OR)
0x04 ^ 0x0F; // => 0x0B (XOR) 0x04 ^ 0x0F; // => 0x0B (XOR)
@ -177,7 +177,7 @@ if (0) {
// Mientras el bucle exista // Mientras el bucle exista
int ii = 0; int ii = 0;
while (ii < 10) { while (ii < 10) {
printf("%d, ", ii++); // ii++ incrementa ii en uno, después de usar su valor. printf("%d, ", ii++); // ii++ incrementa ii en uno, después de usar su valor.
} // => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " } // => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n"); printf("\n");
@ -190,7 +190,7 @@ do {
printf("\n"); printf("\n");
// Bucles 'for' también // Bucles 'for' también
int jj; int jj;
for (jj=0; jj < 10; jj++) { for (jj=0; jj < 10; jj++) {
printf("%d, ", jj); printf("%d, ", jj);
@ -207,13 +207,13 @@ printf("\n");
int x_hex = 0x01; // Puedes asignar hexadecimales a variables int x_hex = 0x01; // Puedes asignar hexadecimales a variables
// El cambio de tipos intentará mantener sus valores numéricos // El cambio de tipos intentará mantener sus valores numéricos
printf("%d\n", x_hex); // => Muestra 1 printf("%d\n", x_hex); // => Muestra 1
printf("%d\n", (short) x_hex); // => Muestra 1 printf("%d\n", (short) x_hex); // => Muestra 1
printf("%d\n", (char) x_hex); // => Muestra 1 printf("%d\n", (char) x_hex); // => Muestra 1
// Los tipos se desbordan sin aviso // Los tipos se desbordan sin aviso
printf("%d\n", (char) 257); // => 1 (El valor máximo de un 'char' es 255) printf("%d\n", (char) 257); // => 1 (El valor máximo de un 'char' es 255)
// Los tipos enteros puden cambiarse a tipos de coma flotante, y viceversa // Los tipos enteros puden cambiarse a tipos de coma flotante, y viceversa
printf("%f\n", (float)100); // %f se sustituye por un 'float' printf("%f\n", (float)100); // %f se sustituye por un 'float'
@ -224,28 +224,28 @@ printf("%d\n", (char)100.0);
// Punteros // Punteros
/////////////////////////////////////// ///////////////////////////////////////
// Un puntero es una variable declarada para almacenar una dirección de // Un puntero es una variable declarada para almacenar una dirección de
// memoria. Su declaración además nos dirá el tipo de dato al que apunta. // memoria. Su declaración además nos dirá el tipo de dato al que apunta.
// Puedes obtener la dirección de memoria de tus variables, y después // Puedes obtener la dirección de memoria de tus variables, y después
// enlazarlas con ellos. // enlazarlas con ellos.
int x = 0; int x = 0;
printf("%p\n", &x); // Usa & para obtener la dirección de una variable. printf("%p\n", &x); // Usa & para obtener la dirección de una variable.
// (%p se sustituye por un puntero) // (%p se sustituye por un puntero)
// => Muestra alguna dirección de memoria; // => Muestra alguna dirección de memoria;
// Los tipos de puntero terminan con * en su declaración // Los tipos de puntero terminan con * en su declaración
int* px; // px es un puntero a un 'int' int* px; // px es un puntero a un 'int'
px = &x; // Almacena la dirección de x en px px = &x; // Almacena la dirección de x en px
printf("%p\n", px); // => Muestra alguna dirección de memoria printf("%p\n", px); // => Muestra alguna dirección de memoria
// Para obtener el valor de la dirección a la que apunta un puntero, pon // Para obtener el valor de la dirección a la que apunta un puntero, pon
// * delante para desreferenciarle. // * delante para desreferenciarle.
printf("%d\n", *px); // => Muestra 0, el valor de x y de la dirección a la printf("%d\n", *px); // => Muestra 0, el valor de x y de la dirección a la
// que apunta px // que apunta px
// También puedes cambiar el valor al que está apuntando el puntero. // También puedes cambiar el valor al que está apuntando el puntero.
// Tenemos que meter la desreferencia entre paréntesis porque ++ tiene // Tenemos que meter la desreferencia entre paréntesis porque ++ tiene
// prioridad frente a *. // prioridad frente a *.
(*px)++; // Incrementa el valor al que apunta px en 1 (*px)++; // Incrementa el valor al que apunta px en 1
printf("%d\n", *px); // => Muestra 1 printf("%d\n", *px); // => Muestra 1
@ -267,24 +267,24 @@ int* x_ptr = x_array;
printf("%d\n", *(x_ptr)); // => Muestra 20 printf("%d\n", *(x_ptr)); // => Muestra 20
printf("%d\n", x_array[0]); // => Muestra 20 printf("%d\n", x_array[0]); // => Muestra 20
// Los punteros aumentan y disminuyen en función de su tipo. // Los punteros aumentan y disminuyen en función de su tipo.
printf("%d\n", *(x_ptr + 1)); // => Muestra 19 printf("%d\n", *(x_ptr + 1)); // => Muestra 19
printf("%d\n", x_array[1]); // => Muestra 19 printf("%d\n", x_array[1]); // => Muestra 19
// Puedes también asigner dinamicamente bloques contiguos de memoria con // Puedes también asigner dinamicamente bloques contiguos de memoria con
// la función malloc de la librería estándard, que toma un entero como // la función malloc de la librería estándard, que toma un entero como
// argumento representando el número de bytes a asignar de la pila. // argumento representando el número de bytes a asignar de la pila.
int* my_ptr = (int*) malloc(sizeof(int) * 20); int* my_ptr = (int*) malloc(sizeof(int) * 20);
for (xx=0; xx<20; xx++) { for (xx=0; xx<20; xx++) {
*(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx funcionaría también aquí *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx funcionaría también aquí
} // Inicializa la memoria a 20, 19, 18, 17... 2, 1 (como 'ints') } // Inicializa la memoria a 20, 19, 18, 17... 2, 1 (como 'ints')
// Desreferenciando la memoria que no has asignado te dará resultados // Desreferenciando la memoria que no has asignado te dará resultados
// impredecibles // impredecibles
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what?
// Cuando hallas acabado con el bloque de memoría malloc, necesitas // Cuando hallas acabado con el bloque de memoría malloc, necesitas
// liberarlo o sino nadie más podrá usarlo hasta que tu programa se cierre // liberarlo o sino nadie más podrá usarlo hasta que tu programa se cierre
free(my_ptr); free(my_ptr);
// Las cadenas pueden ser 'arrays' de chars, pero normalmente se // Las cadenas pueden ser 'arrays' de chars, pero normalmente se
@ -294,13 +294,13 @@ char* my_str = "This is my very own string";
printf("%c\n", *my_str); // => 'T' printf("%c\n", *my_str); // => 'T'
function_1(); function_1();
} // fin de la función main } // fin de la función main
/////////////////////////////////////// ///////////////////////////////////////
// Funciones // Funciones
/////////////////////////////////////// ///////////////////////////////////////
// Sintexis de la declaración de funciones: // Sintexis de la declaración de funciones:
// <tipo de retorno> <nombre>(<argumentos>) // <tipo de retorno> <nombre>(<argumentos>)
int add_two_ints(int x1, int x2){ int add_two_ints(int x1, int x2){
@ -315,13 +315,13 @@ valores.
Ejemplo: invertidor de cadenas in-situ Ejemplo: invertidor de cadenas in-situ
*/ */
// Una función 'void' no retorna valor // Una función 'void' no retorna valor
void str_reverse(char* str_in){ void str_reverse(char* str_in){
char tmp; char tmp;
int ii=0, len = strlen(str_in); // Strlen es parte de la librería int ii=0, len = strlen(str_in); // Strlen es parte de la librería
for(ii=0; ii<len/2; ii++){ // estándard for(ii=0; ii<len/2; ii++){ // estándard
tmp = str_in[ii]; tmp = str_in[ii];
str_in[ii] = str_in[len - ii - 1]; // ii-th último 'char' str_in[ii] = str_in[len - ii - 1]; // ii-th último 'char'
str_in[len - ii - 1] = tmp; str_in[len - ii - 1] = tmp;
} }
} }
@ -333,14 +333,14 @@ printf("%s\n", c); // => ".abeurp anu se otsE"
*/ */
/////////////////////////////////////// ///////////////////////////////////////
// Definición de tipos y estructuras // Definición de tipos y estructuras
/////////////////////////////////////// ///////////////////////////////////////
// Los 'Typedefs' pueden ser utilizados para crear alias de tipos. // Los 'Typedefs' pueden ser utilizados para crear alias de tipos.
typedef int my_type; typedef int my_type;
my_type my_type_var = 0; my_type my_type_var = 0;
// Las estructuras son sólo grupos de datos. // Las estructuras son sólo grupos de datos.
struct rectangle { struct rectangle {
int width; int width;
int height; int height;
@ -365,7 +365,7 @@ void function_1(){
my_rec_ptr->height = 10; // Lo mismo que (*my_rec_ptr).height = 10; my_rec_ptr->height = 10; // Lo mismo que (*my_rec_ptr).height = 10;
} }
// Puedes aplicar un 'typedef' a una estructura por conveniencía. // Puedes aplicar un 'typedef' a una estructura por conveniencía.
typedef struct rectangle rect; typedef struct rectangle rect;
int area(rect r){ int area(rect r){
@ -376,26 +376,26 @@ int area(rect r){
// Punteros a Funciones // Punteros a Funciones
/////////////////////////////////////// ///////////////////////////////////////
/* /*
En tiempo de ejecución, las funciones se localizan en unas direcciones de En tiempo de ejecución, las funciones se localizan en unas direcciones de
memoria concretas. Los punteros a funciones son como cualquier otro memoria concretas. Los punteros a funciones son como cualquier otro
puntero (almacenan una dirección de memoria), pero pueden ser usados para puntero (almacenan una dirección de memoria), pero pueden ser usados para
utilizar funciones directamente, o para pasar 'handlers' (o funciones utilizar funciones directamente, o para pasar 'handlers' (o funciones
'callback') por todos lados. 'callback') por todos lados.
Sin embargo, la sintaxis de definición parecera confusa al principio. Sin embargo, la sintaxis de definición parecera confusa al principio.
Ejemplo: usar str_reverse desde un puntero Ejemplo: usar str_reverse desde un puntero
*/ */
void str_reverse_through_pointer(char * str_in) { void str_reverse_through_pointer(char * str_in) {
// Define un puntero a una función, llamado f. // Define un puntero a una función, llamado f.
void (*f)(char *); // La armadura debe coincidir exactamente con al función objetivo. void (*f)(char *); // La armadura debe coincidir exactamente con al función objetivo.
f = &str_reverse; // Assigna la dirección de la función (determinado en tiempo de ejecuión) f = &str_reverse; // Assigna la dirección de la función (determinado en tiempo de ejecuión)
(*f)(str_in); // Llamando la función desde el puntero (*f)(str_in); // Llamando la función desde el puntero
// f(str_in); // Esta es una alternativa para llamarla pero con una sintaxis igual de válida. // f(str_in); // Esta es una alternativa para llamarla pero con una sintaxis igual de válida.
} }
/* /*
Tanto tiempo como las armaduras de las funciones coincidan, podrás asignar Tanto tiempo como las armaduras de las funciones coincidan, podrás asignar
cualquier función al mismo puntero. cualquier función al mismo puntero.
Los punteros a funciones son normalmente envueltos en 'typedef' para Los punteros a funciones son normalmente envueltos en 'typedef' para
simplificar su legibilidad, como sigue: simplificar su legibilidad, como sigue:
*/ */