tener en cuenta que el largo de la palabra no se calcula, lo que hace el compilador es agregar un “flag” de terminacion nulo en la palabra, asi por ejemplo printf(), sabe hasta donde imprimir la palabra “Mauro”, me explico:
Aqui definimos una variable de tipo “char *” la la cual le damos la direccion a la palabra mauro, la cual esta almacenada en el “stack”, (Sector de memoria de lectura durante el runtime)
char *str ="Mauro";
la cosa es que en realidad lo que hizimos fue hacer esto:
char *str ="Mauro\0";
el carater '\0' es un caracter especial que indica una terminacion nula, en pocas palabras es el caracter de la posicion cero en la tabla ASCII
por lo cual pordemos iterar sobre toda la palabra sin saber implicitamente su largo
// libreria para la funcion "write"#include<unistd.h>voidput_char(char c){// write es una funcion de llamada al sistema para imprimir// al standart output, por ahora pueden pensarlo como// que simplemente esta imprimiendo un caracterwrite(1,&c,1);}intmain(void){// definimor la variable char *str ="Mauro";// en cada iteracion movemos el puntero hasta que el valor// que almacena el mismo sera '\0'for(;*str; str++){put_char(*str);}// imprimimos la nueva linea// recuerden que "\n" != '\n'put_char('\n');}
si tienen algun duda no duden en preguntar, y agradecere su laik prros :v
No entendí el comentario: recuerden que "\n" != '\n'
@gonzagramaglia cuando usas doble comilla, estas refiriendote a un conjuntos de caracteres, por lo cual C lo manejara como tal, haciendo que este retorne un puntero al heap donde se encuentra allocado en memoria, en cambio cuando lo haces con comlla sencilla, indicas que es un unico caracter, el cual lo maneja como un numero, diras, pero porque entonces cuando lo imprimo se muestra como una letra? es porque printf realiza una interpretacion del mismo numero binario de entero a un caracter en ASCII, esto tiene que ver mas con la interpretacion en memoria en C
Es claro que esta explicacion puede tener mas profundidad, pero a razgos generales, eso es la idea principal del por que no son lo mismo
Atento a mas dudas :thumbsup:
++char * name++ y ++char name[]++
No entendía muy bien los usos prácticos y diferencias de estas dos sentencias.
Resulta que:
Cuando declaramos un valor que no va a ser modificado, es más eficiente para el programa tenerlo como puntero y no como array porque así no crea copias ni reserva espacio adicional en memoria.
Aquí esta el post que me ayudo a entenderlo
Es justo lo que busacaba.
Que buena aclaracion
De hecho manejar strings dentro del límite ASCII estándar en C no es la gran cosa.
El problema es cuando quieres representar carácteres individuales (%c) como la ñ y vocales acentuadas, para eso tienes que usar Unicode y en ninguno de los cursos de C que hay en Platzi ni siquiera mencionan el uso de los locales ni de widechar.
Afortunadamente, stackoverflow es tu amigo y una gran fuente de información para complementar con lo enseñado en clase.
Dualidad puntero vector: Quiere decir que puede hacer el recorrido de la siguiente forma:
name[i]; --> Con esto aplicara el recorrido por referencia es lo mismo a *(name+i);
¿Por qué la dirección de memoria es diferente si lo hago de esa manera no debería ser la misma?
#include <stdio.h>int main(){ char * name ="Mauro";printf("Name=%s(%p) \n", name, name);for(int i =0; i <5; i++){printf("name[%d] forma name +i(%p)=%c\n", i, name + i,*(name + i));}for(int i =0; i <5; i++){printf("name[%d] forma name[i](%p)=%c\n", i, name[i], name[i]);}return0;}
Debes tener en cuenta que definiste implícitamente un arreglo. Entonces si quieres ver la dirección de cada elemento de name[i] deberás usar &name[i] para llenar el place %p. Para ver el contenido sólo name[i] . Saludos.
#include <stdio.h>
int main()
{
char * name = "Mauro";
printf("Name=%s(%p) \n", name, name);for(int i =0; i <5; i++){printf("name[%d] forma name +i(%p)=%c\n", i, name + i,*(name + i));}printf("\n");for(int i =0; i <5; i++){printf("name[%d] forma name[i](%p)=%c\n", i,&name[i], name[i]);}return0;
}
Si eso me imaginaba, pero creía que me iba a mandar error, pero en vez de eso me regresa la dirección de una manera ¿resumida? ¿Por qué pasa eso en concreto?
Podríais compartirme enlaces con documentación sobre el lenguaje C?
No me importa si esta en inglés (casi que lo prefiero).
Yo uso , es una gran fuente de documentación casi que para cualquier lenguaje.
Que bonita clase, me gusto. Ahora entiendo porque se dice que C ayuda a entender como funciona la memoria y la teoría de la computacion en general.
Y al mismo tiempo el saber ensamblador ayuda a entender C y todo el trabajo que nos ahorra. Es por eso que son importantes las bases.
Una hermosura.
Hola a todos,
Les comparto el resultado de esta lección;
Existe la posibilidad de que el tamaño de un arreglo sea determinado por los caracteres que ingrese el usuario (osea una variable; tamaño indefinido)...?
Podrías ingresar un string y luego ver su tamaño con la función strlen() y asignarlo a una variable y ese tamaño asignarlo al arreglo.
Ejem:
char cadena[]="hola mundo";// aquí el ejemplo del string int tamano =strlen(cadena);// le estamos asignando a una variable el tamaño de el string "cadena" int mi_array[tamano];// aquí le asignamos el tamaño al array con la variable "tamano"```
No olvides usar la librería <string.h> para que funcione ;)
Entonces no puedo usar strlen con un scanf?
Sin duda esto de los pointers es bastante complejo e interesante.
¿Existe otras formas de definir un string en C?
Ademas de estas maneras:
int main(){ char * name ="Adrian";}
int main(){ char name[]="Adrian";}
Sí, definiendo su longitud sin definir su contenido:
//Nombre de longitud de 20 caractereschar nombre[20]
¿Por qué no necesita que desrefenciar el puntero para imprimir mauro?
printf("Name=%s(%p) \n", name, name);
¿No debería ser ?
printf("Name=%s(%p) \n",*name, name);
Esto pasa porque name ya es un puntero, no debes hacer referencia a su posición en memoria.
Hola, no entendí nada de este video, siempre un string tiene que ser un puntero??? y tampoco entendí la impresión:
printf("name[%d] (%p) = %c\n", i, name + i, *(name + i));
La funcion printf es una funcion de C que te permite escribir a pantalla una salida de datos
el primer parametro de printf es una de las opciones que menciono del link de la documentacion, es para indicarle al programa que tipo de dato voy a mostrar de salida
como ejemplo
%d indica que un entero es lo que se va a mostrar de salida
%c indica que un caracter es lo que se va a mostrar de salida
%s indica que una cadena es lo que se va a mostrar de salida
y asi segun sea la necesidad
Todos deben ir dentro de un string por eso se maneja la siguiente estructura
int x =5;char c ='a';char cadena[10]="cadena";printf("%s %c %d", cadena, c, x);
Donde los siguientes parametros seran los que tendras que imprimir, estos son los que sean necesarios en base a lo que tu estes mandando a salida de pantalla
Si tienes mas dudas, puedes preguntar
Espero te sea de ayuda, buen dia
tener en cuenta que el largo de la palabra no se calcula, lo que hace el compilador es agregar un "flag" de terminacion nulo en la palabra, asi por ejemplo printf(), sabe hasta donde imprimir la palabra "Mauro", me explico:
Aqui definimos una variable de tipo "char *" la la cual le damos la direccion a la palabra mauro, la cual esta almacenada en el "stack", (Sector de memoria de lectura durante el runtime)
char *str ="Mauro";
la cosa es que en realidad lo que hizimos fue hacer esto:
char *str ="Mauro\0";
el carater "\0" es un caracter especial que indica una terminacion nula, en pocas palabras es el caracter de la posicion cero en la tabla ASCII
por lo cual pordemos iterar sobre toda la palabra sin saber implicitamente su largo
// libreria para la funcion "write"#include <unistd.h>voidput_char(char c){// write es una funcion de llamada al sistema para imprimir// al standart output, por ahora pueden pensarlo como// que simplemente esta imprimiendo un caracterwrite(1,&c,1);}int main(void){// definimor la variable char *str ="Mauro";// en cada iteracion movemos el puntero hasta que el valor// que almacena el mismo sera '\0'for(;*str; str++){put_char(*str);}// imprimimos la nueva linea// recuerden que "\n" != '\n'put_char('\n');}
si tienen algun duda no duden en preguntar, y agradecere su laik prros :v
Al final de la cadena de caracteres (string), se finaliza con el caracter '\0'. Esto es lo que le dice a printf que es el final de la cadena.
Para "ver" de forma mas clara, podemos usar la funcion strlen(canena) o ensayar y hacer nuestra propia version de strlen():
#include <stdio.h>int ft_strlen(char *str){ int i; i =0;while(str[i]!='\0') i++;return(i);}int main(void){ char *s ="hola Mundo"; int i; i =0;while(i <ft_strlen(s)){printf("s%d = %c \n", i, s + i, s[i]); i++;}return(0);}
Hay otras 3 bibliotecas que son útiles para el manejo de carácteres especiales en cadenas de texto:
<wchar.h> //provee la variable tipo wchar_t
<stddef.h> //también provee wchar_t, entre otras cosas
<locale.h> //requerido para mostrar texto Unicode
Si se han dado cuenta, al imprimir carácteres fuera del rango ASCII estándar (como la ñ y vocales acentuadas), con los formatos %s y %ls se ve el texto sin problema (con scanf %s/%ls, o con fgets) pero si intentan imprimir el carácter individualmente con %c, les arrojará mojibake. Para imprimir carácteres especiales hacen uso de cualquiera de estas 2 bibliotecas, configuran el locale y ya podrán mostrar estos carácteres uno por uno correctamente con %lc
Por ejemplo:
#include <stdio.h>#include <wchar.h>#include <locale.h>#include <string.h>int main(){setlocale(LC_ALL,""); char mitexto[64]; wchar_t mitexto_w[128];printf("Este es una entrada de texto estándar:\n> ");scanf("%s",&mitexto);freopen(NULL,"r", stdin);freopen(NULL,"w", stdout);wprintf(L"Este es una entrada de texto widestring:\n> ");wscanf(L"%ls",&mitexto_w);freopen(NULL,"w", stdout);putchar('S');printf("\nEste es una salida de texto estándar: '%s'\n", mitexto);for(int i =0; i <=strlen(mitexto); i++)printf("%i-%c\n", mitexto[i], mitexto[i]);freopen(NULL,"w", stdout);putwchar('W');wprintf(L"\nEste es una salida de texto widestring: '%ls'\n", mitexto_w);for(int i =0; i <=wcslen(mitexto_w); i++)wprintf(L"%i-%lc\n", mitexto_w[i], mitexto_w[i]);return0;}
Para finalizar, si la consola se atasca, pueden usar freopen() para forzar el flujo de I/O ya que cada vez que se imprime o se lee texto wide con wprintf/wscanf este flujo es modificado y no vuelve automáticamente “a la normalidad”. A menos que usen un solo tipo de texto (char o widechar) a lo largo de todo el código, esto será necesario para desatascar la lectura y escritura de datos si mezclan chars con widechars.
Nota: La L es un prefijo necesario para indicar que se trata de un texto longstring o widechar, este prefijo no se usa con fgetws o scanf, pero con wscanf y wprintf sí.
Tengo dos variables: char * cadena e int * numero. Porque al inicializar de esta forma:
char * cadena ="Samuel";int * numero =654;printf("Cadena:%s", cadena);printf("Numero:%d", numero);
Me ocasiona problemas en el numero y no en la cadena ?.
Se imprime la cadena sin problema pero el numero no, me menciona este error al compilar:
primer_string.c:Infunction‘main’:primer_string.c:6:17: warning: initialization makes pointer from integer without a cast [-Wint-conversion] int * numero =55;^~```
Bueno no se si sea tarde ya, pero la razón es que numero es un puntero a una variable tipo int, no una variable tipo int,osea, numero DEBE apuntar a una variable tipo int. Recuerda que los punteros solo almacenan direcciones en memoria, en pocas palabras es como si quisieras meter en una variable tipo char un valor int.
Espero te ayude.
Los punteros solo almacenan el numero de memoria, pero no la variable.
// Las cadenas (strings) son sólo arrays de 'chars' (caracteres)```