/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

problemas al leer un csv

 
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
coto.



Registrado: 16 Ago 2007
Mensajes: 5
Ubicación: mos

MensajePublicado: 20/09/2007 1:49 am
Título: problemas al leer un csv

hola

tengo una lista de datos para leer un csv, el csv es tipo esto

12;111
13;112
14;113
15;114
16;115
17;116
18;117
19;118
20;119
21;120
22;121
23;122

bueno pero con mas filas y columnas, y todos con datos enteros.

tengo este codigo:

Cita:
#include <stdio.h>


main(){

char linea[][];
int n;

const char *filename = "C:\\cima.csv";
FILE *Archi;

Archi = fopen(filename,"r"); // abre el archivo
if(Archi==0){ // comprueba si es capaz de abrilo
fprintf(stderr,"Fallo al abrir %s \n",filename); }

while(feof(Archi)){

fgets(linea,n,Archi);
n++;
}

fclose(Archi);



la coña como hago con fgets que lea datos enteros y a la vez haga una matriz bidemensional??? gracias de antemano
Volver arriba
polly



Registrado: 19 Jul 2007
Mensajes: 61

MensajePublicado: 20/09/2007 3:11 am
Título:

la respuesta no la se , pero creo q hay un pequeño fallo en tu programa , no seria en lugar de while(feof(archi)) while( ! feof(archi))
_________________
R.I.P Kurt Cobain
-------------------------
Volver arriba
coto.



Registrado: 16 Ago 2007
Mensajes: 5
Ubicación: mos

MensajePublicado: 20/09/2007 3:21 am
Título:

sisi error de correr...
Volver arriba
mamntc02



Registrado: 30 Abr 2007
Mensajes: 242

MensajePublicado: 20/09/2007 4:45 am
Título:

Hola,

tienes ciertas cosillas q no están bien. La declaración:
Código:
char linea[][];
es errónea. Un array debe tener, a diferencia de los punteros, unas dimensiones definidas, por ser memoria q ser reserva estáticamente. Se puede omitir el primer campo (o dimensión) al declarar funciones, pero no los demás.
A pesar de q puede funcionar esta sentencia tampoco es correcta:
Código:
if(Archi==0){....
Nadie te asegura q NULL esté definido como 0, de hecho ni siquiera es cierto, pq muchos compiladores lo definen como 0L, o como (void *) 0, por tanto usa mejor NULL. También sería correcto:
Código:
if(!Archi){...

Respecto a como recuperar los datos no creo q se pueda hacer directamente, sino q lo vas a tener q hacer a mano, por ejemplo:
Código:

int guardaLinea(int **matrizDatos, char *linea, int row){

   int pos = 0;
   char cadena[20] = {0};

   while(*(++linea) != ';') pos++; // Buscamos el ';'

   memcpy(cadena, linea, pos); //copiamos el primer valor en cadena
   matrizDatos[row][0] = atoi(cadena); // Convertimos a entero

   memset(cadena, 0x0, sizeof(char) * 20);
   memcpy(cadena, &linea[pos], strlen(linea)); //copiamos el segundo valor en cadena
   matrizDatos[row][1] = atoi(cadena); // Convertimos a entero
   
   return 0;
}

Tu código quedaría más o menos:
Código:

int matrizDatos[M][2];
char linea[100] = {0};
...
n = 0;
while(feof(Archi)){

   fgets(linea,100,Archi);
   guardaLinea(matrizDatos, linea, n);
   n++;
}

No he probado q esté bien sólo es orientativo, por lo q es muy posible q tengas q hacer algún cambio.

Saludos.
Volver arriba
DCelso



Registrado: 28 Abr 2004
Mensajes: 112

MensajePublicado: 20/09/2007 7:00 am
Título:

Para poder hacerlo totalmente dinámico deberás recorrer dos veces el archivo.
Una vez para calcular el número máximo de filas y columnas y poder crear la memoria dinámica necesaria.
Y otra vez para leer los datos e insertarlos en la matriz.

Otra opcion sería crear un arreglo TDA enlazado e ir uno a uno creando memorioa e insertando. Pero esto acomplejaría el código.
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3657
Ubicación: Mexico

MensajePublicado: 20/09/2007 7:05 am
Título:

coto. escribió:
tengo una lista de datos para leer un csv, el csv es tipo esto

12;111
13;112
[...]

bueno pero con mas filas y columnas, y todos con datos enteros.
[...]
la coña como hago con fgets que lea datos enteros y a la vez haga una matriz bidemensional

Lo mas importante aqui es que aclares la estructura de cada linea de texto indicando si todos los campos estan separados (excepto el ultimo) por el caracter ';', por ejemplo:
Código:
12;111
12;11112;11112;11113;112
12;11112;111
12;11112;11112;111
...


O estos son pares separados en una linea por algun otro delimitador, por ejemplo espacio blanco:
Código:
12;111 12;111 12;111
12;111 12;111
12;111 12;111 12;111 12;111
...


En cuanto al uso en C de la constante 0 en el contexto de punteros:
Código:
if(Archi == 0){
   fprintf(stderr,"Fallo al abrir %s \n",filename);
}

Es valido ya que en este contexto el uso de la constante resulta en una "null pointer constant". Sin embargo no es politicamente correcto y se prefiere el uso de la macro NULL debido a que esta es mas explicita.

Y para la verificacion de errores es mejor dejar que el mensaje de error se genere de forma automatica mediante la funcion perror:
Código:
if(Archi == NULL){
   perror(filename);
   return EXIT_FAILURE;
}


Por ultimo no es correcto el uso de feof para controlar el bucle ya que se realizaria una iteracion de mas, esto se debe a que la funcion feof solo retorna el valor verdadero despues de que una funcion de lectura trata de leer datos y falla.

En su lugar y si se va a utilizar fgets lo mejor es utilizar el valor de retorno de esta funcion directamente:
Código:
while (fgets(linea, LONG_LINEA, Archi) != NULL){
   
   /* proceso de linea */
   
}
if (ferror(Archi)){
   
   /* manejo de error */
   
}

/* ... */


Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
coto.



Registrado: 16 Ago 2007
Mensajes: 5
Ubicación: mos

MensajePublicado: 20/09/2007 3:10 pm
Título:

ahora tengo esto tal que asi y mis dudas:
Cita:
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#include <string.h>



int guardaLinea(int **matrizDatos, char *linea, int row);

main(){

int matrizDatos[M][2];
char linea[100000] = {0};

int n=0;

const char *filename = "C:\\cima.csv";
FILE *Archi;

Archi = fopen(filename,"r"); // abre el archivo
if(Archi==NULL){ // comprueba si es capaz de abrilo
fprintf(stderr,"Fallo al abrir %s \n",filename); }

while(!feof(Archi)){

fgets(linea,100,Archi);
guardaLinea(matrizDatos, linea, n);
n++;
}

fclose(Archi);

}

int guardaLinea(int **matrizDatos, char *linea, int row){

int pos = 0;
char cadena[100000] = {0};

while(*(++linea) != ';') pos++; // Buscamos el ';'

memcpy(cadena, linea, pos); //copiamos el primer valor en cadena
matrizDatos[row][0] = atoi(cadena); // Convertimos a entero

memset(cadena, 0x0, sizeof(char) * 20);
memcpy(cadena, &linea[pos], strlen(linea)); //copiamos el segundo valor en cadena
matrizDatos[row][1] = atoi(cadena); // Convertimos a entero

return 0;
}




Cita:
int matrizDatos[M][2];


que tiene que ver esa M hay en el medio... no lo cojo por mucho que lo intente.

leugo me da los siguientes erroes al compilar que no doy solucionado a ver quien me ayuda
Cita:

Info :Compiling C:\BC5\BIN\noname00.cpp
Error: noname00.cpp(12,19):Undefined symbol 'M'
Error: noname00.cpp(27,3Cool:Cannot convert 'int ( *)[2]' to 'int * *'
Error: noname00.cpp(27,3Cool:Type mismatch in parameter 'matrizDatos' in call to 'guardaLinea(int * *,char *,int)'
Warn : noname00.cpp(33,2):'matrizDatos' is declared but never used


y de ahi no salgo.. ayuda por favor
Volver arriba
DCelso



Registrado: 28 Abr 2004
Mensajes: 112

MensajePublicado: 20/09/2007 4:59 pm
Título:

Por lo que comentas parece que no te has leido ningún tutorial, libro, apuntes de C. No se puede programar C sin saber C.

En principio M al estar dentro de unos corchetes en la declaración de una variable te da muchas pistas de qué debe de ser. Debe ser un número y además es una de las dimensiones de la matriz declarada. Si char a[2][3] define una matriz de 2 columnas y 3 filas pues entonces si ponemos M será de M filas. Puesto que en la declaración solo pueden ponerse números, nunca se puede usar variables solo te deja la opcion de que es una macro que sirve para identificar un valor a través de un conjunto de palabras más ameno para la lectura del codificador. #define M 3

El siguiente error es también lógico, no le estás pasando de entrada a la función el mismo tipo de dato con que la declaraste. Asi que en la declaración de la funcion pon int *matrizDatos[2]


Para más información leete el libro de C de clase, sino va a ser imposible que puedas seguir programando ya que a cada pregunta que hagas te tendría que remitir a varias páginas de teoría del libro y no acabaríamos nunca.

Venga suerte, y al toro.
Volver arriba
coto.



Registrado: 16 Ago 2007
Mensajes: 5
Ubicación: mos

MensajePublicado: 21/09/2007 1:39 am
Título:

hola

lo de m me lo imaginaba pero nuestro profesor nos decia que los define eran inutiles y que no merecia la pena usarlos...:S solo lo usabamos para el
#define Pi 3.1415

eso esta entendido ahora lo del otro dato no lo entiendo, los punteros siempre fue una asignatura pendiente que poco a poco intento aprender.

libros de c tengo una de anaya que me aclara muchas dudas.. pero no todas como yo quisiera.

un saludo
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 21/09/2007 1:47 am
Título:

coto. escribió:
hola

lo de m me lo imaginaba pero nuestro profesor nos decia que los define eran inutiles y que no merecia la pena usarlos...:S solo lo usabamos para el
#define Pi 3.1415

Hay una macro M_PI con el valor de pi en doble precision, definida en el header math.h


S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
mamntc02



Registrado: 30 Abr 2007
Mensajes: 242

MensajePublicado: 21/09/2007 4:49 am
Título:

Hola,

en mi humilde opinión es mejor usar constantes q #defines por infinitas razones, pero tampoco soy un talibán contra los #defines, como otros Wink Es decir:
Código:

//En lugar de:
#define PI 3.1416
//Es mejor usar
const double PI = 3.1416;

Algunas de las razones las podeis encontrar en: parashift (en inglés)

Saludos.
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 21/09/2007 5:26 am
Título:

Tampoco quiero sentar catedra, pero personalmente las trato de forma diferente simplemente por que son diferentes.
Las macros de literales solo tienen R-value y se resuelven en fase de diseño, su naturaleza es espandirse alla donde haya un identificador con su nombre. Su ventaja es la eficiencia.
En cambio las variables constantes si tienen L-value, incluso en C pueden modificarse en runtime, no asi en C++, pero esto es debido a que son definidas como read-only pasando a una ubicacion de solo lectura y provocando una excepcion si se intenta sobreescribir, algo parecido a los literales de cadena.


S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3657
Ubicación: Mexico

MensajePublicado: 21/09/2007 7:22 am
Título:

coto. escribió:
ahora tengo esto tal que asi y mis dudas

No quiero sonar como un profesor regañon pero simplemente ignoraste lo que te comente y que es fundamental para poder ayudarte: la estructura exacta del archivo de datos, sin esta no es posible desarrollar una solucion que te sea satisfactoria.

Y si vas a programar utilizando el paradigma de programacion estructurada en C++ deberias seguir las indicaciones que ya te dimos como no utilizar feof para controlar la lectura de un archivo.

En lo que respecta al uso o no de constantes simbolicas (macros vs const) esto depende del lenguaje: en C no hay (salvo el uso de enums) otra forma de definir constantes (como ya comento Cheroky en C la palabra reservada "const" NO define constantes) mientras que en C++ "const" si lo hace y por eso se prefiere su uso sobre las macros ("macros are evil" segun el propio autor y la FAQ de comp.lang.c++).

Casi lo olvido: la lectura de un buen libro sobre punteros donde se expliquen las diferencias entre arrays y punteros es necesaria ya que la funcion "guardaLinea" espera un "char **" y tu le estas pasando un "int (*)[2]". Un libro que pone enfasis en el tema de los punteros es:

Pointers on C, 1st edition
Kenneth Reek
Addison Wesley, July 25, 1997
ISBN: 0673999866


Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com