This page needs a recent browser (with SharedArrayBuffer support). Please update Chrome, Edge, Firefox or Safari to the latest version. · Esta página necesita un navegador reciente (con soporte para SharedArrayBuffer). Por favor, actualiza Chrome, Edge, Firefox o Safari a la última versión.
1C basics · Básicos de C
1.1
main, printf y funciones
English
Every C program starts in main. #include <stdio.h> pulls in a header 头文件 so you can use printf to print. A function 函数 is a named block you can call; \n starts a new line. main returns 0 to mean "success".
Español
Todo programa C comienza en main. #include <stdio.h> incluye una cabecera para que puedas usar printf para imprimir. Una función es un bloque nombrado que puedes llamar; \n inicia una nueva línea. main devuelve 0 para indicar "éxito".
#include <stdio.h>
void greet(void) {
printf("Hello, world!\n");
}
int main(void) {
greet();
printf("I am learning C.\n");
return 0;
}
Cada programa C se ejecuta desde main tras incluir las cabeceras
1.2
Variables, tipos y aritmética
English
C needs a type for every variable: int (integer 整数), double (floating-point 浮点数), char (one character). printf uses a format specifier 格式说明符 — %d, %f, %c — for each value. / between two ints is integer division; % is the remainder 余数.
The format string drives both printing and reading:
Specifier
Type
Example output
%d
int
17
%f
double (%.2f = 2 decimal places)
3.14
%c
char
A
%s
a string
Mei
%zu
a size (from sizeof / strlen)
3
%x
int, printed in base 16
ff
scanf("%d", &n) reads keyboard input with the same specifiers (note the &). Its sibling sscanf parses values out of a string, so it runs anywhere:
Español
C necesita un tipo para cada variable: int (entero), double (punto flotante), char (un carácter). printf usa un especificador de formato — %d, %f, %c — para cada valor. / entre dos enteros es división entera; % es el resto.
#include <stdio.h>
int main(void) {
int n = 17;
double pi = 3.14;
char grade = 'A';
printf("%d %.2f %c\n", n, pi, grade); // 17 3.14 A
printf("%d %d\n", 7 / 2, 7 % 2); // 3 1
return 0;
}
La cadena de formato controla tanto la impresión como la lectura:
Especificador
Tipo
Ejemplo de salida
%d
int
17
%f
double (%.2f = 2 decimales)
3.14
%c
char
A
%s
una cadena
Mei
%zu
un tamaño (de sizeof / strlen)
3
%x
int, impreso en base 16
ff
scanf("%d", &n) lee entrada del teclado con los mismos especificadores (nota el &). Su pariente sscanf extrae valores de una cadena, por lo que puede ejecutarse en cualquier lugar:
#include <stdio.h>
int main(void) {
char line[] = "Mei 88";
char name[20];
int score;
sscanf(line, "%19s %d", name, &score); // parse text -> values
printf("%s scored %d\n", name, score); // Mei scored 88
return 0;
}
1.3
Comentarios y estilo
English
A comment 注释 is a note for humans; the compiler ignores it. Use // for one line and /* ... */ for a block. Good indentation 缩进 and clear names make code easy to read.
Common mistakes
Every statement ends with ;, and main should return int (return 0;).
printf needs a format string: %d for int, %f for double, and \n for a new line.
A wrong format like %d for a double prints garbage — match the type.
Español
Un comentario es una nota para humanos; el compilador lo ignora. Usa // para una sola línea y /* ... */ para un bloque. La buena indentación y los nombres claros facilitan la lectura del código.
#include <stdio.h>
int main(void) {
// a single-line comment
/* a block
comment */
int total = 3 + 4; // clear names help
printf("%d\n", total); // 7
return 0;
}
Errores comunes
Cada sentencia termina con ;, y main debería devolver int (return 0;).
printf necesita una cadena de formato: %d para int, %f para double, y \n para una nueva línea.
Un formato incorrecto como %d para un double imprime basura; coincide el tipo.
2Selection · Selección
2.1
if / else
English
An if runs a block when a condition 条件 is true. C has no real boolean 布尔值 type by default: 0 is false and any non-zero value is true. Chain choices with else if and else. Compare with ==, !=, <, >, <=, >=.
Español
Un if ejecuta un bloque cuando una condición 条件 es verdadera. C no tiene un tipo booleano 布尔值 real por defecto: 0 es falso y cualquier valor distinto de cero es verdadero. Encadena opciones con else if y else. Compara con ==, !=, <, >, <=, >=.
#include <stdio.h>
int main(void) {
int score = 72;
if (score >= 90) {
printf("A\n");
} else if (score >= 60) {
printf("Pass\n");
} else {
printf("Fail\n");
}
return 0;
}
if elige la rama verdadera; else la rama falsa
2.2
switch
English
A switch picks one case by an integer value. Each case needs a break to jump out 跳出 — without it, C "falls through" into the next case. default runs when nothing matches.
Common mistakes
if (x = 5) assigns and is always true; use == to compare.
Each switch case needs a break;, or it falls through to the next.
0 is false and any non-zero value is true in a condition.
Español
Un switch selecciona un case mediante un valor entero. Cada case necesita un break para salir 跳出 — sin él, C "cae" al caso siguiente. default se ejecuta cuando nada coincide.
#include <stdio.h>
int main(void) {
int day = 3;
switch (day) {
case 1: printf("Mon\n"); break;
case 2: printf("Tue\n"); break;
case 3: printf("Wed\n"); break;
default: printf("Other\n");
}
return 0;
}
Errores comunes
if (x = 5) asigna y siempre es verdadero; usa == para comparar.
Cada caso de switch necesita un break;, o caerá al siguiente.
0 es falso y cualquier valor distinto de cero es verdadero en una condición.
3Loops · Bucles
3.1
bucles while y for
English
A loop 循环 repeats a block. A while loop runs as long as a condition is true. A for loop packs the start, the test, and the increment 自增 (i++) into one line — best when you know how many times to repeat.
Español
Un bucle repite un bloque de código. Un bucle while se ejecuta mientras una condición sea verdadera. Un bucle for agrupa el inicio, la prueba y el incremento (i++) en una sola línea — es ideal cuando se sabe cuántas veces se debe repetir.
#include <stdio.h>
int main(void) {
int i = 1;
while (i <= 3) {
printf("%d ", i);
i++;
}
printf("\n"); // 1 2 3
for (int j = 0; j < 5; j++) {
printf("%d ", j);
}
printf("\n"); // 0 1 2 3 4
return 0;
}
el bucle while verifica una condición; el bucle for cuenta con un paso
3.2
Acumulación
English
A common pattern: start an accumulator 累加器 at 0, then add to it inside a loop. The same idea counts items or finds a running total.
Español
Un patrón común: iniciar un acumulador en 0, luego sumarle valores dentro del bucle. La misma idea sirve para contar elementos o encontrar una suma total.
#include <stdio.h>
int main(void) {
int total = 0;
for (int i = 1; i <= 5; i++) {
total += i; // 1 + 2 + 3 + 4 + 5
}
printf("%d\n", total); // 15
return 0;
}
3.3
Bucle anidados y patrones
English
A loop inside another loop is a nested 嵌套 loop. The inner loop finishes fully for each step of the outer loop — perfect for grids and patterns.
Common mistakes
for (i = 0; i < n; i++) runs n times; a semicolon right after for (...) makes an empty loop.
A while whose condition never becomes false loops forever.
Declare the counter (int i) before or inside the for header.
Español
Un bucle dentro de otro bucle es un bucle anidado. El bucle interior se completa completamente por cada paso del bucle exterior — perfecto para cuadrículas y patrones.
#include <stdio.h>
int main(void) {
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
printf("*");
}
printf("\n");
}
return 0;
}
Errores comunes
for (i = 0; i < n; i++) se ejecuta n veces; un punto y coma inmediatamente después de for (...) crea un bucle vacío.
Un while cuya condición nunca se vuelve falsa produce un bucle infinito.
Declarar el contador (int i) antes o dentro del encabezado del for.
4Functions · Funciones
4.1
Parámetros y valores de retorno
English
A function takes parameters 参数 (inputs) and gives back a return value 返回值. The return type comes first (int, double, …); void means it returns nothing.
Español
Una función toma parámetros (entradas) y devuelve un valor de retorno. El tipo de retorno aparece primero (int, double, …); void significa que no devuelve nada.
#include <stdio.h>
int square(int x) { // x is a parameter
return x * x; // hand back a value
}
int main(void) {
int r = square(5);
printf("%d\n", r); // 25
return 0;
}
Parámetros entrada; valor de retorno salida
4.2
Prototipos y alcance
English
C reads top to bottom, so a function must be known before it is called. A prototype 函数原型 — the header line plus ; — declares it early so you can keep main first. A variable's scope 作用域 is the block it lives in: it is local 局部 and disappears when the block ends.
Common mistakes
A function used before it is defined needs a prototype above main.
Arguments are passed BY VALUE — changes inside a function do not affect the caller unless you pass a pointer.
A variable declared inside a function is local to it.
Español
C lee de arriba hacia abajo, por lo que una función debe estar declarada antes de ser llamada. Un prototipo — la línea del encabezado más el ; — la declara tempranamente para que pueda mantener main al principio. El alcance de una variable es el bloque en el que vive: es local y desaparece cuando termina el bloque.
#include <stdio.h>
int add(int a, int b); // prototype: declared before use
int main(void) {
printf("%d\n", add(3, 4)); // 7
return 0;
}
int add(int a, int b) { // definition comes later
int sum = a + b; // sum is local to add
return sum;
}
Errores comunes
Una función usada antes de su definición necesita un prototipo encima de main.
Los argumentos se pasan POR VALOR — los cambios dentro de una función no afectan al llamador a menos que pase un puntero.
Una variable declarada dentro de una función es local a ella.
5Arrays · Arreglos
5.1
Arrays 1-D
English
An array 数组 holds several values of one type. Index 索引 from 0. C does not store an array's length, so a common trick computes the element 元素 count: sizeof(a) / sizeof(a[0]).
Español
Un array (arreglo) almacena varios valores de un mismo tipo. El índice (índice) comienza en 0. C no guarda la longitud del array, por lo que una práctica común para calcular el número de elementos es: sizeof(a) / sizeof(a[0]).
#include <stdio.h>
int main(void) {
int scores[3] = {88, 71, 95};
printf("%d\n", scores[0]); // 88
scores[1] = 100;
printf("%d\n", scores[1]); // 100
int n = sizeof(scores) / sizeof(scores[0]);
printf("%d\n", n); // 3
return 0;
}
Los espacios del array se indexan desde 0
5.2
Algoritmos con arrays
English
Traverse 遍历 an array with a for loop to find a max, a total, or a count. Always loop from 0 up to n - 1.
Español
Recorra (recorrida) un array con un bucle for para encontrar un valor máximo, un total o un conteo. Siempre recorra desde 0 hasta n - 1.
#include <stdio.h>
int main(void) {
int a[] = {3, 9, 2, 7};
int n = sizeof(a) / sizeof(a[0]);
int max = a[0], total = 0;
for (int i = 0; i < n; i++) {
if (a[i] > max) max = a[i];
total += a[i];
}
printf("%d %d\n", max, total); // 9 21
return 0;
}
5.3
Arrays 2-D
English
A 2-D array is a grid of rows 行 and columns 列: grid[row][col]. Use two nested loops to visit every cell.
Common mistakes
C does NOT check array bounds: writing a[n] in a size-n array is undefined behaviour.
Valid indexes run from 0 to n - 1.
The array name is a pointer to its first element; sizeof only gives the size in the array's own scope.
Español
Un array 2-D (bidimensional) es una cuadrícula de filas y columnas: grid[row][col]. Utilice dos bucles anidados para visitar cada celda.
#include <stdio.h>
int main(void) {
int grid[2][3] = {{1, 2, 3}, {4, 5, 6}};
printf("%d\n", grid[1][2]); // 6
for (int r = 0; r < 2; r++) {
for (int c = 0; c < 3; c++) {
printf("%d ", grid[r][c]);
}
}
printf("\n"); // 1 2 3 4 5 6
return 0;
}
Errores comunes
C NO verifica los límites del array: escribir a[n] en un array de tamaño n es comportamiento indefinido.
Los índices válidos van de 0 a n - 1.
El nombre del array es un puntero al primer elemento; sizeof solo proporciona el tamaño dentro del propio ámbito del array.
6Pointers · Punteros
6.1
&, * y punteros por referencia
English
A pointer 指针 stores the address 地址 of a variable. &x gives the address of x; *p dereferences 解引用 the pointer — it reads or writes the value stored there. Passing a pointer lets a function change the caller's variable (pass-by-pointer).
The classic use is a swap function. Passing values only copies them — the swap is lost. Passing pointers lets the function reach the caller's variables:
An array name acts as a pointer to its first element, and pointer arithmetic 指针运算 steps by whole elements:
NULL is the pointer that points at nothing — check for it before you dereference.
Common mistakes
&x is the address of x; *p is the value stored at p.
Never use *p on an uninitialised or NULL pointer — it crashes or corrupts memory.
To change a caller's variable, pass its address and write through the pointer.
Español
Un puntero 指针 almacena la dirección 地址 de una variable. &x devuelve la dirección de x; *p desreferencia 解引用 el puntero: lee o escribe el valor almacenado en esa ubicación. Pasar un puntero permite que una función modifique la variable del llamador (punteros por referencia).
Un puntero almacena una dirección; al desreferenciarlo, se sigue la flecha hacia el valor
#include <stdio.h>
void addOne(int *p) { // p holds an address
*p = *p + 1; // change the value at that address
}
int main(void) {
int x = 10;
int *ptr = &x; // & takes the address of x
printf("%d\n", *ptr); // * reads the value: 10
addOne(&x);
printf("%d\n", x); // 11 — changed through the pointer
return 0;
}
El uso clásico es una función de intercambio. Al pasar valores solo se copian — el intercambio se pierde. Al pasar punteros, la función accede a las variables del llamador:
#include <stdio.h>
void swap_values(int a, int b) { // copies: the caller sees nothing
int t = a; a = b; b = t;
}
void swap_pointers(int *a, int *b) { // addresses: the swap is real
int t = *a; *a = *b; *b = t;
}
int main(void) {
int x = 1, y = 2;
swap_values(x, y);
printf("%d %d\n", x, y); // 1 2 (unchanged!)
swap_pointers(&x, &y);
printf("%d %d\n", x, y); // 2 1 (swapped)
return 0;
}
El nombre de un array actúa como un puntero a su primer elemento, y la aritmética de punteros 指针运算 avanza en pasos enteros de elementos:
#include <stdio.h>
int main(void) {
int a[] = {10, 20, 30};
int *p = a; // same as &a[0]
printf("%d\n", *p); // 10
printf("%d\n", *(p + 2)); // 30 — same as a[2]
return 0;
}
NULL es el puntero que no apunta a nada — compruébelo antes de desreferenciarlo.
Errores comunes
&x es la dirección de x; *p es el valor almacenado en la ubicación apuntada por p.
Nunca use *p sobre un puntero sin inicializar o NULL — causará un fallo o dañará la memoria.
Para modificar la variable del llamador, pase su dirección y escriba a través del puntero.
7Strings · Cadenas
7.1
Arrays de caracteres y el terminador nulo
English
A C string 字符串 is an array of char. Every string ends with a hidden null terminator 空终止符'\0', which marks where it stops. strlen (from <string.h>) counts characters up to that '\0'. Print a whole string with %s and one character 字符 with %c.
You can traverse a string by looping until you reach '\0'.
Español
Una cadena en C es un array de char. Cada cadena termina con un terminador nulo oculto '\0', que marca dónde finaliza. strlen (de <string.h>) cuenta los caracteres hasta ese '\0'. Imprime una cadena completa con %s y un solo carácter con %c.
#include <stdio.h>
#include <string.h>
int main(void) {
char name[] = "Mei"; // 'M', 'e', 'i', '\0'
printf("%s\n", name); // Mei
printf("%zu\n", strlen(name)); // 3 (stops at '\0')
printf("%c\n", name[0]); // M
return 0;
}
Una cadena en C es un array de char que termina con un terminador nulo oculto
Puedes recorrer una cadena mediante un bucle hasta alcanzar '\0'.
#include <stdio.h>
int main(void) {
char word[] = "banana";
int count = 0;
for (int i = 0; word[i] != '\0'; i++) {
if (word[i] == 'a') count++;
}
printf("%d\n", count); // 3
return 0;
}
7.2
La librería string.h
English
#include <string.h> gives you the everyday string tools:
Function
Does
strlen(s)
the length, not counting the terminator
strcpy(dst, src)
copy — dst must be big enough
strcat(dst, src)
append src onto the end of dst
strcmp(a, b)
compare: 0 when equal, else negative / positive
strcmp returns 0 for equal, so the test is strcmp(a, b) == 0 — never a == b.
The destination array must have room for the result plus the terminator.
Common mistakes
A C string needs one extra byte for the \0 terminator: a 5-letter word needs char[6].
Copy and compare strings with strcpy / strcmp, not = / ==.
Forgetting the \0 makes printf("%s", ...) run past the end of the text.
Español
#include <string.h> te proporciona las herramientas habituales para manejar cadenas:
Función
Realiza
strlen(s)
la longitud, sin contar el terminador
strcpy(dst, src)
copia — dst debe ser lo suficientemente grande
strcat(dst, src)
appende src al final de dst
strcmp(a, b)
compara: 0 si son iguales, caso contrario negativo / positivo
#include <stdio.h>
#include <string.h>
int main(void) {
char full[40];
strcpy(full, "Mei"); // full is now "Mei"
strcat(full, " Chen"); // append -> "Mei Chen"
printf("%s (%zu)\n", full, strlen(full)); // Mei Chen (8)
printf("%d\n", strcmp("apple", "apple") == 0); // 1 (equal)
return 0;
}
strcmp devuelve 0 cuando las cadenas son iguales, por lo que la comprobación es strcmp(a, b) == 0 — nunca uses a == b.
El array destino debe tener espacio suficiente para el resultado más el terminador.
Errores comunes
Una cadena en C necesita un byte extra para el terminador \0: una palabra de 5 letras requiere char[6].
Copia y compara cadenas usando strcpy / strcmp, no = / ==.
Olvidar el \0 hace que printf("%s", ...) se salga del límite del texto.
8Structs · Estructuras
8.1
struct, typedef, . vs ->
English
A struct 结构体 groups related values into one type. Each value is a member 成员. typedef gives the struct a short name so you can write Dog instead of struct Dog. Use . on a struct value, but -> on a pointer to a struct.
Common mistakes
Use . on a struct value and -> on a struct pointer.
typedef lets you drop the word struct when declaring; without it you write struct Point p;.
Assigning one struct to another copies all its fields.
Español
Una estructura agrupa valores relacionados en un solo tipo. Cada valor es un miembro. typedef le da a la estructura un nombre corto para que pueda escribir Dog en lugar de struct Dog. Use . en un valor de estructura, pero -> en un puntero a una estructura.
#include <stdio.h>
typedef struct {
char name[20];
int age;
} Dog;
int main(void) {
Dog d = {"Rex", 3};
printf("%s is %d\n", d.name, d.age); // Rex is 3 (. on a value)
Dog *p = &d;
p->age = 4; // -> on a pointer
printf("%s is %d\n", d.name, d.age); // Rex is 4
return 0;
}
Errores comunes
Usa . en un valor de struct y -> en un puntero a struct.
typedef le permite omitir la palabra struct al declarar; sin él escribe struct Point p;.
Asignar un struct a otro copia todos sus campos.
. for struct values; -> for pointers to structs
9Dynamic memory · Memoria dinámica
9.1
malloc, free & realloc · malloc, free y realloc
English
malloc allocates 分配 memory on the heap 堆 at run time and returns a pointer to it. realloc resizes that block; free gives it back. Every malloc needs a matching free, or you get a memory leak 内存泄漏. These live in <stdlib.h>.
calloc(n, size) allocates an array like malloc AND fills it with zeros.
Common mistakes
Every malloc needs a matching free; forgetting to free leaks memory.
Using memory after free (a "use-after-free") is a serious bug.
Check that malloc did not return NULL before you use the memory.
Español
malloc asigna memoria en el montículo (heap) en tiempo de ejecución y devuelve un puntero a ella. realloc redimensiona ese bloque; free la devuelve al sistema. Cada malloc necesita un correspondiente free, o se producirá una fuga de memoria (memory leak). Estas funciones se encuentran en <stdlib.h>.
Las variables locales residen en la pila (stack); la memoria asignada con malloc permanece en el montículo hasta que se libera.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 3;
int *a = malloc(n * sizeof(int)); // room for 3 ints
for (int i = 0; i < n; i++) a[i] = i * 10;
a = realloc(a, 4 * sizeof(int)); // grow to 4 ints
a[3] = 30;
for (int i = 0; i < 4; i++) printf("%d ", a[i]);
printf("\n"); // 0 10 20 30
free(a); // hand the memory back
return 0;
}
calloc(n, size) asigna un arreglo como malloc Y además lo rellena con ceros.
Errores comunes
Cada malloc necesita un correspondiente free; olvidar llamar a free provoca fugas de memoria.
Usar memoria después de free (un "uso-después-de-liberar" o use-after-free) es un error grave.
Verifique que malloc no haya devuelto NULL antes de utilizar la memoria.
10Data structures · Estructuras de datos
10.1
Listas enlazadas
English
A linked list 链表 is a chain of nodes 节点. Each node holds a value and a pointer to the next node; the last one points to NULL. Unlike an array it grows one node at a time with malloc. Always free every node when done.
Español
Una lista enlazada 链表 es una cadena de nodos 节点. Cada nodo contiene un valor y un puntero al next nodo; el último apunta a NULL. A diferencia de un arreglo, crece un nodo a la vez con malloc. Siempre free cada nodo cuando haya terminado.
Una lista enlazada: cada nodo contiene un valor y un puntero al siguiente, terminando en NULL
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node *next;
} Node;
int main(void) {
Node *head = NULL;
for (int v = 10; v <= 30; v += 10) { // prepend 10, 20, 30
Node *n = malloc(sizeof(Node));
n->value = v;
n->next = head;
head = n;
}
for (Node *p = head; p != NULL; p = p->next) {
printf("%d ", p->value); // 30 20 10
}
printf("\n");
while (head != NULL) { // free the whole list
Node *t = head;
head = head->next;
free(t);
}
return 0;
}
10.2
Pilas y colas
English
A stack 栈 is LIFO 后进先出 (last in, first out): push and pop at the same end. A queue 队列 is FIFO 先进先出 (first in, first out): add at the back, remove from the front. Both are easy to build on an array with index variables.
Common mistakes
In a linked list, never lose the head pointer, or the whole list is unreachable.
Free every node when you are done, walking the list before you unlink.
Check for an empty list (a NULL head) before you pop.
Español
Una pila 栈 es LIFO 后进先出 (último en entrar, primero en salir): se apilan y desapilan en el mismo extremo. Una cola 队列 es FIFO 先进先出 (primero en entrar, primero en salir): se añade al final y se elimina desde el frente. Ambas son fáciles de implementar sobre un arreglo usando variables de índice.
#include <stdio.h>
int main(void) {
int stack[10];
int top = 0; // next free slot
stack[top++] = 1; // push
stack[top++] = 2;
stack[top++] = 3;
while (top > 0) {
printf("%d ", stack[--top]); // pop: 3 2 1
}
printf("\n");
return 0;
}
#include <stdio.h>
int main(void) {
int queue[10];
int front = 0, back = 0;
queue[back++] = 1; // enqueue
queue[back++] = 2;
queue[back++] = 3;
while (front < back) {
printf("%d ", queue[front++]); // dequeue: 1 2 3
}
printf("\n");
return 0;
}
Errores comunes
En una lista enlazada, nunca pierda el head puntero, o toda la lista será inaccesible.
Libere cada nodo cuando haya terminado, recorriendo la lista antes de desconectarla.
Verifique si la lista está vacía (un NULL head) antes de hacer un pop.
11Searching, sorting & recursion · Búsqueda, ordenamiento y recursión
11.1
Búsqueda lineal y búsqueda binaria
English
Linear search 线性查找 checks each element in turn — it works on any array. Binary search 二分查找 is far faster but needs a sorted 已排序 array: it checks the middle and discards half each step. Both return the index, or -1 if missing.
Español
La búsqueda lineal 线性查找 (linear search) revisa cada elemento en secuencia — funciona con cualquier arreglo. La búsqueda binaria 二分查找 (binary search) es mucho más rápida, pero requiere un arreglo ordenado 已排序: revisa el elemento central y descarta la mitad en cada paso. Ambas devuelven el índice, o -1 si no se encuentra.
#include <stdio.h>
int linear(int a[], int n, int target) {
for (int i = 0; i < n; i++)
if (a[i] == target) return i;
return -1;
}
int binary(int a[], int n, int target) {
int lo = 0, hi = n - 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (a[mid] == target) return mid;
else if (a[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int main(void) {
int a[] = {2, 5, 8, 12, 16, 23};
int n = sizeof(a) / sizeof(a[0]);
printf("%d %d %d\n", linear(a, n, 12), binary(a, n, 12), binary(a, n, 9));
return 0; // 3 3 -1
}
Búsqueda lineal explora todo; búsqueda binaria reduce a la mitad un rango ordenado
11.2
Ordenamiento
English
Bubble sort 冒泡排序 repeatedly compares neighbours and swaps 交换 any pair that is out of order. After each pass the largest value "bubbles" to the end.
Español
El ordenamiento burbuja 冒泡排序 compara repetidamente los elementos adyacentes e intercambia 交换 cualquier par que esté fuera de orden. Después de cada pasada, el valor más grande "sube" hacia el final.
#include <stdio.h>
int main(void) {
int a[] = {5, 2, 9, 1, 7};
int n = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (a[j] > a[j + 1]) {
int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t;
}
}
}
for (int i = 0; i < n; i++) printf("%d ", a[i]);
printf("\n"); // 1 2 5 7 9
return 0;
}
11.3
Recursión
English
Recursion 递归 is a function that calls itself. It needs a base case 基准情形 to stop, and a recursive call that steps toward it. Without a base case it never ends.
Common mistakes
Binary search needs a sorted array; recursion needs a base case.
Each recursive call must move closer to the base case, or the stack overflows.
Bubble and insertion sort are O(n²) — fine to learn, slow at scale.
Español
La recursión 递归 es una función que se llama a sí misma. Necesita un caso base 基准情形 para detenerse, y una llamada recursiva que se acerque a él. Sin un caso base, nunca termina.
#include <stdio.h>
int factorial(int n) {
if (n <= 1) return 1; // base case
return n * factorial(n - 1); // recursive call
}
int main(void) {
printf("%d\n", factorial(5)); // 120
return 0;
}
Errores comunes
La búsqueda binaria necesita un arreglo ordenado; la recursión necesita un caso base.
Cada llamada recursiva debe acercarse al caso base, o la pila desbordará.
El ordenamiento burbuja y el de inserción son O(n²): adecuados para aprender, pero lentos a gran escala.
12Files & errors · Archivos y errores
12.1
Archivos de texto
English
fopen returns a file pointer 文件指针; the mode 模式 string says what to do — "w" write, "r" read, "a" append. Write with fprintf, read with fscanf, and always fclose when done.
Español
fopen devuelve un puntero a archivo; la cadena de modo indica qué operación realizar — "w" para escribir, "r" para leer, "a" para añadir. Escriba con fprintf, lea con fscanf y siempre cierre el archivo con fclose cuando haya terminado.
#include <stdio.h>
int main(void) {
FILE *out = fopen("scores.txt", "w"); // open for writing
fprintf(out, "Alice 80\nBob 95\n");
fclose(out);
FILE *in = fopen("scores.txt", "r"); // open for reading
char name[20];
int score;
while (fscanf(in, "%s %d", name, &score) == 2) {
printf("%s -> %d\n", name, score);
}
fclose(in);
return 0;
}
fopen → lectura/escritura → fclose
12.2
Manejo de errores con códigos de retorno
English
C has no exceptions. Instead a function signals failure with a return code 返回码 — by convention 0 means success and non-zero means an error. The caller checks the code before trusting the result. (fopen follows the same idea: it returns NULL when it fails.)
Common mistakes
Check that fopen did not return NULL before reading or writing.
Always fclose a file when you are done.
Return a non-zero code from main to signal an error to the caller.
Español
C no tiene excepciones. En su lugar, una función sinaliza un fallo mediante un código de retorno: por convención, 0 significa éxito y un valor distinto de cero indica un error. El llamador verifica el código antes de confiar en el resultado. (fopen sigue el mismo principio: devuelve NULL cuando falla.)
#include <stdio.h>
// returns 0 on success, -1 if the divisor is 0
int safe_divide(int a, int b, int *result) {
if (b == 0) return -1; // error code
*result = a / b;
return 0; // success
}
int main(void) {
int r;
if (safe_divide(10, 2, &r) == 0)
printf("10 / 2 = %d\n", r); // 10 / 2 = 5
if (safe_divide(10, 0, &r) != 0)
printf("cannot divide by zero\n"); // error reported
return 0;
}
Errores comunes
Verifique que fopen no devolvió NULL antes de leer o escribir.
Cierre siempre el archivo con fclose cuando termine de usarlo.
Devuelva un código distinto de cero desde main para indicar un error al llamador.
13Bits & data · Bits y datos
13.1
Bits, binario y operadores bit a bit
English
A bit 位 is a single 0 or 1; numbers are stored in binary 二进制. Bitwise 按位 operators work on the bits directly: & AND, | OR, ^ XOR, << shift left (×2 each step), >> shift right (÷2).
Hexadecimal 十六进制 (base 16) writes binary compactly: one hex digit is exactly four bits. Write hex literals with 0x; print with %x:
Español
Un bit 位 es un único 0 o 1; los números se almacenan en binario 二进制. Los operadores bit a bit 按位 actúan directamente sobre los bits: & AND, | OR, ^ XOR, << desplazamiento a la izquierda (×2 por cada paso), >> desplazamiento a la derecha (÷2).
#include <stdio.h>
int main(void) {
int a = 12; // 1100
int b = 10; // 1010
printf("%d\n", a & b); // 8 AND -> 1000
printf("%d\n", a | b); // 14 OR -> 1110
printf("%d\n", a ^ b); // 6 XOR -> 0110
printf("%d\n", a << 1); // 24 left shift
printf("%d\n", a >> 1); // 6 right shift
return 0;
}
La notación hexadecimal 十六进制 (base 16) escribe el binario de forma compacta: un dígito hexadecimal equivale exactamente a cuatro bits. Escribe literales hexadecimales con 0x; imprime con %x:
#include <stdio.h>
int main(void) {
printf("%d\n", 0xFF); // 255 (0x marks a hex literal)
printf("%x\n", 255); // ff
printf("%x\n", 12); // c
return 0;
}
Los operadores bit a bit actúan sobre los bits de los enteros
13.2
Codificación por longitud de corrida
English
Run-length encoding (RLE) is a simple compression 压缩 method: replace each run 游程 of repeated characters with a count and the character. It is lossless 无损 — the original is fully recoverable.
Common mistakes
& is bitwise AND and && is logical AND — do not confuse them.
A left shift << 1 doubles a value; a right shift >> 1 halves it.
Bit n has value 1 << n (C has no ** power operator); check a bit with (x >> n) & 1.
Español
La codificación por longitud de corrida (RLE, por sus siglas en inglés) es un método simple de compresión 压缩: reemplaza cada corrida 游程 de caracteres repetidos con un contador y el carácter. Es sin pérdida 无损 — el original se puede recuperar completamente.
#include <stdio.h>
#include <string.h>
int main(void) {
char *s = "aaabbc";
int n = strlen(s);
for (int i = 0; i < n; ) {
char c = s[i];
int run = 0;
while (i < n && s[i] == c) { run++; i++; }
printf("%d%c", run, c); // 3a2b1c
}
printf("\n");
return 0;
}
Errores comunes
& es AND bit a bit y && es AND lógico — no los confundas.
Un desplazamiento a la izquierda << 1 duplica un valor; un desplazamiento a la derecha >> 1 lo reduce a la mitad.
El bit n tiene el valor 1 << n (C no tiene el operador de potencia **); verifica un bit con (x >> n) & 1.
14Preprocessor & qualifiers · Preprocesador y calificadores
14.1
Preprocesador, const, static, enum
English
The preprocessor 预处理器 runs before compiling. #define makes a macro 宏 — plain text replaced everywhere. const makes a constant 常量 that cannot change. static inside a function keeps a variable's value between calls. An enum (enumeration 枚举) names a set of integers starting at 0.
Bigger programs split across files: declarations go in a header 头文件 file (mine.h), included with #include "mine.h" — quotes mean your own file, < > means the standard library. An include guard (#ifndef MINE_H / #define MINE_H / #endif) stops a header being included twice.
Common mistakes
#define does plain text replacement with no type checking; wrap macro bodies and arguments in parentheses.
A const value cannot be changed after it is set.
A static local variable keeps its value between calls to the function.
Español
El preprocesador se ejecuta antes de compilar. #define crea una macro — texto plano que se reemplaza en todas partes. const define una constante que no puede modificarse. static dentro de una función mantiene el valor de una variable entre llamadas. Un enum (enumeración) nombra un conjunto de enteros que comienza en 0.
#include <stdio.h>
#define MAX 100 // macro: text replaced before compiling
enum Color { RED, GREEN, BLUE }; // named integers 0, 1, 2
int next_id(void) {
static int count = 0; // keeps its value between calls
count++;
return count;
}
int main(void) {
const double PI = 3.14; // cannot be changed
printf("%d %.2f\n", MAX, PI); // 100 3.14
printf("%d %d %d\n", RED, GREEN, BLUE); // 0 1 2
int a = next_id();
int b = next_id();
printf("%d %d\n", a, b); // 1 2
return 0;
}
Los programas más grandes se dividen en varios archivos: las declaraciones van en un archivo de cabecera (mine.h), que se incluye con #include "mine.h" — las comillas indican tu propio archivo, mientras que los ángulos < > indican la biblioteca estándar. Una protección contra inclusión múltiple (#ifndef MINE_H / #define MINE_H / #endif) evita que una cabecera sea incluida dos veces.
Errores comunes
#define realiza un reemplazo de texto sin verificación de tipos; encierra los cuerpos y argumentos de las macros entre paréntesis.
Un valor const no puede cambiarse después de haber sido asignado.
Una variable local static conserva su valor entre llamadas a la función.
#define, const, enum, y static mantienen el código claro
Pick one and the site follows you — notes, papers, videos and practice all open on it. · Selecciona uno y el sitio te sigue — notas, documentos, videos y práctica se abren en él.
Type to search notes, lessons, code, vocabulary and past-paper questions across every subject. · Escribe para buscar notas, lecciones, código, vocabulario y preguntas de exámenes anteriores en todas las materias.