Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Semana 8
Clase 13
Agenda
1 Pixeles 2 Punteros
3 malloc 4 scanf
Pixeles
★ Podemos aumentar cada vez más y más una imagen, pero pronto
veremos píxeles individuales, como lo siguiente.
★ Puesto que esta imagen está almacenada con un número finito de
bytes, puede que cada uno representando un valor de rojo, verde o
azul por cada píxel, por lo tanto hay un número finito de píxeles.
Adobe photoshop, un
software de edición de
imágenes popular,
incluye un seleccionador
de color que se ve algo
similar a este.
¿Por qué es importante manejar los
canales de colores de una imagen?
Resulta que hay otro sistema base, hexadecimal, o base-16, donde hay 16
dígitos:
0 1 2 3 4 5 6 7 8 9 A B C D E F
address.c
1 #include <stdio.h>
2 int main(void)
3 {
4 int n = 50;
5 int *p = &n;
6 printf("%p\n", p);
7 }
★ “%p” es la secuencia de escape para imprimir una dirección con printf. Y
solo tenemos que usar el nombre de la variable p, luego de haberla
declarado.
address.c
Obtendremos algo similar a la
1 #include <stdio.h>
siguiente salida.
2
3 int main(void) {
4
$ make address
int n = 50;
5 int *p = &n; $ ./address
6 printf("%p\n", p); 0x7ffda0a4767c
7 printf("%i\n", *p);
50
8 }
★ En la memoria, podríamos tener una variable p, con el valor de una
dirección almacenada, por ejemplo 0x123, y otra variable, un entero,
con el valor 50, en esa dirección.
Observa que p toma 8 bytes, debido a que en sistemas de computadores
modernos, 64 bits son usados para poder corresponder a las direcciones
con billones de bytes de memoria disponible. Con 32 bits, solo podemos
contar hasta 4 billones de bytes, o alrededor de 4GB de memoria.
Strings
address.c
1 #include <stdio.h>
2
3 int main(void)
4 {
5 char *s = "HI!";
6 printf("%s\n", s);
7 }
★ Obtendremos la misma salida que con cs50.h
$ make address
$ ./address
HI!
En la librería CS50, un string es definido con typedef char *string;. Con
typedef, estamos creando un tipo de dato personalizado para la palabra
string, haciéndolo equivalente a char*.
Comparar strings
Cuando comparamos dos cadenas, vemos que las mismas entradas hacen que
nuestro programa imprima "Different":
compare.c
1 #include <cs50.h>
2 #include <stdio.h>
$ ./compare
3
4 int main(void) { s: HI!
5 char *s = get_string("s: ");
6
t: HI!
char *t = get_string("t: ");
7 if (s == t) Different
8 printf("Same\n");
9 else
10 printf("Different\n");
11 }
★ Cada string es un puntero, char *, a una ubicación diferente en la
memoria, donde se almacena el primer carácter de cada cadena.
1 #include <stdio.h>
2
3 int main(void) {
4 int numbers[] = {4, 6, 8, 2, 7, 5, 0};
5 printf("%i\n", *numbers);
6 printf("%i\n", *(numbers + 1));
7 printf("%i\n", *(numbers + 2));
8 printf("%i\n", *(numbers + 3));
9 printf("%i\n", *(numbers + 4));
10 printf("%i\n", *(numbers + 5));
11 printf("%i\n", *(numbers + 6));
12 }
★ Obtendremos la siguiente salida:
$ make address
$ ./address
4
6
8
2
7
5
0
★ Resulta que solo necesitamos agregar 1 a las direcciones de numbers,
en lugar de 4 (incluso a pesar de que los ints tienen un tamaño de 4
bytes), debido a que el compilador ya conoce que el tipo de cada valor
en numbers es 4 bytes. Con + 1, estamos diciéndole al compilador que
se mueva al siguiente valor en el arreglo, no el siguiente byte.
copy.c
1 #include <cs50.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 int main(void) {
8 char *s = get_string("s: ");
9 char *t = malloc(strlen(s) + 1);
10 for (int i = 0, n = strlen(s) + 1; i < n; i++)
11 t[i] = s[i];
12
13 t[0] = toupper(t[0]);
14 printf("s: %s\n", s);
15 printf("t: %s\n", t);
16 }
★ Creamos una nueva variable para apuntar a un nuevo string con char *t.
El argumento de malloc es el número de bytes que nos gustaría usar.
Sabemos la longitud de s, pero necesitamos agregar 1 para el carácter
nulo o ‘\0’.
copy.c
1 #include <cs50.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 int main(void) {
8 char *s = get_string("s: ");
9 char *t = malloc(strlen(s) + 1);
10 strcpy(t, s);
11 t[0] = toupper(t[0]);
12 printf("s: %s\n", s);
13 printf("t: %s\n", t);
14 free(t);
15 }
También debemos evitar posibles errores.
copy.c
. . .
. . .
scanf
Podemos pedir datos usando la librería estándar, stdio.h, con la función scanf.
scanf.c
1 #include <stdio.h>
2
3 int main(void)
4 {
5 int x;
6 printf("x: ");
7 scanf("%i", &x);
8 printf("x: %i\n", x);
9 }
★ scanf toma un formato, %i, por lo que la entrada se lee para ese
formato. También pasamos la dirección en la memoria donde
queremos que vaya esa entrada “&x”.
$ make scanf
$ ./scanf
x: 50
x: 50
Intentemos nuevamente, pero ahora para strings.
scanf.c
1 #include <stdio.h>
2
3 int main(void)
4 {
5 char *s;
6 printf("s: ");
7 scanf("%s", s);
8 printf("s: %s\n", s);
9 }
★ make previene de cometer este error, así que lo usaremos clang para
demostrarlo.
★ No hemos asignado ninguna memoria para “s”, por lo que se está
escribiendo en una dirección desconocida en la memoria.
scanf.c