0% encontró este documento útil (0 votos)
16 vistas43 páginas

Lenguaje C

Este documento explica conceptos básicos sobre cadenas de caracteres (strings) en C, incluyendo cómo se almacenan y manipulan strings, funciones útiles de las bibliotecas string.h y ctype.h, y cómo aceptar argumentos de línea de comandos en la función main.

Cargado por

JRoiz
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
16 vistas43 páginas

Lenguaje C

Este documento explica conceptos básicos sobre cadenas de caracteres (strings) en C, incluyendo cómo se almacenan y manipulan strings, funciones útiles de las bibliotecas string.h y ctype.h, y cómo aceptar argumentos de línea de comandos en la función main.

Cargado por

JRoiz
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 43

Lenguaje C

Semana 6

Clase 10
Agenda
1 String 2 string.h

3 ctype.h 4 Argumentos de la
línea de comandos

5 struct
String
En C, las variables de tipo string no existen realmente,
entonces, ¿Cómo funciona esto?

★ Resulta que las strings son sólo arreglos de caracteres y no están


definidos en C pero si en la librería de CS50.

★ Debido a que nuestra string se llama s, la cual es sólo un arreglo,


cada carácter puede ser accedido con s[0], s[1] y así
sucesivamente.
hi.c

1 #include <cs50.h>
2 #include <stdio.h>
3
4 int main(void)
5 {
6 string s = "HI!";
7 printf("%i %i %i\n", s[0], s[1], s[2]);
8 }
★ El resultado del código anterior se verá así, como cuando nosotros
imprimimos una variable tipo char.

$ make hi
$ ./hi
72 73 33
★ En la memoria, nuestras tres variables char se almacenaron así:

H I !
c1 c2 c3

★ Cada carácter de la string se almacenó en un byte de memoria


★ Los strings terminan con el carácter especial, ‘\0’, un byte con todos
sus bits siendo 0, de esa forma nuestro programa sabe dónde termina
el string. A esto se le conoce cómo el carácter nulo. Entonces
necesitamos cuatro bytes para almacenar el string con tres caracteres.

H I ! \0
s[0] s[1] s[2] s[3]
Otro tipo de datos que hemos visto, no necesitan nada al final,
debido a que todas tienen un tamaño fijo. Otros lenguajes o librerías
tienen tipos personalizados que representan números con una
cantidad de bytes variante, entonces hay más precisión, eso puede
ser implementado guardando cuantos bytes cada número tiene.
★ Incluso podemos imprimir el último byte en nuestra string para ver que
su valor sea verdaderamente “0”.
hi.c

1 #include <cs50.h>
2 #include <stdio.h>
3
4 int main(void)
5 {
6 string s = "HI!";
7 printf("%i %i %i %i\n", s[0], s[1], s[2], s[3]);
8 }
$ make hi
$ ./hi
72 73 33 0
★ Podemos escribir un programa para saber el tamaño de una string:

length.c
1 #include <cs50.h>
2 #include <stdio.h>
3
4 int main(void)
5 {
6 string name = get_string("Name: ");
7
8 int i = 0;
9 while (name[i] != '\0')
10 {
11 i++;
12 }
13 printf("%i\n", i);
14 }
★ Probemos con los siguientes casos:

$ make length
$ ./length
Name: HI!
3
$ ./length
Name: BYE!
4
$ ./length
Name: David
5
★ Podemos crear una función para que haga exactamente lo mismo que
el código anterior:

length.c

. . .
13 int string_length(string s)
14 {
15 int i = 0;
16 while (s[i] != '\0')
17 {
18 i++;
19 }
20 return i;
21 }
string.h
★ Resulta que el código de calcular la longitud de un string ya existe.
Podemos usar una función que viene con la librería de string de C,
strlen, para encontrar la longitud de una string.
length.c

1 #include <cs50.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void)
6 {
7 string name = get_string("Name: ");
8 int length = strlen(name);
9 printf("%i\n", length);
10 }
Podemos usar el manual de CS50 para encontrar y aprender acerca
de librerías y funciones. Las librerías estándar vienen con
documentación antigua, llamadas manuales, y no son muy fáciles de
entender para un principiante. Las versiones de CS50 incluyen
documentación más simple para funciones comunes.
★ Podemos intentar imprimir cada carácter de nuestra string en un ciclo:
length.c

1 #include <cs50.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void)
6 {
7 string s = get_string("Input: ");
8 printf("Output: ");
9 for (int i = 0; i < strlen(s); i++)
10 {
11 printf("%c", s[i]);
12 }
13 printf("\n");
14 }
Podemos combinar lo visto y escribir un código que cambie los char a mayúscula:
uppercase.c

1 #include <cs50.h>
2 #include <stdio.h>
3 #include <string.h>
4 int main(void)
5 {
6 string s = get_string("Before: ");
7 printf("After: ");
8 for (int i = 0, n = strlen(s); i < n; i++)
9 {
10 if (s[i] >= 'a' && s[i] <= 'z')
11 {
12 printf("%c", s[i] - 32);
13 }
14 else
15 {
16 printf("%c", s[i]);
17 }
18 }
19 printf("\n");
20 }
★ Probemos con los siguientes casos:

$ make uppercase
$ ./uppercase
Before: hi
After: HI
$ ./uppercase
Before: david
After: DAVID
ctype.h
★ La librería o biblioteca llamada “ctype.h” define varias funciones
que son útiles para probar y manejar caracteres.

★ Podemos buscar en el manual de CS50 “minúscula”, y parece que


hay otra librería, ctype.h, que podemos usar.

★ Podemos reescribir el código anterior para verificar si una letra


es minúscula usando la función “islower”.
ejemplo.c
1 #include <cs50.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 int main(void) {
7 string s = get_string("Before: ");
8 printf("After: ");
9 for (int i = 0, n = strlen(s); i < n; i++)
10 {
11 if (islower(s[i]))
12 {
13 printf("%c", s[i] - 32);
14 }
15 else
16 {
17 printf("%c", s[i]);
18 }
19 }
20 }
★ Según el manual, islower nos retorno un valor diferente a cero si
c, el carácter que le pasamos, es minúscula. Los valores
diferentes a cero son tratados cómo un true (verdadero) en
expresión booleana (el 0 equivale a false).

★ Podemos simplificarlo aún más, y pasar cada carácter a otro


función, toupper, esta función cambia a mayúscula las letras en
minúscula y las letras que ya están en mayúscula no las cambia
ejemplo.c

1 #include <cs50.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 int main(void)
7 {
8 string s = get_string("Before: ");
9 printf("After: ");
10 for (int i = 0, n = strlen(s); i < n; i++)
11 {
12 printf("%c", toupper(s[i]));
13 }
14 printf("\n");
15 }
Argumentos de la línea de
comandos
★ Nuestros propios programas pueden tomar argumentos en la
línea de comando. Podemos cambiar los argumentos de nuestra
función main, ya no va ser “void”, o no va tomar ningún
argumento, ahora haremos esto:
hi.c
1 #include <stdio.h>
2
3 int main(int argc, string argv[])
4 {
. ...
9 }
★ argc y argv son dos variables que nuestra función main va tomar
automáticamente cuando ejecutamos nuestro programa en la línea
de comando. argc es el conteo de argumentos, o la cantidad de
argumentos (palabras) escritas. argv[], es vector de argumento (a
lista de argumento), es un arreglo de argumentos (palabras), no
tiene tamaño específico ya que no sabemos cuantas palabras
habrán.
★ Intentemos imprimir argumentos:

argv.c

1 #include <cs50.h>

2 #include <stdio.h>

3 int main(int argc, string argv[])

4 {

5 printf("hello, %s\n", argv[0]);

6 }
★ El primer argumento, argv[0], es el nombre del programa (la
primera palabra escrita, cómo ./hello).

$ make argv
$ ./argv David
hello, ./argv
★ Vamos a cambiar el código para escribir el argumento que queramos:

argv.c

1 #include <cs50.h>

2 #include <stdio.h>

3 int main(int argc, string argv[])

4 {

5 printf("hello, %s\n", argv[1]);

6 }
★ Cuando corremos nuestro programa sin un segundo argumento,
vemos (null) impreso.

$ make argv
$ ./argv
hello, (null)
$ ./argv David
hello, David
★ Debemos validar que tenemos la cantidad correcta de argumentos:

argv.c

1 #include <cs50.h>
2 #include <stdio.h>
3
4 int main(int argc, string argv[])
5 {
6 if (argc == 2)
7 {
8 printf("hello, %s\n", argv[1]);
9 }
10 else
11 {
12 printf("hello, world\n");
13 }
14 }
★ Ahora, siempre vamos a imprimir algo válido, pero vamos a tener
que actualizar nuestro programa para que acepte más de dos
argumentos.

$ make argv
$ ./argv
hello, world
$ ./argv David
hello, David
$ ./argv David Malan
hello, world
struct
★ Tenemos dos arreglos, names and numbers, y nos aseguraremos que
cada número de cada persona se encuentre en el mismo índice que su
nombre.
★ Buscaremos en el arreglo names el nombre de alguien, y
retornaremos su número de teléfono correspondiente en el mismo
índice.
★ Este programa es correcto, pero mal diseñado, debido a que tenemos
que ser muy cuidadoso con ambos arreglos ya que el índice del
nombre de una persona debe ser igual al índice de su teléfono.
agenda.c

1 #include <cs50.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6 string names[] = {"Carter", "David"};
7 string numbers[] = {"+1-617-495-1000", "+1-949-468-2750"};
8
9 for (int i = 0; i < 2; i++)
10 {
11 if (strcmp(names[i], "David") == 0)
12 {
13 printf("Found %s\n", numbers[i]);
14 return 0;
15 }
16 }
17 printf("Not found\n");
18 return 1;
19 }
★ Resulta que en C podemos definir nuestro propio tipo de dato, o
estructura de datos. Sería un mejor diseño para nuestro programa
tener un arreglo con un tipo de dato person que incluye tanto su
nombre cómo número de teléfono, de esa manera solo podríamos
decir person people[].
★ En C, podemos crear una struct con esta sintaxis:

typedef struct le dice al compilador que


agenda.c
estamos definiendo nuestra propia
5 typedef struct estructura, y person, será el nombre de
6 {
nuestra estructura de datos.
7 string name;

8 string number;
Dentro de struct, tendremos dos strings,
9 }
name y number. A estas dos variables les
10 person;
conoceremos como campos de la
estructura.
En base a esta estructura, nosotros podemos crear nuestra variable del
tipo de la estructura.

agenda.c

5 person alumno;

6 alumno.name = "Juan";
7 alumno.number = "+1-234";
🙍Juan
📱+1-234
agenda.c

14 person people[2];
15
16 people[0].name = "Carter";
17 people[0].number = "+1-617-495-1000";
18
19 people[1].name = "David";
20 people[1].number = "+1-949-468-2750";
21
22 for (int i = 0; i < 2; i++)
23 {
24 if (strcmp(people[i].name, "David") == 0)
25 {
26 printf("Found %s\n", people[i].number);
27 return 0;
28 }
29 }
★ Vemos nueva sintaxis para inicializar el valor de cada variable dentro de la
struct person usando el operador “.”

★ En las ciencias computacionales, la encapsulación es la idea que datos


relacionados se deben agrupar juntas, acá encapsulamos dos piezas de
información, name y number a la misma estructura de datos. El color de un
píxel con valores rojo, verde y azul también pueden ser representados en
una estructura de datos.
¿Preguntas?

También podría gustarte