Seguimos buscando a Arshak. Ayudanos compartiendo!
Encuesta no oficial de docentes
Resultados de la encuesta no oficial de docentes
Probaste el SIGA Helper?

Donar $100 Donar $200 Donar $500 Donar mensualmente


Enviar respuesta 
 
Calificación:
  • 0 votos - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Buscar en el tema
Trabado con un tipo de ejercicios especifico de archivos
Autor Mensaje
nanohueso Sin conexión
Profesor del Modulo A
Thats what she said
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 239
Agradecimientos dados: 269
Agradecimientos: 30 en 20 posts
Registro en: Feb 2012
Mensaje: #16
RE: Trabado con un tipo de ejercicios especifico de archivos
Gente, estoy teniendo dificultad para comprender la funcion strtok( char * , caracter delimitador);
O sea
Código de ejemplo

/* Compile options needed: none
*/


#include <string.h>
#include <stdio.h>

char string[] = "a string,of ,,tokens";
char *token;

void main(void)
{
token = strtok(string," ,"); /*There are two delimiters here*/
while (token != NULL){
printf("The token is: %s\n", token);
token = strtok(NULL," ,");
}
}


Y la salida es esto

El token es: una
El token es: cadena
El token es: de
El token es: tokens

No entiendo como es que funcion strtok , token es un array de punteros ? , la verdad que estoy mareado
31-01-2014 15:24
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Dios Sin conexión
Presidente del CEIT
.
********

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 1.057
Agradecimientos dados: 32
Agradecimientos: 160 en 132 posts
Registro en: Dec 2011
Mensaje: #17
RE: Trabado con un tipo de ejercicios especifico de archivos
No, token es un puntero a char. Supongo que estarás al tanto de que el nombre de una variable array es un puntero a la primera posición de memoria del array. Por eso después de que declarás


char string[] = "a string,of ,,tokens";




El nombre "string" es un puntero que apunta al inicio del string.
Ahora bien, si pusieras


char string[] = "a string,of ,,tokens";
char *token = string+2;
printf("%s",token);




La salida va a ser "string,of ,,tokens", porque token está apuntando al inicio de string más dos posiciones.
La función strtok() usa esto (lo de usar punteros que apuntan a "dentro de un array") en el paso 3 que describo abajo.

strtok(), más o menos, lo que hace es:
  1. Recibe un string (la primera llamada a strtok())
  2. Busca el separador y lo reemplaza con '\0' (para que la cadena termine ahí).
  3. Devuelve el puntero al inicio del token resultante. Así, el string inicial queda "separado" en tokens que empiezan donde dice el puntero devuelto y terminan donde estaba el separador.
  4. En las siguientes llamadas, donde se le manda NULL, sigue buscando a partir del último '\0'.


Entonces, después de cada vez que llamás a la función, token es un puntero al inicio de un string que estaba delimitado por el separador.

Nota al margen: la función main debería ser de tipo int.

«(…)Se arman paquetes… ¿eh?… tecnológicos… tecnológicos portes de… en donde están… este… interrelacionados con las otras capas.(…)»
(Este mensaje fue modificado por última vez en: 31-01-2014 17:03 por Dios.)
31-01-2014 17:01
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] Dios recibio 1 Gracias por este post
nanohueso (31-01-2014)
nanohueso Sin conexión
Profesor del Modulo A
Thats what she said
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 239
Agradecimientos dados: 269
Agradecimientos: 30 en 20 posts
Registro en: Feb 2012
Mensaje: #18
RE: Trabado con un tipo de ejercicios especifico de archivos
(31-01-2014 17:01)Dios escribió:  No, token es un puntero a char. Supongo que estarás al tanto de que el nombre de una variable array es un puntero a la primera posición de memoria del array. Por eso después de que declarás


char string[] = "a string,of ,,tokens";




El nombre "string" es un puntero que apunta al inicio del string.
Ahora bien, si pusieras


char string[] = "a string,of ,,tokens";
char *token = string+2;
printf("%s",token);




La salida va a ser "string,of ,,tokens", porque token está apuntando al inicio de string más dos posiciones.
La función strtok() usa esto (lo de usar punteros que apuntan a "dentro de un array") en el paso 3 que describo abajo.

strtok(), más o menos, lo que hace es:
  1. Recibe un string (la primera llamada a strtok())
  2. Busca el separador y lo reemplaza con '\0' (para que la cadena termine ahí).
  3. Devuelve el puntero al inicio del token resultante. Así, el string inicial queda "separado" en tokens que empiezan donde dice el puntero devuelto y terminan donde estaba el separador.
  4. En las siguientes llamadas, donde se le manda NULL, sigue buscando a partir del último '\0'.


Entonces, después de cada vez que llamás a la función, token es un puntero al inicio de un string que estaba delimitado por el separador.

Nota al margen: la función main debería ser de tipo int.

como es que si le mandas NULL la funcion entiende que tiene que trabajar con el string que estuvo trabajando anteriormente ? jaaj alta magia hay ahi

Duda existencial :
si yo tengo


typedef struct t_nodo{
char codigo[10];
int cantidad;
struct t_nodo *next;
}NODO;




Si creo un puntero NODO , es decir, NODO *aux;
Puedo hacer aux->next= a otra cosa ? , osea es un puntero vacio todavia, no le hice malloc.. como es que funciona?

Mas alla de esa duda existencial

Aca esta toda la parte practica resuelta, ahora si me gusta como esta hecha , mucho mas corto y dinamico



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PATH "~/Documents/InformaticaI/datos.txt"
#define LEN 1020

typedef struct t_nodo{
char codigo[10];
int cantidad;
struct t_nodo *next;
}NODO;

void levantar_archivo(FILE *fp);
void insertar_nodo(NODO **H,NODO *aux);
void buscar_nodo(NODO **H,int mode,char *codigo);

int main(void)
{
NODO *H;
FILE *fp;

H=NULL;
fp = fopen(PATH,"r+t");

levantar_archivo(fp,&H);

return 0;
}

void levantar_archivo(FILE *fp)
{
char buffer[1020];
char *buff;
NODO *aux,*H;
H = NULL

aux = (NODO *)malloc(sizeof(NODO));

while (fgets(buffer,sizeof(buffer),fp) != EOF)
{

buff = strtok(buffer,","); // ahi tengo codigo

strcpy(aux->codigo,buff);

strtok(NULL,","); // descripcion
strtok(NULL,","); //cantidad
strtok(NULL,","); //Observaciones

aux->cantidad = atoi(buff);

insertar_nodo(&H,aux);

}
}

void insertar_nodo(NODO **H,NODO *aux)
{
if( (*H) == NULL) //lista vacia
{
*H = aux;
aux->next = NULL;
}
else
{
NODO *var1;
var1 = *H;
while(var1->next != NULL) // corroboracion de la existencia de otro nodo con el mismo codigo
{
if( strcmp(var1->codigo,aux->codigo) == 0 )
{
aux->cantidad += var1->cantidad;
}
var1=var1->next;
}
aux->next = *H; //insercion al principio de la lista
*H=aux;
}
}

void buscar_nodo(NODO **H,int mode,char *codigo)
{
NODO *aux,*var1;
aux= *H; // es lo mismo que poner aux->next = *H ???
int posicion=0;

while( aux->next != NULL)
{
if( strcmp(aux->codigo,codigo) == 0)
{
if(mode==0)
{
printf("
Codigo: %s y Cantidad:%d
",codigo,aux->cantidad);
}
else if(mode == 1)
{
printf("
Posicion: %d
",posicion);
}
else
{
printf("
Codigo: %s y Cantidad:%d
",codigo,aux->cantidad);
var1->next = aux->next;
free(aux);
}
}
var1->next=aux;
aux=aux->next;
posicion++;
}


(Este mensaje fue modificado por última vez en: 31-01-2014 20:43 por nanohueso.)
31-01-2014 20:06
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Dios Sin conexión
Presidente del CEIT
.
********

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 1.057
Agradecimientos dados: 32
Agradecimientos: 160 en 132 posts
Registro en: Dec 2011
Mensaje: #19
RE: Trabado con un tipo de ejercicios especifico de archivos
(31-01-2014 20:06)nanohueso escribió:  como es que si le mandas NULL la funcion entiende que tiene que trabajar con el string que estuvo trabajando anteriormente ? jaaj alta magia hay ahi

No importa cómo lo hace... es la magia de la abstracción =P

Cuando hacés los strtok() estás perdiendo los valores, acordate de que devuelve un puntero a la ubicación del inicio del token.
Deberías hacer lo mismo que hiciste con aux->codigo para las demás.
Por ejemplo:



buff = strtok(NULL,",");
strcpy(aux->descripcion, buff);





¡A menos que no lo necesites para nada!

(31-01-2014 20:06)nanohueso escribió:  Si creo un puntero NODO , es decir, NODO *aux;
Puedo hacer aux->next= a otra cosa ? , osea es un puntero vacio todavia, no le hice malloc.. como es que funciona?

Depende del contexto.

Si inmediatamente después de declarar el puntero aux intentás acceder a un miembro, debería darte un error en tiempo de ejecución (Segmentation fault o similar) porque el contenido de aux sería "basura".

Ahora, si a aux le asignás una dirección válida de un nodo


NODO *nodo, *aux;
nodo = (NODO*)malloc(sizeof(NODO));
aux=nodo;
aux->next = bla;




Eso sí debería andar (no tiene que estar de corrido todo, puede ser una función que recibe un puntero a un nodo, etc).

De todas maneras, aunque no sé cuánta práctica tenés, igual te digo que el tema de los punteros en C suele ser uno de los que más problemas trae. Hay que usarlos a conciencia y pensando bien qué es y a qué apunta cada uno, y así y todo podés llegar a tener muchos problemas con los famosísimos segmentation fault.

nanohueso escribió:


NODO *aux,*var1;
aux= *H; // es lo mismo que poner aux->next = *H ???
int posicion=0;




No, no es lo mismo, no va a andar si lo hacés así. El puntero recién declarado aux no apunta a nada, su dirección es "basura".
Sólo luego de hacer la asignación aux=*H va a andar cuando intentes acceder a algún nodo.

«(…)Se arman paquetes… ¿eh?… tecnológicos… tecnológicos portes de… en donde están… este… interrelacionados con las otras capas.(…)»
(Este mensaje fue modificado por última vez en: 31-01-2014 22:41 por Dios.)
31-01-2014 22:25
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] Dios recibio 1 Gracias por este post
nanohueso (01-02-2014)
luchovl2 Sin conexión
Presidente del CEIT
Dígame, Ingeniero.
********

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 1.335
Agradecimientos dados: 24
Agradecimientos: 356 en 324 posts
Registro en: May 2009
Mensaje: #20
RE: Trabado con un tipo de ejercicios especifico de archivos
(31-01-2014 14:59)Dios escribió:  Lucho, la condición de tu while está mal. Avanza mientras no sea el carácter '\0' Y el carácter sea coma. En cuanto encuentre uno que no sea coma se sale del while.

s[i] == ',' tiene que ser la condición de un if interior al while.

Cierto. Gracias a Dios. Ahí lo corregí.
01-02-2014 00:39
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
nanohueso Sin conexión
Profesor del Modulo A
Thats what she said
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 239
Agradecimientos dados: 269
Agradecimientos: 30 en 20 posts
Registro en: Feb 2012
Mensaje: #21
RE: Trabado con un tipo de ejercicios especifico de archivos
(31-01-2014 22:25)Dios escribió:  
(31-01-2014 20:06)nanohueso escribió:  como es que si le mandas NULL la funcion entiende que tiene que trabajar con el string que estuvo trabajando anteriormente ? jaaj alta magia hay ahi

No importa cómo lo hace... es la magia de la abstracción =P

Cuando hacés los strtok() estás perdiendo los valores, acordate de que devuelve un puntero a la ubicación del inicio del token.
Deberías hacer lo mismo que hiciste con aux->codigo para las demás.
Por ejemplo:



buff = strtok(NULL,",");
strcpy(aux->descripcion, buff);





¡A menos que no lo necesites para nada!

(31-01-2014 20:06)nanohueso escribió:  Si creo un puntero NODO , es decir, NODO *aux;
Puedo hacer aux->next= a otra cosa ? , osea es un puntero vacio todavia, no le hice malloc.. como es que funciona?

Depende del contexto.

Si inmediatamente después de declarar el puntero aux intentás acceder a un miembro, debería darte un error en tiempo de ejecución (Segmentation fault o similar) porque el contenido de aux sería "basura".

Ahora, si a aux le asignás una dirección válida de un nodo


NODO *nodo, *aux;
nodo = (NODO*)malloc(sizeof(NODO));
aux=nodo;
aux->next = bla;




Eso sí debería andar (no tiene que estar de corrido todo, puede ser una función que recibe un puntero a un nodo, etc).

De todas maneras, aunque no sé cuánta práctica tenés, igual te digo que el tema de los punteros en C suele ser uno de los que más problemas trae. Hay que usarlos a conciencia y pensando bien qué es y a qué apunta cada uno, y así y todo podés llegar a tener muchos problemas con los famosísimos segmentation fault.

nanohueso escribió:


NODO *aux,*var1;
aux= *H; // es lo mismo que poner aux->next = *H ???
int posicion=0;




No, no es lo mismo, no va a andar si lo hacés así. El puntero recién declarado aux no apunta a nada, su dirección es "basura".
Sólo luego de hacer la asignación aux=*H va a andar cuando intentes acceder a algún nodo.

Dios, te agradezco muchisimo tu rpta , me tas re ayudando =D , un abrazo loco

(31-01-2014 22:25)Dios escribió:  
(31-01-2014 20:06)nanohueso escribió:  como es que si le mandas NULL la funcion entiende que tiene que trabajar con el string que estuvo trabajando anteriormente ? jaaj alta magia hay ahi

No importa cómo lo hace... es la magia de la abstracción =P

Cuando hacés los strtok() estás perdiendo los valores, acordate de que devuelve un puntero a la ubicación del inicio del token.
Deberías hacer lo mismo que hiciste con aux->codigo para las demás.
Por ejemplo:



buff = strtok(NULL,",");
strcpy(aux->descripcion, buff);





¡A menos que no lo necesites para nada!

(31-01-2014 20:06)nanohueso escribió:  Si creo un puntero NODO , es decir, NODO *aux;
Puedo hacer aux->next= a otra cosa ? , osea es un puntero vacio todavia, no le hice malloc.. como es que funciona?

Depende del contexto.

Si inmediatamente después de declarar el puntero aux intentás acceder a un miembro, debería darte un error en tiempo de ejecución (Segmentation fault o similar) porque el contenido de aux sería "basura".

Ahora, si a aux le asignás una dirección válida de un nodo


NODO *nodo, *aux;
nodo = (NODO*)malloc(sizeof(NODO));
aux=nodo;
aux->next = bla;




Eso sí debería andar (no tiene que estar de corrido todo, puede ser una función que recibe un puntero a un nodo, etc).

De todas maneras, aunque no sé cuánta práctica tenés, igual te digo que el tema de los punteros en C suele ser uno de los que más problemas trae. Hay que usarlos a conciencia y pensando bien qué es y a qué apunta cada uno, y así y todo podés llegar a tener muchos problemas con los famosísimos segmentation fault.

nanohueso escribió:


NODO *aux,*var1;
aux= *H; // es lo mismo que poner aux->next = *H ???
int posicion=0;




No, no es lo mismo, no va a andar si lo hacés así. El puntero recién declarado aux no apunta a nada, su dirección es "basura".
Sólo luego de hacer la asignación aux=*H va a andar cuando intentes acceder a algún nodo.

Dios, te agradezco muchisimo tu rpta , me tas re ayudando =D , un abrazo loco
(Este mensaje fue modificado por última vez en: 01-02-2014 02:16 por nanohueso.)
01-02-2014 02:16
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
leibniz Sin conexión
Secretario General

*******

Ing. Electrónica
Facultad Regional Buenos Aires

Mensajes: 849
Agradecimientos dados: 46
Agradecimientos: 24 en 17 posts
Registro en: Dec 2012
Mensaje: #22
RE: Trabado con un tipo de ejercicios especifico de archivos
No pude resistirme a no estudiar análisis y probar hacer esto!

En definitiva:
  • Gracias a fscanf no necesitas atoi, lees directamente en los campos del struct.
  • Con strcasecmp ordenas comparando cadenas enteras, no necesitas hacerlo char por char.

Suponemos que por ser librerías estándar, ANSI C, se pueden utilizar sin problemas.

Así me quedó a un programa similar, similar puesto que no copié el prototipo de la función, lo hice todo en el main.

Spoiler: Mostrar


#include <stdio.h>
#include <string.h>
#include <malloc.h>

typedef struct t_nodo {
int edad;
char Nombre[80];
struct t_nodo *siguiente;
} t_nodo;

int main() {
t_nodo *lista = NULL; //la lista donde cargo la lectura
t_nodo *ultimoNodo; //para saber donde agregar el proximo nodo
t_nodo *listaOrdenada = NULL; //la lista donde voy cargando los nodos ordenados
t_nodo *auxOrden; //auxiliar para ordenar
t_nodo *auxNodo; //madera, por favor

FILE *archivo;
char rutaArchivo[]="datos.csv";

archivo=fopen(rutaArchivo,"r");

//leo el archivo de datos y voy cargando la lista
while ( feof(archivo) == 0 ) {
if ( lista == NULL ) { //caso especial, primer elemento
lista=malloc(sizeof(t_nodo));
ultimoNodo=lista; }
else {
ultimoNodo->siguiente=malloc(sizeof(t_nodo)); //el resto de los elementos
ultimoNodo=ultimoNodo->siguiente; }

fscanf(archivo, "%d,%s\n",&ultimoNodo->edad,ultimoNodo->Nombre);
}
ultimoNodo->siguiente=NULL; //el final de la lista!

//Muestro la lista antes de ordenarla
auxNodo=lista;
while ( auxNodo != NULL ) {
printf("%d\t%s\n",auxNodo->edad,auxNodo->Nombre);
auxNodo=auxNodo->siguiente; }
printf("\n\n\n");

//Hora de ordenar...
while ( lista != NULL ) {
auxNodo=lista;
auxOrden=auxNodo;

//busco el menor elemento
while ( auxNodo->siguiente != NULL ) {
auxNodo=auxNodo->siguiente;
if ( strcasecmp(auxNodo->Nombre, auxOrden->Nombre) < 0 ) {
//d printf("%s<%s\n",auxNodo->Nombre,auxOrden->Nombre);
auxOrden=auxNodo; }
}

//d printf("%d\t%s\n",auxOrden->edad,auxOrden->Nombre);

//lo desenlazo de la lista desordenada
auxNodo=lista;
if ( lista == auxOrden ) { //caso especial, desenlazar el primer elemento
lista=auxOrden->siguiente; }
else {
while ( 1 ) {
if ( auxNodo->siguiente == auxOrden ) {
auxNodo->siguiente=auxOrden->siguiente;
auxOrden->siguiente=NULL;
break; }
auxNodo=auxNodo->siguiente; }
}
//lo agrego a la lista ordenada
if ( listaOrdenada == NULL ) { //caso especial, primer elemento
listaOrdenada=auxOrden;
ultimoNodo=listaOrdenada; }
else { //el resto de los elementos
ultimoNodo->siguiente=auxOrden;
ultimoNodo=ultimoNodo->siguiente; }
}

lista=listaOrdenada;
//Muestro la lista despues de ordenarla
auxNodo=lista;
while ( auxNodo != NULL ) {
printf("%d\t%s\n",auxNodo->edad,auxNodo->Nombre);
auxNodo=auxNodo->siguiente; }
printf("\n\n\n");

return 0;
}



Momentos mágicos del código:



fscanf(archivo, "%d,%s\n",&ultimoNodo->edad,ultimoNodo->Nombre);



No estoy seguro de que sea compatible con archivos csv guardados en windows...



strcasecmp(auxNodo->Nombre, auxOrden->Nombre) < 0);



Para encontrar cual nodo es el que debe anteceder al resto.

[Imagen: Leibnitz_signature.svg]
01-02-2014 13:08
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] leibniz recibio 1 Gracias por este post
nanohueso (26-09-2017)
Buscar en el tema
Enviar respuesta 




Usuario(s) navegando en este tema: 1 invitado(s)