sábado, 1 de marzo de 2008

C: strings, punteros, structs, archivos

Hoy, 9 AM en punto, tengo final de "Lenguaje de programación 2" y no tengo sueño. No deberia haber siesteado 2 horas y media (!).

Es así que para aprovechar el tiempo (?), publico aquí algunas funciones, definiciones, etc, a modo de resumen y repaso.

Strings - Funciones copadas (?)

strcpy(cadena1, cadena2)
Mete el contenido de cadena2 en la cadena1
strcat(cadena1, cadena2)
Lo mismo que hacer cadena1=cadena1+cadena2 en Java
int x=strlen(cadena)
En la variable de tipo entero x guarda la longitud de cadena
strupr(cadena)
Convierte cadena a CADENA. A veces no funca (!) asi que hay recorrer toda la cadena haciendo toupper(char) a cada caracter.
int x=strcmp(cad1,cad2)
Si cad1 y cad2 son iguales, devuelve 0.
Diferencia entre gets(cadena) y scanf("%s",&cadena)
scanf detecta espacio como fin de la cadena
gets guarda toda la cadena, con espacios y todo

Uso de punteros - Ejemplos
int * ptr; // puntero a entero
int x=*ptr; // a x le asigno el entero al que el puntero apunta

int * buscar(int * vec, int num, int tam);
Una funcion que busca el numero num en el vector de enteros vec. tam es el tamaño del vector. La función devuelve un puntero a entero.
Adentro de ella, vec es la direccion de memoria al primer elemento del vector. Si quiero ir al segundo elemento, tengo que hacer vec+1. Para ir al tercero vec+2 y así.
Por eso la implementacion de esa funcion seria:
for(i=0; i<tam;i++)
   if (*(vec+i)==num)
     return (vec+i);
return NULL;
// *(vec+i) es el contenido de la posicion i del vector

Structs
typedef struct alumno {
   int codigo;
   char nya[20];
   float nota;
} alu;

Defino el tipo de dato struct alumno o alu que es una variable compuesta (digamos) por 3 variables adentro. Como el viejo y querido record de Pascal.

Para utilizarlo con funciones, en el main:
struct alumno registro; // poner "alu registro;" es lo mismo
cargar(&registro); // le paso la direccion de memoria
La función cargar sería:
void cargar(struct alumno * reg){
   scanf("%d", &(reg->legajo));
   gets(reg->nya);
   scanf("%f", &(reg->nota));
}

Memoria dinámica
(Incluir la libreria stdlib.h)

int * vec; // defino un puntero a entero llamado vec

vec=(int *) malloc(cantidad*sizeof(int));
Para el puntero vec estoy reservando cantidad*sizeof(int) bytes de memoria. La función calloc es similar, pero los parametros son distintos.

vec=(int *) realloc(vec,cantidadTotal*sizeof(int));
Si quiero redimensionar el espacio que reservé porque me di cuenta que necesitaba mas lugares o porque sì.

free (vec)
Libero la memoria.

Para trabajar con structs, donde es más útil esto de la memoria dinámica y aparte porque seguro me lo toman :P, en el main:
struct alumno * vec;
ingresa(vec,cant);
La función ingresa:
void ingresa(struct alumno * vec, int cant){
   for (int i=0; i<cant; i**){
     scanf("%d",&((vec+i)->legajo));
     gets((vec+i)->nya);
     scanf("%f",&((vec+i)->nota));
   }

Archivos
FILE *arch; // puntero a archivo
arch=fopen("C:\\cpp\\arch.dat","wb+"); //abro el archivo
El parámetro "wb+" crea el archivo. Si el archivo ya existe, lo pisa.
El otro atributo posible (de los usados, digamos) es "rb+", que lo abre para lectura/escritura.

Si me piden "cree el archivo bla y guarde blabla", uso "wb+".
Si me piden "abra el archivo bla y modifque tal registro", uso "rb+".

while (!feof(arch)) recorre el archivo mientras no llegue al fin del mismo.

Para posicionarse en el archivo:
fseek(arch,0,SEEK_SET); //se posiciona al principio
fseek(arch,0,SEEK_END); //se posiciona al final
fseek(arch,x,SEEK_CUR); //para desplazarse x bytes desde la posicion actual

Si necesito saber cuantos registros hay en el archivo.
int cant=ftell(arch)/sizeof(struct alumno); //solo puedo utilizarlo despues de ir a la ultima posicion del archivo.

Para guardar en el archivo:
fwrite(alu,sizeof(struct alumno),1,arch);
 alu es el puntero que apunta (valga la redundancia) a lo que voy a escribir en arch.
 sizeof(struct alumno) es el tamaño de lo que voy a escribir.
 1 es la cantidad bloques (elementos) que voy a guardar.

Hay un par de variantes utiles. Si quiero recorrer mi vector con un for y grabar registro por registro:
fwrite((alu+i),sizeof(struct alumno),1,arch);
O puedo grabar todo mi vector de una:
fwrite(alu,cant*sizeof(struct alumno),1,arch);

fread (para cargar desde el archivo) es más o menos similar. Si quiero leer todo un archivo y meterlo en memoria, luego de reservar ese espacio:
fread(alu,cant*sizeof(struct alumno),1, arch);

Importante: Cada vez que se hace un fwrite o un fread el puntero al archivo avanza una posición.


Archivos de texto
(esto es copypaste, ni bola le di)

FILE *arch=fopen("c:\\cpp\\texto.txt","w"); // (o "r", no se usa b porque no es binario)

fget(aux,80,arch);
Saca del archivo arch 80 caracteres y los mete en la cadena aux

fputs("cadena",arch); //se sobreentiende

fprintf(arch,"%d",alu->nota); //mete el valor de alu->nota en el archivo


Por el momento, nada más. Suerte (?)

((escuchando)) LETHAL - V.A.M.

1 comentario:

Mel dijo...
Este comentario ha sido eliminado por el autor.