Buonasera,
Sono abbastanza ferrato in quello che riguarda il linguaggio C "puro", cioè fino a che non devo entrare in contatto con il sistema operativo vado via che è una bellezza. Il problema è appunto quando devo interagire col sistema.
Ho scritto un programma che, dato un nome file esistente e un nome file da creare crea il secondo copiandoci dentro il primo, e la cosa va che è una bellezza. Lo ho poi esteso in modo che riceva (leggendoli da file) il primo dei nomi di file da aprire e il primo di quelli da creare, il programma con un suo algoritmo si genera tutti i nomi files di input possibili successivi a quello dato e prova ad aprirli. Se vi riesce crea il file di output e ci copia dentro il file aperto. Infine genera, sempre tramite algoritmo, il successivo nome file di output.
Per capirci ecco il codice
//Programma che ricopia un file da una posizione a un'altra cambiandone il nome
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char nomein [100];
char nomeou [100];
char nomedati [] = "/home/flavio/Scrivania/input.txt";
char nomescrivi[]="/home/flavio/Scrivania/output.txt";
int myatoi(char stringa[])
{
//Mi serve ottenere l'intero corrispondente ai primi 2 caratteri della stringa,
//anche se è più lunga di 2.
int ritorno=0;
if(stringa[0] >= '0' && stringa[0] <= '9' && stringa[1] >= '0' && stringa[1] <= '9')
{
ritorno=((stringa[0] - '0') * 10 + (stringa[1] - '0')) + 1;
//printf ("La stringa %s corrisponde ad un numero: %d\n", stringa, ritorno);
return ritorno;
}
printf ("La stringa %s non corrisponde ad un numero\n", stringa);
return (0);
}
int GeneraNome(char vecchio[])
{
//Funzione che, dato il vecchio del file, genera quello del successivo
//Regola: La funzione lavora subito prima dell'ultimo punto, alzando di 1 il numero
int lunghezza = strlen(vecchio);
int temporaneo = 0;
//printf ("Chiamato sulla stringa %s\n", vecchio);
for(; vecchio[lunghezza] != '.'; lunghezza--);//Arrivo all'ultimo punto
if(lunghezza > 0)
{
lunghezza--;//Se sono ancora nella stringa passo al carattere precedente
}
else
{
printf("Nessun '%c' nella stringa\n", '.');
return (0);
}
temporaneo = myatoi(&(vecchio[lunghezza - 1]));
if(temporaneo > 0 && temporaneo < 60)
{
//Alzo di 1 i secondi
vecchio[lunghezza - 1] = (temporaneo / 10) + '0';
vecchio [lunghezza] = (temporaneo % 10) + '0';
return (1);
}
//Azzero i secondi
vecchio[lunghezza] = vecchio[lunghezza-1] = '0';
lunghezza-=2;
//Ora sono sull'ultima cifra dei minuti, faccio le stesse operazioni
temporaneo = myatoi(&(vecchio[lunghezza - 1]));
if(temporaneo > 0 && temporaneo < 60)
{
//Alzo di 1 i minuti
vecchio[lunghezza - 1] = (temporaneo / 10) + '0';
vecchio [lunghezza] = (temporaneo % 10) + '0';
return (1);
}
//Azzero i minuti e faccio lo stesso di prima sulle ore
vecchio[lunghezza] = vecchio[lunghezza-1] = '0';
lunghezza-=2;
//E sono sull'ultima cifra delle ore
temporaneo = myatoi(&(vecchio[lunghezza - 1]));
if(temporaneo > 0 && temporaneo < 25)
{
//Alzo di 1 i minuti
vecchio[lunghezza - 1] = (temporaneo / 10) + '0';
vecchio [lunghezza] = (temporaneo % 10) + '0';
return (1);
}
//Se non sono ancora uscito significa che devo alzare il giorno
vecchio[lunghezza] = vecchio[lunghezza-1] = '0';
lunghezza-=2;
printf("Alzare il giorno");
return (0);
}
int GeneraNome2(char vecchio[])
{
//Per semplicità ho diviso la generazione del nome in due funzioni distinte
int lunghezza = strlen(vecchio);
int temporaneo=0;
for(; vecchio[lunghezza] != '-'; lunghezza--);//Arrivo all'ultimo -
if(lunghezza <=0)
{
printf("Nessun '%c' nella stringa\n", '-');
return (0);
}
lunghezza--;
//Sono sull'ultima cifra dei giorni
temporaneo = myatoi(&(vecchio[lunghezza - 1]));
if(temporaneo > 0 && temporaneo < 32)
{
//Alzo di 1 i giorni
vecchio[lunghezza - 1] = (temporaneo / 10) + '0';
vecchio [lunghezza] = (temporaneo % 10) + '0';
return (1);
}
//Azzero i giorni
vecchio[lunghezza]='1';
vecchio[lunghezza-1]='0';
lunghezza-=2;
//Faccio la stessa operazione sui mesi
temporaneo = myatoi(&(vecchio[lunghezza - 1]));
if(temporaneo > 0 && temporaneo < 13)
{
//Alzo di 1 i mesi
vecchio[lunghezza - 1] = (temporaneo / 10) + '0';
vecchio [lunghezza] = (temporaneo % 10) + '0';
return (1);
}
//Dovrei azzerare i mesi e passare agli anni, ma al momento non ho nulla con nome 2020
printf ("Ultimo file raggiunto\n");
return (0);
}
int GeneraNomeOutput (char vecchio[])
{
//Crea il nome dell'output a partire dal vecchio
int inizionome, finenome, i;
inizionome=finenome=strlen (vecchio);
for(; vecchio[finenome] != '.'; finenome--);//Arrivo all'ultimo .
if(finenome > 0)
{
finenome--;//Se sono ancora nella stringa passo al carattere precedente
}
else
{
printf("Nessun '%c' nella stringa\n", '.');
return (0);
}
for(; vecchio[inizionome] != '/'; inizionome--);//Arrivo all'ultimo .
if(finenome <= 0)
{
printf("Nessun '%c' nella stringa\n", '/');
return (0);
}
//Ho i limiti del nome, ora devo solo alzarlo
for (i=finenome;i>inizionome;i--)
{
if (vecchio[i]=='9')
vecchio[i]='0';
else if (vecchio[i]>='0' && vecchio [i]<'9')
{
vecchio[i]++;
return (1);
}
else
{
return (0);
}
}
return (0);
}
int main(int argc, char **argv)
{
int volte = 30, i = 0;
FILE* in = NULL;
FILE* ou = NULL;
FILE* dati = NULL;
FILE* scrivi=NULL;
char carattere = 0;
dati = fopen(nomedati, "r");
if(dati == NULL)
{
printf("%s non aperto\n", nomedati);
return (0);
}
fgets(nomein, 90, dati);
fgets(nomeou, 90, dati);
fclose(dati);
nomein [strlen(nomein) - 1] = 0;
nomeou [strlen(nomeou) - 1] = 0;
printf("File di inizio:%s\nFile di fine:%s\n", nomein, nomeou);
scrivi=fopen (nomescrivi, "w");
while(i < volte)
{
in = fopen(nomein, "r");
if(in != NULL)
{
printf("File %s trovato\n", nomein);
i++;
ou = fopen(nomeou, "w");
if(ou == NULL)
{
printf("PROBLEMA: File %s non aperto!!\nTermine programma", nomeou);
return (0);
}
printf("File %s aperto correttamente, trascrivo\n", nomeou);
while(fscanf(in, "%c", &carattere) != EOF)
{
fprintf(ou, "%c", carattere);
}
printf("Trascrizione completata con successo\n");
GeneraNomeOutput(nomeou);
fclose(ou);
fclose(in);
}
fprintf (scrivi, "%s\n", nomein);
if(GeneraNome(nomein) == 0)//Se non riesco a generare il nome aumentando il numero prima del punto
{
if (GeneraNome2 (nomein)==0)
{
return (0);
}
}
}
fclose (scrivi);
return (0);
}
Come potrete intuire è un metodo funzionante, ma terribilmente lento (una roba che lo fai partire e riesci a farti un caffè prima che sia arrivato a metà). Mi sono chiesto come si possa velocizzare, e mi sono risposto che l'unico modo sarebbe poter conoscere il contenuto della directory di input (magari stampato in un file). Al che mi resterebbe da leggere quel file riga a riga, separando quindi i vari elementi della cartella, passare la riga ad una funzione di controllo (che risponda alla domanda "questo file è di quelli cercati?") e, in caso di risposta affermativa, posso procedere alla copia del file verificato secondo le attuali regole (copia byte a byte in un file di output appositamente creato il cui nome sia generato attraverso una funzione).
Domanda successiva che mi sono posto riguarda la risoluzione di un secondo problema: i files, una volta copiati, devo cancellarli dalla cartella di origine, azione che posso fare manualmente ma idealmente è lunga, e difficile se la regola di copiatura non segue un ordine alfabetico (non è questo il caso, ma non si sa mai). L'operazione di spostamento non sarebbe complicata concettualmente, basterebbe rinominare il file (chiaramente rinominare il vero nome del file, che include la sua posizione), ma ciò non lo so fare. Qual'è (sapendo che deve esistere) una funzione di sistema che lo fa?
Buone feste!