[Risolto][C]Leggere numeri da file e invertirne l'ordine

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

[Risolto][C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

Come da consegna devo:
Scrivere una funzione che preso in ingresso il nome di un file contenente interi, lo modifichi in modo da contenere gli stessi interi, ma in ordine decrescente.

Questo è il codice che ho scritto:

Codice: Seleziona tutto

#include<stdio.h>
#include<stdlib.h>
#include "betterio.h"
#define FILENAME_LENGHT 100
int main(void)
{
    puts("Nome del file:");
    char *file =(char) malloc(FILENAME_LENGHT *sizeof(char));
    fgets(file,FILENAME_LENGHT,stdin);
    rmret(file);
    FILE *fp = fopen(file,"r");
    while(!feof(fp))
    {
        // 
    }
    return 0;
}
Il problema è come salvare i numeri letti,uso array di array di char? Uso fgets che legge fino a '\n'? Sono bloccato nel punto in cui devo leggere e salvare i numeri in un array.

Giusto per chiarezza,"betterio.h" contiene rmret che rimuove '\n' che fgets legge e lo sostituisce con '\0'.
Ultima modifica di ubuntumate il sabato 19 settembre 2015, 0:11, modificato 1 volta in totale.
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Avatar utente
Dclaudio1990
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 624
Iscrizione: sabato 11 aprile 2015, 14:31
Distribuzione: openSUSE
Sesso: Maschile
Località: Roma

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da Dclaudio1990 »

Ci sono tanti modi per salvare il contenuto del file , per esempio un array di char, e riscrivere il contenuto nel modo inverso con un ciclo for data la grandezza dell' array , una cosa non mi è chiara gli interi sul file sono gia in ordine crescente?
Ciao :ciao:
"Io penso, dunque sono, ossia esisto."
-René Descartes
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

Suppongo che i numeri siano già ordinati...nella consegna non dice nulla a riguardo.Comunque pensavo di risolvere usando un array di char dinamico che rialloco a ogni carattere che incontro,salvo il carattere nell'array e infine cerco '\n' e tutto ciò che è compreso tra '\n' e il precedente return o indice 0,è un numero.Poi con atoi converto in int e riordino in modo decrescente per poi scrivere su file.

EDIT: Ho provato a implementare l'esercizio richiesto,ma ho questo errore:

Codice: Seleziona tutto

./main num                                                                                                                                      
*** Error in `./main': realloc(): invalid next size: 0x0000000000700240 ***                                                                                                        
======= Backtrace: =========                                                                                                                                                       
/usr/lib/libc.so.6(+0x72055)[0x7f35a9f81055]                                                                                                                                       
/usr/lib/libc.so.6(+0x779a6)[0x7f35a9f869a6]                                                                                                                                       
/usr/lib/libc.so.6(+0x7aa19)[0x7f35a9f89a19]                                                                                                                                       
/usr/lib/libc.so.6(realloc+0x139)[0x7f35a9f8ac69]                                                                                                                                  
./main[0x4007e8]                                                                                                                                                                   
/usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f35a9f2f610]                                                                                                                         
./main[0x400699]                                                                                                                                                                   
======= Memory map: ========                                                                                                                                                       
00400000-00401000 r-xp 00000000 08:02 2360166                            /home/neon/Documenti/Programmazione/Esercizi/file_num_decr/main                                           
00600000-00601000 rw-p 00000000 08:02 2360166                            /home/neon/Documenti/Programmazione/Esercizi/file_num_decr/main                                           
00700000-00721000 rw-p 00000000 00:00 0                                  [heap]                                                                                                    
7f35a4000000-7f35a4021000 rw-p 00000000 00:00 0                                                                                                                                    
7f35a4021000-7f35a8000000 ---p 00000000 00:00 0                                                                                                                                    
7f35a9cf9000-7f35a9d0f000 r-xp 00000000 08:02 8785108                    /usr/lib/libgcc_s.so.1                                                                                    
7f35a9d0f000-7f35a9f0e000 ---p 00016000 08:02 8785108                    /usr/lib/libgcc_s.so.1                                                                                    
7f35a9f0e000-7f35a9f0f000 rw-p 00015000 08:02 8785108                    /usr/lib/libgcc_s.so.1                                                                                    
7f35a9f0f000-7f35aa0aa000 r-xp 00000000 08:02 8786582                    /usr/lib/libc-2.22.so                                                                                     
7f35aa0aa000-7f35aa2a9000 ---p 0019b000 08:02 8786582                    /usr/lib/libc-2.22.so                                                                                     
7f35aa2a9000-7f35aa2ad000 r--p 0019a000 08:02 8786582                    /usr/lib/libc-2.22.so                                                                                     
7f35aa2ad000-7f35aa2af000 rw-p 0019e000 08:02 8786582                    /usr/lib/libc-2.22.so                                                                                     
7f35aa2af000-7f35aa2b3000 rw-p 00000000 00:00 0                                                                                                                                    
7f35aa2b3000-7f35aa2d5000 r-xp 00000000 08:02 8786581                    /usr/lib/ld-2.22.so                                                                                       
7f35aa48d000-7f35aa490000 rw-p 00000000 00:00 0                                                                                                                                    
7f35aa4d2000-7f35aa4d4000 rw-p 00000000 00:00 0                                                                                                                                    
7f35aa4d4000-7f35aa4d5000 r--p 00021000 08:02 8786581                    /usr/lib/ld-2.22.so                                                                                       
7f35aa4d5000-7f35aa4d6000 rw-p 00022000 08:02 8786581                    /usr/lib/ld-2.22.so                                                                                       
7f35aa4d6000-7f35aa4d7000 rw-p 00000000 00:00 0                                                                                                                                    
7fff373fa000-7fff3741b000 rw-p 00000000 00:00 0                          [stack]                                                                                                   
7fff37563000-7fff37565000 r--p 00000000 00:00 0                          [vvar]                                                                                                    
7fff37565000-7fff37567000 r-xp 00000000 00:00 0                          [vdso]                                                                                                    
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Annullato (core dump creato)
Il codice scritto è:

Codice: Seleziona tutto

#include<stdio.h>
#include<stdlib.h>
#define EXCEPTED_ARGS 2
#define CMD_USAGE_ERROR 64

int main(int argc,char **argv)
{
	if(argc < EXCEPTED_ARGS)
	{
		fprintf(stderr,"Error: too few arguments passed.\n");
		exit(CMD_USAGE_ERROR);
	}
	
	FILE *fp = fopen(argv[1],"r"); //apro il file in lettura
	int *v = NULL;// array di interi
	int i = 0;//contatore
	while(!feof(fp))//finchè il file non termina
	{
		v = (int *)realloc(v,i+1);//aggiungo lo spazio per un intero
		if(v == NULL)// se realloc fallisce
		{
			//errore! esco dal ciclo
			fprintf(stderr,"Error: unable to reallocate space in memory.\n");
			break;
		}
		fscanf(fp,"%d",&v[i]);//leggo i numeri
		i++;//aggiono i
	}
	fclose(fp);//chiudo il file
	free(v);//libero lo spazio in memoria
	return 0;
}

RIEDIT: ho deciso di contare prima le righe del file e poi creare l'array con dimensione pari al numero di righe senza impazzire con array dinamici.

Codice: Seleziona tutto

#include<stdio.h>
#include<stdlib.h>
#include "futils.h"
#define EXCEPTED_ARGS 2
#define CMD_USAGE_ERROR 64

int main(int argc,char **argv)
{
	if(argc < EXCEPTED_ARGS)
	{
		fprintf(stderr,"Error: too few arguments passed.\n");
		exit(CMD_USAGE_ERROR);
	}
	
	int a_size = countlines(argv[1]);
	int *v = (int *) malloc(a_size * sizeof(int));
	FILE *fp = fopen(argv[1],"r");
	int i = 0;
	while(!feof(fp))
	{
		fscanf(fp,"%d",&v[i]);
		fprintf(stdout,"Numero: %d\n",v[i]);
	}
	int size = (int)sizeof(v);
	fprintf(stdout,"Dimensione array: %d\n",size);
	free(v);
	fclose(fp);
	return 0;
}
Il problemi sono:
-che mi dice che array ha dimesione pari a 8,che non è vero perchè avrei avuto problemi di overflow.
-visualizza due volte il numero nove,l'ultimo presente nel file.

Qui l'output di gdb:

Codice: Seleziona tutto

(gdb) break 24
Breakpoint 1 at 0x40091c: file main.c, line 24.
(gdb) r num
Starting program: /home/neon/Documenti/Programmazione/Esercizi/file_num_decr/main num
Numero: 1
Numero: 2
Numero: 3
Numero: 4
Numero: 5
Numero: 6
Numero: 7
Numero: 8
Numero: 9
Numero: 9

Breakpoint 1, main (argc=2, argv=0x7fffffffdf68) at main.c:24
24              int size = (int)sizeof(v);
(gdb) print size
$1 = 4196816                  # Perchè diavolo vale 4196816? Forse perchè prima di countlines non è inizializzata?
(gdb) p size
$2 = 4196816               # Qui era una prova con p
(gdb) n
25              fprintf(stdout,"Dimensione array: %d\n",size);
(gdb) p size
$3 = 8                   # Ora diventa 8,perchè?
(gdb) n
Dimensione array: 8
26              free(v);
(gdb) n
27              fclose(fp);
(gdb) n
28              return 0;
(gdb) n
29      }
(gdb) n
0x00007ffff7a57610 in __libc_start_main () from /usr/lib/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.
[Inferior 1 (process 15320) exited normally]
Codice di futils.c : (che dovrebbe essere file-util ma sembra essere futil(e) :D )

Codice: Seleziona tutto

#include "futils.h"
#include<stdio.h>
#include<stdlib.h>
int countlines(const char *filename)
{
	int lines = 0;
	FILE *fp = fopen(filename,"r");
	if(fp == NULL)
	{
		return -1;
	}
	while(!feof(fp))
	{
		if(fgetc(fp) == '\n')
		{
			lines++;
		}
	}
	fclose(fp);
	return lines;
}
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Avatar utente
Dclaudio1990
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 624
Iscrizione: sabato 11 aprile 2015, 14:31
Distribuzione: openSUSE
Sesso: Maschile
Località: Roma

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da Dclaudio1990 »

Ciao , se i numeri sono ordinati leggili con un semplice array di dimensioni dinamiche , puoi vedere la size con :

Codice: Seleziona tutto

fseek(fp, 0L, SEEK_END);
size = ftell(fp);
Una volta che sai la size:

Codice: Seleziona tutto

char array_c=malloc(size);
Fai una lettura sul file completa e con un for scrivi i numeri al contrario.
Dimmi se capisci.
Ciao:ciao:
"Io penso, dunque sono, ossia esisto."
-René Descartes
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

Sinceramente non ho capito fseek e ftell,cercavo una cosa più semplice e che usasse le funzioni spiegate nel pdf da cui ho tratto l'esercizio.

Dopo un momento di debugging con il mitico gdb,ho scoperto che:
-c'è un errore nella funzione countlines perchè i numeri sono 9 nel file( 1 2 3 4 5 6 7 8 9) oppure ho premuto invio dopo il nove e alloca lo spazio per 10 int e non per 9.Quindi il decimo numero fantasma vale 0 dato che non viene mai toccato.
-non incrementavo i!!
-perchè sizeof dice 8 invece di 10?
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da M_A_W_ 1968 »

La realloc() è un crimine contro l'umanità ed equivale a cambiare casa con tanto di trasloco di mobili e masserizie ogni volta che arriva un nuovo ospite. Non va usata con leggerezza, e ai neofiti si ripete semplicemente che non va usata.

Detto questo, gli approcci standard per codesti esercizi sono sostanzialmente due:
1) Doppia lettura del file, la prima per determinare il numero di elementi e preallocare l'array;

2) Inserimento di un elementare header nel file, una singola linea che indichi il numero delle entries presenti (non esime dal controllo successivo di errori, per troppi o troppo pochi dati presenti).

La funzione countlines() proposta è pesantemente errata. Il conteggio delle righe avviene con un idioma assolutamente standard, come il seguente:

Codice: Seleziona tutto

#include <stdio.h>

#define BUFF_SIZE 128

int main(void)
{
   FILE *fin;
   char buff[BUFF_SIZE];
   unsigned int num_lines = 0;

   fin = fopen("MIOFILE.TXT", "r");

   if (NULL == fin)
   {
       fputs("Errore durante l'apertura del file !", stderr);
       return (1);
   }

   while (NULL != fgets(buff, BUFF_SIZE, fin))
   {
       ++num_lines;
   }

   printf("Il file contiene %d linee.\n", num_lines);

   /*
      Per riportare il puntatore all'inizio del file:
      fseek(fin, 0, SEEK_SET);
      oppure
      rewind(fin);
   */

   fclose(fin);

   return (0);
}
Per convertire in valore numerico i dati letti da ciascuna riga si usano atoi() o la più robusta strtol(). Se i dati non fossero ordinati, è sufficiente usare la qsort().
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

M_A_W_ 1968 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4803845#p4803845][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:La realloc() è un crimine contro l'umanità ed equivale a cambiare casa con tanto di trasloco di mobili e masserizie ogni volta che arriva un nuovo ospite. Non va usata con leggerezza, e ai neofiti si ripete semplicemente che non va usata.

Detto questo, gli approcci standard per codesti esercizi sono sostanzialmente due:
1) Doppia lettura del file, la prima per determinare il numero di elementi e preallocare l'array;

2) Inserimento di un elementare header nel file, una singola linea che indichi il numero delle entries presenti (non esime dal controllo successivo di errori, per troppi o troppo pochi dati presenti).

La funzione countlines() proposta è pesantemente errata. Il conteggio delle righe avviene con un idioma assolutamente standard, come il seguente:

Codice: Seleziona tutto

#include <stdio.h>

#define BUFF_SIZE 128

int main(void)
{
   FILE *fin;
   char buff[BUFF_SIZE];
   unsigned int num_lines = 0;

   fin = fopen("MIOFILE.TXT", "r");

   if (NULL == fin)
   {
       fputs("Errore durante l'apertura del file !", stderr);
       return (1);
   }

   while (NULL != fgets(buff, BUFF_SIZE, fin))
   {
       ++num_lines;
   }

   printf("Il file contiene %d linee.\n", num_lines);

   /*
      Per riportare il puntatore all'inizio del file:
      fseek(fin, 0, SEEK_SET);
      oppure
      rewind(fin);
   */

   fclose(fin);

   return (0);
}
Per convertire in valore numerico i dati letti da ciascuna riga si usano atoi() o la più robusta strtol(). Se i dati non fossero ordinati, è sufficiente usare la qsort().
Dunque niente realloc...tanto meglio perchè è un casino da capire e poi credo che generi un poco di overhead con il continuo riallocamento di memoria.
Anyway non mi era proprio passato in mente di usare fgets() per contare le righe,usa un buffer a vuoto ma è sempre meglio di countlines() con fgetch().L'ho capita al volo la tua spiegazione,grazie @M_A_W .Ora continuo a svolgere l'esercizio.
EDIT: in ogni caso non cambia nulla,stesso output di gdb :muro:
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

Re: [C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

Risolto,in modo barbaro,ma ce l'ho fatta a fare sta cosa banale:

Codice: Seleziona tutto

#include<stdio.h>
#include<stdlib.h>
#include "futils.h"
#define EXCEPTED_ARGS 2
#define CMD_USAGE_ERROR 64
#define IOERR 74
int main(int argc,char **argv)
{
	if(argc < EXCEPTED_ARGS)
	{
		fprintf(stderr,"Error: too few arguments passed.\n");
		exit(CMD_USAGE_ERROR);
	}
	
	int a_size = countlines(argv[1]); //#
	int v[a_size];
	FILE *fp = fopen(argv[1],"r");
	int i = 0;
	while(i < a_size)
	{
		fscanf(fp,"%d",&v[i]);
		i = i + 1;
	}
	fclose(fp);
	naive_sort(v,a_size);
	FILE *out = fopen(argv[1],"w");
	if(out != NULL)
	{
		//int k;
		for(int k = 0;k < a_size;k++)
		{
			fprintf(out,"%d\n",v[k]);
		}
	}
	else
	{
		fprintf(stderr,"I/O error\n");
		exit(IOERR);
	}
	return 0;
}
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [RISOLTO][C]Leggere numeri da file e invertirne l'ordine

Messaggio da vbextreme »

Codice: Seleziona tutto

int v[a_size];
attenzione, usando una variabile come dimensione di un vettore il compilatore (se post c'89)genererà in automatico una malloc e una free, è altamente sconsigliato usare quell'obrobrio ed è sempre da preferirsi la forma estesa
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

Re: [RISOLTO][C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

Dici che è meglio usare int *v =(int *) malloc(a_size * sizeof(int)) ?
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [Risolto][C]Leggere numeri da file e invertirne l'ordine

Messaggio da vbextreme »

si
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
ubuntumate
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1180
Iscrizione: giovedì 28 maggio 2015, 18:18
Distribuzione: Windows 7
Sesso: Maschile
Località: Milano

Re: [Risolto][C]Leggere numeri da file e invertirne l'ordine

Messaggio da ubuntumate »

Perfetto! Grazie per questo tuo consiglio :birra:
Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.
ACM/IEEE Code of ethics.
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 15 ospiti