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:
- ["Adam Bard", "http://adambard.com/"]
translators:
- ["Francisco García", "http://flaskbreaker.tumblr.com/"]
- ["Francisco García", "http://flaskbreaker.tumblr.com/"]
lang: es-es
---
¡Ah!, C. Aun hoy en día sigue siendo el lenguaje por excelencia de la
computación moderna de alto rendimiento.
¡Ah!, C. Aun hoy en día sigue siendo el lenguaje por excelencia de la
computación moderna de alto rendimiento.
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
ten en cuenta el manejo manual de memoria y te llevará tan lejos como
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
ten en cuenta el manejo manual de memoria y te llevará tan lejos como
necesites.
```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
@ -33,12 +33,12 @@ Los comentarios multil
void function_1();
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).
int main() {
// 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
// Todas las sentencias deben terminar con un punto y coma.
@ -46,9 +46,9 @@ printf("%d\n", 0); // => Muestra 0
// 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
// determina su tamaño en bytes.
// determina su tamaño en bytes.
// 'ints' (enteros) son normalmente de 4 bytes
int x_int = 0;
@ -65,53 +65,53 @@ char y_char = 'y'; // Los caracteres literales se entrecomillan con ''
long x_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;
// '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;
// Todos los tipos enteros pueden ser 'unsigned'. Esto significa que no
// pueden ser negativos, pero el valor máximo de una variable 'unsigned'
// es mayor que el de una no 'unsigned' del mismo tamaño.
// pueden ser negativos, pero el valor máximo de una variable 'unsigned'
// es mayor que el de una no 'unsigned' del mismo tamaño.
unsigned char ux_char;
unsigned short ux_short;
unsigned int ux_int;
unsigned long long ux_long_long;
// 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
// de tipo T en bytes por lo que podemos expresar el tamaño de estos tipos
// 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
// de tipo T en bytes por lo que podemos expresar el tamaño de estos tipos
// portatilmente.
// 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
int my_int_array[20]; // Este array ocupa 4 * 20 = 80 bytes
// (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};
// 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-
my_array[0]; // => 0
// Los arrays varían; ¡son sólo memoria!
// Los arrays varían; ¡son sólo memoria!
my_array[1] = 2;
printf("%d\n", my_array[1]); // => 2
// 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'.
// (No tenemos porqué añadir el byte nulo en cadenas literales; el
// compilador lo añade al final por nosotros.)
// 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'.
// (No tenemos porqué añadir el byte nulo en cadenas literales; el
// compilador lo añade al final por nosotros.)
char a_string[20] = "Esto es 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' #20 es de valor indefinido.
*/
@ -122,22 +122,22 @@ printf("%d\n", a_string[18]); // => 0
// 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;
// La aritmética es sencilla
// La aritmética es sencilla
i1 + i2; // => 3
i2 - i1; // => 1
i2 * i1; // => 2
i1 / i2; // => 0 (0.5, pero es truncado tras el 0)
f1 / f2; // => 0.5, más o menos épsilon
// Módulo está también
f1 / f2; // => 0.5, más o menos épsilon
// Módulo está también
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,
// 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)
3 == 2; // => 0 (Falso)
3 != 2; // => 1 (Verdadero)
@ -146,16 +146,16 @@ f1 / f2; // => 0.5, m
2 <= 2; // => 1
2 >= 2; // => 1
// La lógica funiona en enteros
!3; // => 0 (not lógico)
// La lógica funiona en enteros
!3; // => 0 (not lógico)
!0; // => 1
1 && 1; // => 1 (and lógico)
1 && 1; // => 1 (and lógico)
0 && 1; // => 0
0 || 1; // => 1 (or lógico)
0 || 1; // => 1 (or lógico)
0 || 0; // => 0
// ¡Operadores de bits!
~0x0F; // => 0xF0 (Negación)
// ¡Operadores de bits!
~0x0F; // => 0xF0 (Negación)
0x0F & 0xF0; // => 0x00 (AND)
0x0F | 0xF0; // => 0xFF (OR)
0x04 ^ 0x0F; // => 0x0B (XOR)
@ -177,7 +177,7 @@ if (0) {
// Mientras el bucle exista
int ii = 0;
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, "
printf("\n");
@ -190,7 +190,7 @@ do {
printf("\n");
// Bucles 'for' también
// Bucles 'for' también
int jj;
for (jj=0; jj < 10; jj++) {
printf("%d, ", jj);
@ -207,13 +207,13 @@ printf("\n");
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", (short) x_hex); // => Muestra 1
printf("%d\n", (char) x_hex); // => Muestra 1
// 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
printf("%f\n", (float)100); // %f se sustituye por un 'float'
@ -224,28 +224,28 @@ printf("%d\n", (char)100.0);
// Punteros
///////////////////////////////////////
// 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.
// Puedes obtener la dirección de memoria de tus variables, y después
// 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.
// Puedes obtener la dirección de memoria de tus variables, y después
// enlazarlas con ellos.
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)
// => 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'
px = &x; // Almacena la dirección de x en px
printf("%p\n", px); // => Muestra alguna dirección de memoria
px = &x; // Almacena la dirección de x en px
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.
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
// También puedes cambiar el valor al que está apuntando el puntero.
// Tenemos que meter la desreferencia entre paréntesis porque ++ tiene
// También puedes cambiar el valor al que está apuntando el puntero.
// Tenemos que meter la desreferencia entre paréntesis porque ++ tiene
// prioridad frente a *.
(*px)++; // Incrementa el valor al que apunta px en 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_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_array[1]); // => Muestra 19
// 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
// argumento representando el número de bytes a asignar de la pila.
// 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
// argumento representando el número de bytes a asignar de la pila.
int* my_ptr = (int*) malloc(sizeof(int) * 20);
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')
// Desreferenciando la memoria que no has asignado te dará resultados
// Desreferenciando la memoria que no has asignado te dará resultados
// impredecibles
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what?
// 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
// 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
free(my_ptr);
// 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'
function_1();
} // fin de la función main
} // fin de la función main
///////////////////////////////////////
// Funciones
///////////////////////////////////////
// Sintexis de la declaración de funciones:
// Sintexis de la declaración de funciones:
// <tipo de retorno> <nombre>(<argumentos>)
int add_two_ints(int x1, int x2){
@ -315,13 +315,13 @@ valores.
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){
char tmp;
int ii=0, len = strlen(str_in); // Strlen es parte de la librería
for(ii=0; ii<len/2; ii++){ // estándard
int ii=0, len = strlen(str_in); // Strlen es parte de la librería
for(ii=0; ii<len/2; ii++){ // estándard
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;
}
}
@ -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.
typedef int my_type;
my_type my_type_var = 0;
// Las estructuras son sólo grupos de datos.
// Las estructuras son sólo grupos de datos.
struct rectangle {
int width;
int height;
@ -365,7 +365,7 @@ void function_1(){
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;
int area(rect r){
@ -376,26 +376,26 @@ int area(rect r){
// 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
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
'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
*/
void str_reverse_through_pointer(char * str_in) {
// Define un puntero a una función, llamado f.
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_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.
// Define un puntero a una función, llamado f.
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_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.
}
/*
Tanto tiempo como las armaduras de las funciones coincidan, podrás asignar
cualquier función al mismo puntero.
Tanto tiempo como las armaduras de las funciones coincidan, podrás asignar
cualquier función al mismo puntero.
Los punteros a funciones son normalmente envueltos en 'typedef' para
simplificar su legibilidad, como sigue:
*/