View Full Version : [C/C++]Errore caricamento in matrice da file
Salve a tutti,
vi scrivo perché sto incontrando un problema nel caricamento di una matrice nrighe X 2 da un file di testo.
In pratica nel mio file ci sono numeri del genere:
103
520 2214
238 3031
3116 3437
4228 4848
4837 50
ma al momento del caricamento in matrice li carica in modo sbagliato, così:
10
3 5
20 22
14 23
8 30
31 31
16 34
37 42
28 48
48 48
37 50
naturalmente mi scombina tutto e mi restituisce un risultato sbagliato.
Mi potreste dare una mano a capire cos'è che mi da' questo problema?
Grazie :)
The_ouroboros
10-02-2013, 15:45
Senza codice è un po come capire cos'è il rosso per un cieco :doh:
Giusto! :doh:
Ecco il codice della fase di caricamento!
unsigned int missioni[NRIGHE][2],arrayi[NRIGHE],nr=0,i=0,j=0,somma=0,tmp;
int maxgio=-100,num=0;
bool trovato=false,fine=false;
FILE *fin,*fout;
fin=fopen("input.txt","r");
fout=fopen("output.txt","w");
fscanf(fin,"%u",&nr);
for(i=0;i<nr;i++){
for(j=0;j<2;j++){
fscanf(fin,"%u",&missioni[i][j]);
if(missioni[i][j]!=0){
num++;
}
}
}
sottovento
11-02-2013, 04:43
Per curiosita' l'ho fatto girare e mi legge correttamente tutti i dati.
Ce l'hai detta proprio tutta? :D Scusa, intendevo dire: il file input.txt e' un file di testo? Non e' che l'estensione e' sbagliata e i dati sono in altro formato...
Strano che ti funzioni!
Mi sta facendo uscire matto questo codice!:muro:
E' un file di testo .txt, altrimenti neanche lo leggeva...!
Compilo con Dev C++!
Perchè?
sottovento
11-02-2013, 11:12
L'ho compilato con VS2005 (si, e' vecchio ma lo sono anch'io e per ora non mi hanno ancora buttato via). Funziona senza problemi.
Prova a pubblicare il file di testo completo, cosi' vediamo....
Quello nel primo post è il file di testo completo!
sottovento
11-02-2013, 11:28
Quello nel primo post è il file di testo completo!
Scusa ma
103
520 2214
238 3031
3116 3437
4228 4848
4837 50
non puo' essere il file completo, visto che il primo numero dice di leggere 103 coppie, ma ne conto solo 5. (Nel mio test ho modificato questo valore a mano)
Lo so' che può sembrar strano ma è un test datomi da fare e dice 103 righe quando poi ce ne sono solo 5(sta cosa non l'ho capita)infatti ho dovuto modificare il programma aggiungendo la variabile num che mi indica quanti numeri effettivamente ci sono...
Ma anche modificando quel parametro a me esce sbagliato il caricamento.
Boh.
sottovento
11-02-2013, 11:41
Quindi, se scrivi 5 al posto di 103, come dovrebbe effettivamente essere, ottieni lo stesso una sequenza sbagliata?
Perdona l'insistenza ma e' necessario verificare. Cosi' come e' necessario aggiungere i controlli
- sull'apertura del file (fin != NULL);
- sul numero di elementi che vai a leggere con la fscanf(), cosi' da essere sicuri che l'elemento e' stato letto. Siccome leggi un elemento alla volta, fscanf() ti deve ritornare 1. Altrimenti c'e' un errore.
Lo so' che può sembrar strano ma è un test datomi da fare e dice 103 righe quando poi ce ne sono solo 5(sta cosa non l'ho capita)infatti ho dovuto modificare il programma aggiungendo la variabile num che mi indica quanti numeri effettivamente ci sono...
Ma anche modificando quel parametro a me esce sbagliato il caricamento.
Boh.
Quindi, se scrivi 5 al posto di 103, come dovrebbe effettivamente essere, ottieni lo stesso una sequenza sbagliata?
sì:doh:
- sul numero di elementi che vai a leggere con la fscanf(), cosi' da essere sicuri che l'elemento e' stato letto. Siccome leggi un elemento alla volta, fscanf() ti deve ritornare 1. Altrimenti c'e' un errore.
Non ho capito cosa dovrei fare!Sorry!
sottovento
11-02-2013, 11:56
sì:doh:
Non ho capito cosa dovrei fare!Sorry!
Suggerivo di modificare leggermente il codice in modo da esser sicuri che le letture vadano a buon fine.
Insomma, c'e' qualcosa di strano se il tuo codice funziona sul mio computer e non sul tuo, pertanto devi cercare di ottenere piu' informazioni sull'errore.
Qui una libera interpretazione:
unsigned int missioni[NRIGHE][2],arrayi[NRIGHE],nr=0,i=0,j=0,somma=0,tmp;
int maxgio=-100,num=0;
bool trovato=false,fine=false;
int numReadItems;
FILE *fin,*fout;
fin=fopen("input.txt","r");
if (fin == NULL)
{
perror ("Errore apertura input.txt. Errore:");
return -1;
}
// fout=fopen("output.txt","w");
numReadItems = fscanf(fin,"%u",&nr);
if (numReadItems != 1) // Deve ritornare 1 se tutto e' ok
{
printf ("Error reading tuple count\n");
return -1;
}
for(i=0;i<nr;i++){
for(j=0;j<2;j++){
numReadItem = fscanf(fin,"%u",&missioni[i][j]);
if (numReadItem != 1)
{
printf ("Error reading tuple [%d][%d]\n", i, j);
return -1;
}
if(missioni[i][j]!=0){
num++;
}
}
}
Non mi restituisce nulla!
sottovento
11-02-2013, 12:39
Non mi restituisce nulla!
Intendi che non vedi nessun errore e nonostante questo ottieni dei valori errati?
sottovento
11-02-2013, 12:44
Senti, riesci a fare un attachment del tuo file di input?
Non sapendo cos'altro pensare, mi viene da verificare se ci siano dei caratteri "strani" (magari non printabili) nel file....
The_ouroboros
11-02-2013, 13:22
http://i47.tinypic.com/27ywc4z.png
Scusa la mia ignoranza, cosa significa?
The_ouroboros
11-02-2013, 13:26
ho aperto il tuo file in vi e mi da quegli ^M :)
sottovento
11-02-2013, 13:27
Beh, mi sembra che vim e The_ouroboros abbiano colpito un'altra volta :D
Stai leggendo un file che non e' nel formato che ti aspettavi. Nei miei test avevo creato il file in accordo col software, ma ho paura che si debba fare il contrario ;)
Non ci sto capendo molto!:doh:
Quale sarebbe la soluzione?
sottovento
11-02-2013, 17:20
Non ci sto capendo molto!:doh:
Quale sarebbe la soluzione?
Prima di tutto bisognerebbe sapere quali sono le specifiche ;)
1 - se hai scritto il software in base alle specifiche (quindi ti aspetti il numero delle coppie e poi le coppie stesse) allora il file non e' conforme. Potresti chiedere a chi ti ha fornito il file di esportarlo nuovamente (i vari ^M rappresentano una diversa codifica del newline, probabilmente il file e' passato da sistema a sistema);
2 - se la risposta e' "questo c'abbiamo", allora forse e' meglio capire cosa ci devi fare con il file. Supponendo che il file sia comunque nel formato <numero di coppie, <coppie>>, allora puoi semplicemente abbandonare la lettura mediante fscanf() e cercare qualcosa di piu' robusto.
Per esempio, se il file non e' troppo grosso (i computer odierni hanno un sacco di RAM) potrei leggere tutto il file in un botto, portandomelo in un buffer in memoria. Poi potrei scandire il buffer, scartando i caratteri che non mi servono e decodificando i numeri;
3 - Se oltre alla risposta "questo c'abbiamo" e' in dubbio anche il formato del file, non scrivere codice ma cerca di chiarire bene la struttura del file. Dopo di che puoi scrivere del codice elegante e robusto che lo decodifica
Allora il problema è che questo è un esercizio di olimpiadi d'informatica, dove nella descrizione del problema vi sono delle assegnazioni, ma quando vado a testarlo nel loro sistema non passa i test perché non legge il file correttamente.
Per esempio poi vi sono le assegnazioni che non vengono rispettate, di seguito il testo dell'esercizio:
Descrizione del problema:
Il Commissario Basettoni ha presentato a Topolino le missioni che egli dovrà
svolgere segretamente nel corso dell'anno. Per ogni missione, oltre al luogo da
raggiungere, Basettoni ne indica la durata in giorni e la data massima entro
cui deve essere completata. In altri termini, la missione può iniziare in
qualunque giorno dell'anno ma deve durare esattamente il numero di giorni
indicato e terminare non oltre la data di scadenza.
Topolino, presa la lista delle missioni ricevuta da Basettoni, ordina tali
missioni in base alla loro data di scadenza. Quindi, numera i giorni dell'anno
da 1 a 365 (non esistono anni bisestili a Topolinia) e trasforma le date di
scadenza in numeri secondo tale numerazione. Per esempio, se una missione dura
15 giorni e deve essere svolta entro il 18 febbraio, Topolino la vede
semplicemente come una coppia di interi 15 49 (in quanto il 18 febbraio è il
quarantanovesimo giorno dell'anno).
Poiché può effettuare una sola missione alla volta, Topolino non sarà in grado
di svolgerle tutte, pur iniziando una missione il giorno immediatamente
successivo a quello in cui termina la precedente. Vuole perciò sapere il numero
massimo di missioni che è in grado di eseguire rispettando i vincoli sulla loro
durata e scadenza. Supponendo che Topolino già fornisca le coppie di interi
ordinate per scadenza (il secondo membro delle coppie), aiutatelo a calcolare
il massimo numero di missioni che può svolgere.
Per esempio, se ci sono quattro missioni, una di tre giorni da terminare entro
il 5 gennaio, una di quattro giorni entro l'8 gennaio, una di tre giorni entro
il 9 gennaio e una di 6 giorni entro il 12 gennaio, Topolino vi fornisce la
lista di quattro coppie 3 5, 4 8, 3 9 e 6 12. Il numero massimo di missioni che
può svolgere è pari a tre, ossia le missioni corrispondenti alle coppie
3 5, 3 9 e 6 12: la prima missione inizia il primo di gennaio e termina il 3
gennaio; la seconda inizia il 4 gennaio e termina il 6 gennaio; la terza inizia
il 7 gennaio e termina il 12 gennaio. (Notare che, scegliendo la missione
corrispondente alla coppia 4 8, Topolino può svolgere al più due missioni.)
Dati di input :
Il file input.txt è composto da N+1 righe. La prima riga contiene un intero
positivo che rappresenta il numero N di missioni presentate da Basettoni a
Topolino. Le successive N righe rappresentano durata e scadenza delle missioni:
ciascuna riga è composta da due interi d e s separati da uno spazio, a
rappresentare che la corrispondente missione dura d giorni e deve essere
completata entro l's-esimo giorno dell'anno.
Dati di output :
Il file output.txt è composto da una sola riga contenente un intero che
rappresenta il massimo numero di missioni che Topolino può svolgere rispettando
i vincoli su durata e scadenza.
Assunzioni:
- 1 <= N <= 100;
- 1 <= d,s <= 365;
- d <= s
Esempi di input/output: +-----------+------------+
| input.txt | output.txt |
+-----------+------------+
| 4 | 3 |
| 3 5 | |
| 4 8 | |
| 3 9 | |
| 6 12 | |
+-----------+------------+
Vincenzo1968
11-02-2013, 22:04
Ohé,
è un file misto Linux/Windows:
http://img850.imageshack.us/img850/5246/crlflf.jpg
Notepad++ mostra che alcune righe sono terminate con CR/LF(Windows); altre con LF(Linux).
:D
Ma io non capisco ancora da cosa sia dovuto!!!
Ok,può essere un problema del correttore on-line che ha generato sti input sbagliati,ma se io gli riscrivo è sempre lo stesso problema!
Mah
Vincenzo1968
11-02-2013, 22:22
Ti conviene usare un bell'automa come quello che abbiamo utilizzato nel contest 5:
http://www.hwupgrade.it/forum/showthread.php?t=1799059&page=2
e pure più veloce :D :
http://www.hwupgrade.it/forum/showpost.php?p=23702302&postcount=21
http://www.hwupgrade.it/forum/showpost.php?p=23706985&postcount=24
;)
Scusa di che automa parli?:D
Vincenzo1968
11-02-2013, 22:34
Scusa di che automa parli?:D
Non ti fare impressionare dal nome. L'implementazione è una cavolata. Si tratta di un semplice ciclo while:
http://www.hwupgrade.it/forum/showpost.php?p=23706985&postcount=24
;)
Ehm...
Grazie,ma...come avete capito ho cominciato da poco a programmare e ci sto capendo poco di tutto quel codice...
Come dovrei utilizzarlo?
Vincenzo1968
11-02-2013, 22:38
Ehm...
Grazie,ma...come avete capito ho cominciato da poco a programmare e ci sto capendo poco di tutto quel codice...
Come dovrei utilizzarlo?
Domani mattina ti posto il codice adattato per il tuo caso.
Mo me vag' a cucca'.
Buonanotte. ;)
Grazie mille!:)
Mi fa' arrabbiare il fatto che le assunzioni delle variabili sono comprese tra 1 e 365 per d e s, quando poi nel file di test ci sono numeri del tipo 4450, i numero di righe compreso tra 1 e 100 e invece nel test 3500 etc.
Mah!
Comunque aspetto "tue notizie"!:)
...se c'è qualcuno con qualche altra soluzione si faccia avanti!:sofico:
Vincenzo1968
12-02-2013, 11:43
L'automa mi dice che ci sono caratteri non validi.
Non è che il file "input.txt" è nel formato unicode(utf8)? Se si, bisogna utilizzare i caratteri unicode per leggere il file(wchar.h).
Questa cosa non la so', ma scusami non era già venuto fuori che ci fossero caratteri estranei?
Cmq io i numeri gli leggo come interi, cosa dovrei cambiare?
Vincenzo1968
12-02-2013, 13:00
Questa cosa non la so', ma scusami non era già venuto fuori che ci fossero caratteri estranei?
Cmq io i numeri gli leggo come interi, cosa dovrei cambiare?
Si ma con l'automa, visto che leggiamo un byte per volta, non importa se le righe sono terminate una con CR-LF e l'altra con LF.
Il discorso cambia se il file è in formato, per esempio, UTF-8. In questo caso bisogna utilizzare i caratteri unicode(definiti nel file wchar.h) che hanno la dimensione di due byte anziché uno. E bisogna utilizzare le apposite funzioni al posto di fgets, etc.
Si potrebbe implementare ina funzioncina per leggere il formato del file e utilizzare le funzioni appropriate, ASCII/Unicode, in base a quanto restituito dalla funzioncina.
Informati un po'; cerca di sapere in che formato è il file di input.
Ok sto iniziando a capire, ma come dicevo prima non so' di che tipo è il file.
So' solo che è un file txt, che hanno creato per fare i test nel correttore on-line.
Ma siamo sicuri che sia questo il problema del caricamento sbagliato dei numeri in matrice?
The_ouroboros
12-02-2013, 13:47
m ai sottovalurare il formato e come enda la linea (LF o CR+LF)
Vincenzo1968
12-02-2013, 13:55
Con questo file:
5
21 8
55 89
34 2
89 13
3 89
L'output è questo:
http://img221.imageshack.us/img221/2285/stek78.jpg
Questo è il codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#define BUFFER_SIZE 4096
typedef enum tagStati
{
S_ERROR = -1, S0, S1
} Stati;
int GetArraySize(const char *szFileName)
{
int array_size = 0;
FILE *fp;
unsigned char buffer[BUFFER_SIZE + 1];
int numread;
int k;
unsigned char c;
unsigned char byteCR = 0x13;
unsigned char byteLF = 0x10;
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s\n", szFileName);
return S_ERROR;
}
numread = fread(buffer, 1, BUFFER_SIZE, fp);
if (numread == 0)
{
fclose(fp);
printf("Errore 4 nella lettura del file %s\n", szFileName);
return S_ERROR;
}
*(buffer + numread + 1) = '\0';
k = 0;
c = *(buffer + k);
array_size = 0;
while ( c != '\n' )
{
if ( c >= '0' && c <= '9' )
{
array_size = array_size * 10 + c - '0';
}
k++;
c = *(buffer + k);
}
fclose(fp);
return array_size;
}
Stati DFA(const char *szFileName, unsigned int **a, int array_size)
{
Stati stato = S0;
FILE *fp;
unsigned char buffer[BUFFER_SIZE + 1];
int numblocks;
int numread;
char c;
int k, x;
int riga, colonna;
int num;
unsigned char byteCR = 0x13;
unsigned char byteLF = 0x10;
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s\n", szFileName);
return S_ERROR;
}
if ( fseek(fp, 0, SEEK_END) )
return 0;
numblocks = ftell(fp)/BUFFER_SIZE;
if ( numblocks == 0 )
{
numblocks = 1;
}
else
{
if ( ftell(fp) % BUFFER_SIZE != 0 )
numblocks++;
}
fseek(fp, 0, SEEK_SET);
numread = fread(buffer, 1, BUFFER_SIZE, fp);
if (numread == 0)
{
fclose(fp);
printf("Errore 1 nella lettura del file %s\n", szFileName);
return S_ERROR;
}
k = 0;
c = *(buffer + k);
k++;
while ( c != '\n' )
{
if (c == '\0')
{
printf("Errore 2 nella lettura del file.\n");
fclose(fp);
return S_ERROR;
}
c = *(buffer + k);
k++;
}
riga = colonna = 0;
num = 0;
x = 0;
while ( x < numblocks )
{
c = *(buffer + k);
k++;
switch ( stato )
{
case S0:
num = 0;
if ( c >= '0' && c <= '9' )
{
num = c - '0';
stato = S1;
}
else if ( c == '\0' )
{
return stato;
}
else if ( c == '\n' )
{
colonna = 0;
riga++;
if (riga >= array_size)
return stato;
}
else
{
printf("Automa: Stato S0 errore sul carattere -> '%c' k -> %d\n", c, k);
return S_ERROR;
}
break;
case S1:
if ( c >= '0' && c <= '9' )
{
num = num * 10 + c - '0';
}
else if ( c == ' ' )
{
a[riga][colonna] = num;
num = 0;
colonna++;
stato = S0;
}
else if ( c == '\n' )
{
a[riga][colonna] = num;
num = 0;
riga++;
colonna = 0;
stato = S0;
}
else
{
printf("Automa: Stato S1 errore sul carattere -> '%c'\n", c);
return S_ERROR;
}
break;
}
if ( k >= BUFFER_SIZE )
{
numread = fread(buffer, 1, BUFFER_SIZE, fp);
if (numread == 0)
{
fclose(fp);
printf("Errore 3 nella lettura del file %s\n", szFileName);
return S_ERROR;
}
k = 0;
x++;
}
}
fclose(fp);
return stato;
}
int main()
{
clock_t c_start, c_end;
int x, y;
unsigned int **missioni;
int array_size;
Stati stato;
char *szFileName = "inputISO.txt";
c_start = clock();
array_size = GetArraySize(szFileName);
if ( array_size <= 0 )
return;
printf("\nNumero righe: %d\n", array_size);
missioni = (unsigned int**)malloc(sizeof(unsigned int*)*array_size);
if ( missioni != NULL )
{
for ( x = 0; x < array_size; x++ )
{
missioni[x] = (int*)malloc(sizeof(int)*2);
if ( missioni[x] == NULL )
{
printf("Memoria insufficiente.\n");
return S_ERROR;
}
}
}
else
{
printf("Memoria insufficiente.\n");
return S_ERROR;
}
stato = DFA(szFileName, missioni, array_size);
if ( stato == S_ERROR )
{
printf("L'automa ha restituito un errore.\n");
return -1;
}
c_end = clock();
printf("\nTempo impiegato per la lettura del file -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC);
printf("\nGli elementi della matrice:\n");
for ( x = 0; x < array_size; x++ )
{
for ( y = 0; y < 2; y++ )
{
printf("missioni[%d][%d] -> %d\n", x, y, missioni[x][y]);
}
printf("\n");
}
printf("\n");
for ( x = 0; x < array_size; x++ )
free(missioni[x]);
free(missioni);
return 0;
}
Ma non funzionerà se il file in input non è in formato ANSI/ISO.
Se il file in input è in formato UTF-8 dobbiamo modificare il codice in modo da utilizzare i caratteri unicode.
;)
The_ouroboros
12-02-2013, 13:57
Ref: http://en.wikipedia.org/wiki/UTF-8
Vincenzo1968
12-02-2013, 15:08
Questa è la versione unicode:
cut
http://img202.imageshack.us/img202/1894/stek78unicode.jpg
http://img27.imageshack.us/img27/5558/inpututf8.jpg
Stavo facendo alcune prove ed effettivamente creando un file di testo nuovo e scrivendo "a mano" i vari numeri il programma legge tutto correttamente, allora penso sia più che plausibile che i file generati per i test dal correttore non siano dei semplici txt ma formattati, come dite voi in UTF-8...
Ho notato anche che alcune volte i risultati non coincidono anche se facendo i vari calcoli "a mano" il risultato del mio programma è giusto(non è detto che la mia soluzione al problema sia giusta, ma credo di esserci arrivato), quindi penso che ci sia un problema nel correttore che ha generato e testato dei file sbagliati,però comunque mi piacerebbe capire come poter ovviare a questo problema...!:)
Vincenzo1968
12-02-2013, 15:24
Se utilizzi wchar_t, come ho fatto io nell'ultima versione che ho postato, leggi entrambi i tipi di file(ASCII/UNICODE).
Ho modificato il programma in moda che accetti il file da leggere come parametro da riga di comando:
$ ./stek78unicode inputUTF8.txt
Numero righe: 5
Tempo impiegato per la lettura del file -> 0.00000 secondi
Gli elementi della matrice:
missioni[0][0] -> 21
missioni[0][1] -> 8
missioni[1][0] -> 55
missioni[1][1] -> 89
missioni[2][0] -> 34
missioni[2][1] -> 2
missioni[3][0] -> 89
missioni[3][1] -> 13
missioni[4][0] -> 3
missioni[4][1] -> 89
$ ./stek78unicode inputISO.txt
Numero righe: 5
Tempo impiegato per la lettura del file -> 0.00000 secondi
Gli elementi della matrice:
missioni[0][0] -> 21
missioni[0][1] -> 8
missioni[1][0] -> 55
missioni[1][1] -> 89
missioni[2][0] -> 34
missioni[2][1] -> 2
missioni[3][0] -> 89
missioni[3][1] -> 13
missioni[4][0] -> 3
missioni[4][1] -> 89
;)
Vincenzo mi aiuteresti ad implementare l'automa per il mio codice?
Vincenzo1968
12-02-2013, 15:38
Vincenzo mi aiuteresti ad implementare l'automa per il mio codice?
E il codice che ho postato cos'è?
Legge il file che gli passi dalla riga di comando e crea l'array "missioni".
;)
Boh, DevC++ non lo compila neanche!:O
The_ouroboros
12-02-2013, 15:55
Boh, DevC++ non lo compila neanche!:O
non usare quella "cosa" allora:D
Vincenzo1968
12-02-2013, 16:54
Boh, DevC++ non lo compila neanche!:O
Con GCC su Linux compila e funziona perfettamente come hai potuto vedere dagli screeshot. Su Windows con Visual Studio invece compila ma non funziona. Stampa caratteri a muzzo.
Sarà questione di endianess o chissà che altro.
Io comunque passo. Me so' scucciat', ohi!
Mi dispiace :boh:
The_ouroboros
12-02-2013, 17:03
Vai di Code::Blocks (www.codeblocks.org/) molto meglio ;)
Vincenzo1968
12-02-2013, 21:59
Ho capito perché non funziona su Windows. La seguente istruzione:
printf("\nsizeof(wchar_t) = %d\n", sizeof(wchar_t));
restituisce 4 su Linux e 2 su Windows...
Vi rendete conto?
sottovento
13-02-2013, 04:13
Vincenzo
int GetArraySize(const char *szFileName)
{
int array_size = 0;
FILE *fp;
unsigned char buffer[BUFFER_SIZE + 1];
int numread;
int k;
unsigned char c;
unsigned char byteCR = 0x13;
unsigned char byteLF = 0x10;
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s\n", szFileName);
return S_ERROR;
}
numread = fread(buffer, 1, BUFFER_SIZE, fp);
if (numread == 0)
{
fclose(fp);
printf("Errore 4 nella lettura del file %s\n", szFileName);
return S_ERROR;
}
*(buffer + numread + 1) = '\0';
k = 0;
c = *(buffer + k);
array_size = 0;
while ( c != '\n' )
{
if ( c >= '0' && c <= '9' )
{
array_size = array_size * 10 + c - '0';
}
k++;
c = *(buffer + k);
}
fclose(fp);
return array_size;
}
Se nel mio file scrivo, sulla prima riga
12 90 44
la funzione GetArraySize() ritornera' 129044. Secondo me sarebbe meglio ritornare 12.
Inoltre, nella funzione DFA() vai a leggere un blocco di dati dal file, grande AL MASSIMO BUFFER_SIZE bytes, ma poi non ti interessi della dimensione effettivamente letta e continui a scandire il buffer, appunto, fino al raggiungimento di BUFFER_SIZE. Naturalmente questo puo' provocare problemi.
L'istruzione
if ( fseek(fp, 0, SEEK_END) )
return 0;
lascera' ovviamente il file aperto nel caso il return venga eseguito.
sottovento
13-02-2013, 05:40
Dimenticavo
*(buffer + numread + 1) = '\0';
Se la lunghezza del file >= BUFFER_SIZE bytes, questa istruzione mandera' il software in crash.
Se la lunghezza del file e' < BUFFER_SIZE, questa istruzione lascera' un carattere invalido nel buffer.
k = 0;
c = *(buffer + k);
array_size = 0;
while ( c != '\n' )
{
if ( c >= '0' && c <= '9' )
{
array_size = array_size * 10 + c - '0';
}
k++;
c = *(buffer + k);
}
Se l'utente da come input un file composto da una linea sola, questa porzione di codice andra' in crash.
C'e' un'altra criticita': il file viene letto a blocchi di BUFFER_SIZE (=4096) bytes. L'automa non ne e' consapevole.
La funzione DFA() fallira' nella decodifica del file nel caso la fine del blocco cada proprio a meta' della lettura di un numero.
In tal caso ci potrebbe essere un ritorno di quanto finora letto, oppure l'emissione di un codice di errore a seconda dello stato attuale dell'automa.
@Vincenzo: don't get me wrong! Sto solo facendo una pausa, non ce l'ho assolutamente con te. Anzi, mi sei simpatico direi che ci assomigliamo pure (io non porto gli occhiali, pero' :D ). Quanto sto trovando e' fisiologico in un programma scritto in C/C++: se tu ispezionassi il mio codice troveresti le stesse cose
Vincenzo1968
13-02-2013, 10:30
Dimenticavo
*(buffer + numread + 1) = '\0';
Se la lunghezza del file >= BUFFER_SIZE bytes, questa istruzione mandera' il software in crash.
Se la lunghezza del file e' < BUFFER_SIZE, questa istruzione lascera' un carattere invalido nel buffer.
No perché il buffer lo alloco di BUFFER_SIZE + 1. Altrimenti nel contest 5 il programma sarebbe andato in crash alla lettura del primo blocco da 4096 byte visto che leggiamo file di grosse dimensioni.
Per il resto ho adattato il codice del contest 5 dove si supponeva che il file fosse ben formato.
Non ci vuole niente a modificare l'automa per fargli rilevare se la prima riga non è ben formata(89 21 34) o se il file contiene più righe di quelle specificate nella prima riga.
Ma, come dicevo prima, me so' scucciat', ohi! C'è da terminare il contest 19. :O
;)
sottovento
13-02-2013, 10:37
No perché il buffer lo alloco di BUFFER_SIZE + 1.
Dovresti allocarlo di BUFFER_SIZE + 2 :D
In realta',
*(buffer + numread + 1) = '\0';
c'e' un +1 di troppo che ti porta a scrivere alla locazione BUFFER_SIZE+1 che e' fuori dal tuo buffer (l'ultima tua locazione disponibile e' buffer[BUFFER_SIZE] poiche' il buffer ha dimensione BUFFER_SIZE+1)
Vincenzo1968
13-02-2013, 10:54
Ma scusa se alloco BUFFER_SIZE + 1 e leggo dal file BUFFER_SIZE:
numread = fread(buffer, 1, BUFFER_SIZE, fp);
con
*(buffer + numread + 1) = '\0';
Piazzo il terminatore di fine stringa alla fine dei caratteri letti.
Se fread mi legge BUFFER_SIZE = 4096 byte, piazzo il terminatore nel byte 4097 del buffer.
Se fread mi legge meno di BUFFER_SIZE, per esempio 123 byte(perché siamo arrivati alla fine del file), piazzo il terminatore, '\0', nel bite 124.
O no?
sottovento
13-02-2013, 11:05
Ma scusa se alloco BUFFER_SIZE + 1 e leggo dal file BUFFER_SIZE:
numread = fread(buffer, 1, BUFFER_SIZE, fp);
con
*(buffer + numread + 1) = '\0';
Piazzo il terminatore di fine stringa alla fine dei caratteri letti.
Se fread mi legge BUFFER_SIZE = 4096 byte, piazzo il terminatore nel byte 4097 del buffer.
Se fread mi legge meno di BUFFER_SIZE, per esempio 123 byte(perché siamo arrivati alla fine del file), piazzo il terminatore, '\0', nel bite 124.
O no?
Supponiamo il file contenga un solo byte; quindi
numread = 1
*buffer = buffer[0] = carattere letto
Immagino vorrai mettere il terminatore a *(buffer + numread) altresi' detto buffer[numread], cioe' buffer[1], visto che buffer[0] contiene l'ultimo carattere letto da file.
Vincenzo1968
13-02-2013, 11:13
Supponiamo il file contenga un solo byte; quindi
numread = 1
*buffer = buffer[0] = carattere letto
Immagino vorrai mettere il terminatore a *(buffer + numread) altresi' detto buffer[numread], cioe' buffer[1], visto che buffer[0] contiene l'ultimo carattere letto da file.
Giusto.
Comunque in seguito, nei contest successivi, ho eliminato questa pratica di allocare BUFFER_SIZE + 1 e mettere il terminatore di fine stringa alla fine del buffer. Alloco BUFFER_SIZE e durante la lettura dei singoli caratteri, invece di controllare se sto leggendo '\0', controllo che k non sia maggiore o uguale a BUFFER_SIZE. In caso contrario leggo il successivo blocco e riporto il valore di k a zero.
Ma giusta osservazione la tua, grazie per avermelo fatto notare. ;)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.