Je lis un fichier dans un programme utilisant C. dans le fichier J'ai des dates chacune dans une ligne distincte exactement comme ceci:
#include <stdio.h> #include <stdlib.h> void FileRead(FILE *pr) { char date [15]; fgets(date,15,pr); printf("date : %s", date); } int main() { char x; FILE *pr; pr=fopen("mytextfile.txt","r"); if(pr==NULL) { printf("File can not be opened."); return 0; } while(scanf("%c", &x)) { switch(x) { case 'v' : FileRead(pr); break; case 'k' : return 0; } } fclose(pr); return 0; }
Maintenant, je veux que le programme les lise comme dates et trouvez la différence entre la date actuelle et ces dates. est-il possible de convertir ces dates dans un format lisible par C? quelque chose comme ceci: 2019.01.01
Actuellement, je le lis en utilisant fgets
et je ne parviens pas à le convertir au format ci-dessus.
Voici mon code:
20190101 20190304 20180922
3 Réponses :
Une fois que vous avez char *
via fgets
, utilisez atoi
pour convertir en entier. Ensuite, vous avez la date au format AAAAMMJJ. Ensuite, vous pouvez faire
const int day = dateYYYYMMDD % 100; const int month = (dateYYYYMMDD % 10000)/100; const int year = dateYYYYMMDD / 10000;
Vous pouvez utiliser C Date et heure fonctions pour obtenir la date actuelle.
Pour faire la différence entre la date actuelle et ces dates, une option consiste à convertir toutes les dates en Date julienne et ensuite faire une différence de nombre sur les dates juliennes.
Si obtenir la date julienne est difficile, normaliser à la même année (en ajoutant 365 ou 366 basé sur l'année est bissextile ou non à mesure que vous passez d'une année inférieure à une année supérieure). Arrivez ensuite au même mois, puis faites la différence de jour.
Éviter d'utiliser atoi
, c'est fournir zéro la possibilité de valider la conversion. Utilisez plutôt strtol
. Ou bien que ce ne soit pas génial, mais mieux serait de lire avec fgets
et l'analyse avec sscanf
. Au moins, vous avez une mesure du succès / échec de la conversion.
Le résultat est, il vous suffit de boucler les lignes du fichier et de définir une condition if dans celui-ci
20190315 20190304 20180922
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> int main(void) { char buff[20]; time_t now = time(NULL); strftime(buff, 20, "%Y%m%d\n", localtime(&now)); printf("Today : %s \n\n", buff); static const char filename[] = "file.txt"; FILE *file = fopen(filename, "r"); if (file != NULL) { char line[128]; /* or other suitable maximum line size */ while (fgets(line, sizeof line, file) != NULL) /* read a line */ { fputs(line, stdout); /* write the line */ if (strcmp(line, buff) == 0) printf("\nThis line of date equal to current date\n"); } fclose(file); } else { perror(filename); /* why didn't the file open? */ } return 0; }
référence indéfinie à getline.
La réponse est correcte, je viens de l'exécuter dans mon système Ubuntu, quelle est votre plate-forme? Les fenêtres ? linux? Mac ? c'est l'erreur de configuration du système! changez #define _GNU_SOURCE avec votre source à l'aide de [link] ( stackoverflow.com/questions/13112784/... )
Il imprime la date actuelle, mais le problème est toujours là, imaginez maintenant qu'il y a un mot dans la première ligne et un mot dans la deuxième ligne et la date dans la troisième ligne. maintenant, comment lire uniquement la troisième ligne (date) et soustraire le nombre de jours de la date actuelle à cela?
problème encore des moyens? référence indéfinie à getline. ??
Non, c'est bien maintenant. et s'il y a un mot dans la première ligne et un mot dans la deuxième ligne et la date dans la troisième ligne. maintenant, comment lire uniquement la troisième ligne (date) et soustraire le nombre de jours de la date actuelle à cela?
Le moyen le plus simple d'approcher la différence d'ici là est de lire les dates du fichier et de les analyser en mois, jour et année ( m, j, y
). Si vous n'allez pas faire une validation complète de chaque conversion, un moyen simple de séparer l'année à 4 chiffres et le mois et le jour à 2 chiffres consiste à utiliser fscanf
avec le champ approprié -width modificateurs pour limiter la conversion au nombre de chiffres requis, par exemple
$ ./bin/time_from_now2 dat/3dates-w-headers.txt non-date line: This file contains dates to read and convert to days. non-date line: The file also contains this description and dates in the format: non-date line: non-date line: yyyymmdd date[1] 01/01/2019 is 6348645.00 sec (73.4797 days) from now. date[2] 03/04/2019 is 991845.00 sec (11.4797 days) from now. date[3] 09/22/2018 is 15078645.00 sec (174.521 days) from now.
Ensuite, tout ce qui est nécessaire dans la boucle est de renseigner le struct tm code > avec les valeurs de l'année, du mois et du jour (en vous rappelant de soustraire
1900
de l'année, et de définir chacun des membres heure, minute et seconde sur zéro et le membre heure d'été sur -1 ). Une fonction simple peut le faire et renvoyer
time_t
après avoir appelé mktime
, par exemple
$ cat dat/3dates-w-headers.txt This file contains dates to read and convert to days. The file also contains this description and dates in the format: yyyymmdd 20190101 20190304 20180922
Pour terminer, tout ce dont vous avez besoin est pour obtenir les valeurs time_t
et appelez difftime
pour obtenir la différence en secondes entre l'heure actuelle et l'heure lue dans le fichier sous la forme d'une valeur double
. En continuant la boucle dans main ()
, par exemple
#include <stdio.h> #include <time.h> #define MAXC 1024u /* if you need a constant, #define one (or more) */ time_t fill_broken_down_time (int y, int m, int d) { /* initialize struct members */ struct tm bdt = { .tm_sec=0, .tm_min=0, .tm_hour=0, .tm_mday=d, .tm_mon=m>0?m-1:0, .tm_year=y-1900, .tm_isdst=-1 }; return mktime(&bdt); /* return mktime conversion to time_t */ } int main (int argc, char **argv) { /* use filename provided as 1st argument (stdin by default) */ FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; int y, m, d, n = 1; char buf[MAXC]; /* buffer to hold each line read from file */ if (!fp) { /* validate file open for reading */ perror ("file open failed"); return 1; } while (fgets (buf, MAXC, fp)) { /* read each line in file */ /* if line isn't a date line, just output line as non-date line */ if (sscanf (buf, "%4d%2d%2d", &y, &m, &d) != 3) { printf ("non-date line: %s", buf); continue; } time_t now = time(NULL), then = fill_broken_down_time (y, m, d); double secs = difftime (now, then); /* get seconds between dates */ printf ("date[%d] %02d/%02d/%04d is %11.2f sec (%g days) from now.\n", n++, m, d, y, secs, secs / 86400.0); } if (fp != stdin) fclose (fp); /* close file if not stdin */ return 0; }
En le mettant complètement, vous pouvez faire quelque chose comme:
./yourprogram < your_date_file
Je ne parviens pas à ouvrir le fichier. plus je veux montrer la différence en jours. et si la première ligne est un nom, le deuxième nom de famille et la troisième une date?
Bravo, David! cela semble une solution incroyable et devrait être la réponse. quelque chose d'autre m'est venu à l'esprit, pouvons-nous utiliser des instructions if en même temps tout en lisant des fichiers en utilisant fgets
et scanf
? si oui, je voudrais ajouter autre chose à cette question.
Bien sûr, c'est la beauté de la programmation, vous pouvez ajouter toutes les conditions supplémentaires que vous souhaitez dans n'importe quelle boucle. La condition que je viens de vérifier vérifie si la ligne ne parvient pas à analyser y, m d
- si c'est le cas, je l'imprime comme expliqué ci-dessus et je vais chercher la ligne suivante. Vous pouvez changer cela comme vous le souhaitez. Essayez-le et si vous avez des problèmes, faites-le moi savoir.
Fonctionne bien maintenant. Je vous dois beaucoup. Je vous remercie.
D'ACCORD. J'ai ajouté quelques valeurs dans le fichier. la première ligne est le nom, la deuxième est le numéro de plaque comme AA333BB
, la troisième est la valeur bool
1
ou 0
, quatrième est le coût 100,00
et la date finale. dans mon cas, il s'agit d'un record pour un client. J'en ai beaucoup dans le même fichier mais séparés seulement par une ligne vide. Maintenant, je veux imprimer le nom et le numéro de plaque de chaque enregistrement, si la date est plus d'un an à partir de maintenant. et bien sûr je veux vérifier si le type est 1
je dois imprimer un vlaue et si son 0
je devrais en imprimer un autre. Je ne suis pas en mesure de comprendre votre exemple dans ce cas, pouvons-nous faire cela?
si le type est 1, je veux multiplier le coût par 1,5
et s'il vaut 0 je veux qu'il soit multiplié par 2,5
. Je sais que cela a l'air bizarre mais dites-moi si c'est possible.
Ce que vous voudrez faire est d'utiliser le compteur n
pour contrôler ce que vous lisez. Vous pouvez simplement faire while (fgets (..)) {switch (n) {case 1: / * gérer la 1ère ligne * / break; cas 2: / * gérer le numéro de plaque * / break, ....
L'autre option est de tester le contenu de chaque ligne - mais si vous savez qu'elle a un format fixe et ce que les lignes contiennent, alors un simple compteur et switch
ou un if (n == 1) ... else if (n == 2) ... else if ...
est un plus simple marche à suivre.
Sur votre multiplicateur de coût, vous pouvez rendre le nom de fichier obligatoire comme argv [1]
(1er argument du programme), puis passer 0
ou 1
comme < code> argv [2] (2ème argument) définissant une valeur par défaut de '0'
ou '1'
si aucun 2ème argument n'est passé. (par exemple, int multflag = argc> 2? argv [2] [0]: '1'
; (qui définit simplement multflag
au 1er caractère de argv [ 2]
si fourni ou '1'
par défaut en utilisant l'opérateur ternaire . Ensuite, vous pouvez simplement vérifier if (multflag ==
'0' ) val * 2.5; else val * 1.5;
Rien d'extraordinaire. (La bonne manière serait d'utiliser getopt
et de configurer un schéma de prise d'options - mais c'est pour plus tard....)
Et notez ... les guillemets simples autour de '0'
et '1'
(vous lisez les arguments comme des caractères de la ligne de commande) donc lorsque vous comparez le multflag
assurez-vous de comparer avec "0"
ou "1"
:)
Sûr. Je vais essayer de vous faire savoir s'il y a eu un problème. :)
@ DavidC.Rankin J'ai posé la question ici stackoverflow.com/questions/55191612/...
C a une bibliothèque de traitement de date intégrée: en.wikipedia.org/wiki/C_date_and_time_functions
Existe-t-il un moyen d'obtenir cette date comme entrée et de trouver la différence entre le courant et l'entrée?
@TomasAnda Oui, mais sans une tentative de votre part dans votre question pour le faire vous-même (voir comment créer un exemple reproductible minimal a>) peu de gens seront enclins à vous aider.
"Actuellement, je l'ai lu en utilisant fgets et je ne suis pas capable de le convertir au format ci-dessus" -> postez votre code, sinon c'est juste un message d'écriture du code pour moi.
Oui, vous lisez chaque ligne, séparez l '
année, mois, jour
et utilisez cela pour remplir unestruct tm
(qui représentera alors le temps décomposé), que vous passez enmktime
pour convertir entime_t
que vous pouvez utiliser pour obtenir la différence en secondes par rapport à l'heure actuelle (généralement obtenue aveclocaltime ()
).@GovindParmar J'ai également ajouté le code.
printf ("Le fichier ne peut pas être ouvert.")
est l'exemple canonique d'un mauvais message d'erreur. Il ne dit pas quel fichier, il ne dit pas pourquoi il n'a pas pu être ouvert et il imprime le message dans le mauvais flux.if (fopen (chemin, mode) == NULL) {perror (chemin); ...