utilidad de timeleft -- ampo con datetime camp codereview Relacionados El problema

timeleft utility


15
vote

problema

Español

Esta utilidad le indica cuánto tiempo se queda hasta el tiempo que establece antes.

Tiempo de configuración:

  newMax1  

usando la utilidad:

  newMax2  

Código:

  newMax3  
Original en ingles

This utility tells you how much time is left until the time you set before.

Setting time:

> timeleft set '2017/04/25;15:00:00' 

Using utility:

> timeleft 2 days, 10 hours, 40 minutes, 25 seconds remaining... 

Code:

#include <string.h> // strcmp #include <stdio.h> // fopen, fclose, fprintf, fscanf, sscanf #include <time.h> // time, mktime  #define TIME_PATH "time.txt"  static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining...\n";     int days = t / 86400; t -= days * 86400;     int hours = t / 3600; t -= hours * 3600;     int minutes = t / 60; t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    }  int main(int argc, char **argv) {     int status = 0;     if (argc <= 1) {         FILE *f = fopen(TIME_PATH, "r");         if (!f) {             fprintf(stderr, "Could not open time\n");             status = 1;         } else {             long t;             if (fscanf(f, "%ld", &t) != 1) {                 fprintf(stderr, "Could not read time\n");                 status = 1;             } else {                 time_t ref = (time_t) t;                 time_t now = time(NULL);                 if (now >= ref) fprintf(stdout, "It's over!\n");                 else printRemainingTime(ref - now);             }             fclose(f);         }     } else if (argc == 3 && strcmp(argv[1], "set") == 0) {         int Y, M, D, h, m, s;         if (sscanf(argv[2], "%d/%d/%d;%d:%d:%d", &Y,&M,&D,&h,&m,&s) != 6) {             fprintf(stderr, "Invalid time format\n");         } else if (Y >= 2038) {             fprintf(stderr, "Do not plan too far ahead!\n");         } else {             struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 };             time_t ut = mktime(&t);             if (ut < 0) {                 fprintf(stderr, "Parsing/range error\n");                 status = 1;             } else {                 FILE *f = fopen(TIME_PATH, "w");                 if (!f) {                     fprintf(stderr, "Failed to save time\n");                     status = 1;                 } else {                     fprintf(f, "%ld", (long) ut);                     fclose(f);                 }             }         }     } else {         fprintf(stderr, "Usage: ");         if (argv[0]) fprintf(stderr, "%s ", argv[0]);         fprintf(stderr, "[set YYYY/MM/DD;hh:mm:ss]\n");     }     return status; } 
     

Lista de respuestas

15
 
vote
vote
La mejor respuesta
 
  1. No se compila sin advertencias bajo clang -Wextra :

      $ clang -Wall -Wextra cr161559.c cr161559.c:43:69: warning: missing field 'tm_gmtoff' initializer       [-Wmissing-field-initializers]             struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 };   
  2. Esperando un semi-colon en los argumentos de la línea de comandos es inconveniente: significa que siempre tiene que citar el argumento al ejecutar el programa desde el shell:

      $ timeleft set 2017/04/25;15:00:00 Invalid time format bash: 15:00:00: command not found   

    Sería mejor usar algún otro formato de entrada, uno que no usa metaduros de shell.

  3. [recomendación eliminada después de la amenaza de la violencia en los comentarios.]

  4. Separación de la Declaración de s De la llamada a fprintf significa que no obtendrá una advertencia (al menos no de las versiones actuales de Clang o GCC ) Si la cadena de formato no coincide con los argumentos. Por ejemplo, si accidentalmente omitió uno de los argumentos:

      const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; /* ... */ fprintf(stdout, s, days, hours, minutes);   

    Luego, la compilación tiene éxito sin previo advertencia bajo Clang y GCC, sino que la salida no tiene sentido:

      $ timeleft 1 days, 22 hours, 33 minutes, 142630783 seconds remaining...   

    pero si hubieras escrito en su lugar:

      printf("%d days, %d hours, %d minutes, %d seconds remaining... ",        days, hours, minutes);      

    Luego clang detecta el problema:

      cr161559.c:12:45: warning: more '%' conversions than data arguments [-Wformat]     printf("%d days, %d hours, %d minutes, %d seconds remaining... ",                                            ~^   
 
  1. It doesn't compile without warnings under clang -Wextra:

    $ clang -Wall -Wextra cr161559.c cr161559.c:43:69: warning: missing field 'tm_gmtoff' initializer       [-Wmissing-field-initializers]             struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 }; 
  2. Expecting a semi-colon in the command-line arguments is inconvenient: it means that you always have to quote the argument when running the program from the shell:

    $ timeleft set 2017/04/25;15:00:00 Invalid time format bash: 15:00:00: command not found 

    It would be better to use some other input format, one that doesn't use shell meta-characters.

  3. [Recommendation deleted following threat of violence in comments.]

  4. Separating the declaration of s from the call to fprintf means that you won't get a warning (at least not from current versions of Clang or GCC) if the format string doesn't match the arguments. For example, if you accidentally omitted one of the arguments:

    const char *s = "%d days, %d hours, %d minutes, %d seconds remaining...\n"; /* ... */ fprintf(stdout, s, days, hours, minutes); 

    then the compilation succeeds without warning under both Clang and GCC, but the output is nonsense:

    $ timeleft 1 days, 22 hours, 33 minutes, 142630783 seconds remaining... 

    But if you had written instead:

    printf("%d days, %d hours, %d minutes, %d seconds remaining...\n",        days, hours, minutes);    

    then Clang detects the problem:

    cr161559.c:12:45: warning: more '%' conversions than data arguments [-Wformat]     printf("%d days, %d hours, %d minutes, %d seconds remaining...\n",                                            ~^ 
 
 
 
 
11
 
vote

Solo unas pocas sugerencias:

Macros estándar

El archivo STDLIB.H contiene dos macros que son muy buenos para usar cuando terminan el programa, 9988777665544330 y EXIT_FAILURE1 . El poder hará main() un poco más legible.

  #include <stdlib.h>  int main(int argc, char **argv) {     int status = EXIT_SUCCESS;     if (argc <= 1) {         FILE *f = fopen(TIME_PATH, "r");         if (!f) {             fprintf(stderr, "Could not open time ");             status = EXIT_FAILURE;         } else {             long t;             if (fscanf(f, "%ld", &t) != 1) {                 fprintf(stderr, "Could not read time ");                 status = EXIT_FAILURE;             } else {                 time_t ref = (time_t) t;                 time_t now = time(NULL);                 if (now >= ref) fprintf(stdout, "It's over! ");                 else printRemainingTime(ref - now);             }             fclose(f);         }   

Ponga cada declaración en su propia línea

Este código podría ser más legible si cada declaración estuvo en su propia línea:

  static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400; t -= days * 86400;     int hours = t / 3600; t -= hours * 3600;     int minutes = t / 60; t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    }   

Ejemplo:

  static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400;     t -= days * 86400;     int hours = t / 3600;     t -= hours * 3600;     int minutes = t / 60;     t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    }   

advertencias del compilador

El compilador que estoy usando está marcando las siguientes líneas para la conversión de tipo implícito de long a int :

      int days = t / 86400;     int hours = t / 3600;     int minutes = t / 60;     int seconds = t;   

Tal vez sería mejor declarar days , EXIT_FAILURE0 , 99887766555443311 99887766555443312 como EXIT_FAILURE3 para que coincida con el mismo tipo que EXIT_FAILURE4 puede mutilar.

Convenciones de nombres variables inconsistentes

En la función EXIT_FAILURE5 tiene las variables EXIT_FAILURE6 , EXIT_FAILURE7 , 99887776655443318 , EXIT_FAILURE9 , main()020 , main()1 . Esto es inconsistente. Hay algunos buenos nombres de variables como main()2 , main()3 , main()4 99887766555443325 y luego están los nombres de variables main()6 (? TIEMPO?) Y main()7 (? CRINA?). Ninguno de estos nombres de variables es muy descriptivo. Si main()8 es para cadena, podría ser mejor llamado main()9 y si 99887776655443330 es para el tiempo Tal vez #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 1 podría ser un nombre mejor.

Dentro del #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 2 FUNCIÓN ES LA DECLARACIÓN DE VARIABLE #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 3 . Quizás los nombres más descriptivos serían #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 4 , #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 55 , #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 36 , #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 77 , 998877665544433338 , #include <stdlib.h> int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (argc <= 1) { FILE *f = fopen(TIME_PATH, "r"); if (!f) { fprintf(stderr, "Could not open time "); status = EXIT_FAILURE; } else { long t; if (fscanf(f, "%ld", &t) != 1) { fprintf(stderr, "Could not read time "); status = EXIT_FAILURE; } else { time_t ref = (time_t) t; time_t now = time(NULL); if (now >= ref) fprintf(stdout, "It's over! "); else printRemainingTime(ref - now); } fclose(f); } 9 .

reducir la complejidad, siga SRP

the Principio de la responsabilidad única establece que cada módulo o clase debe tener la responsabilidad en una sola parte de la funcionalidad proporcionada por el software, y esa responsabilidad debe ser encapsulada por la clase. Todos sus servicios deben estar estrechamente alineados con esa responsabilidad.

Robert C. Martin expresa el principio de la siguiente manera:

Una clase debe tener solo una razón para cambiar.

Si bien esto se dirige principalmente a las clases en idiomas orientados a objetos, se aplica a funciones y subrutinas en idiomas de procedimiento también.

La función principal podría dividirse en al menos 3 funciones:

  static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400; t -= days * 86400;     int hours = t / 3600; t -= hours * 3600;     int minutes = t / 60; t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 0  

El mensaje de error no es bastante correcto

Estos dos mensajes de error no usan el nombre de archivo completo de Time.txt:

  static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400; t -= days * 86400;     int hours = t / 3600; t -= hours * 3600;     int minutes = t / 60; t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 1  

y

  static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400; t -= days * 86400;     int hours = t / 3600; t -= hours * 3600;     int minutes = t / 60; t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 2  

El usuario podría estar engañado para agregar el archivo static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 3 , en lugar del archivo static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 4

 

Just a few suggestions:

Standard Macros

The file stdlib.h contains two macros that are very good to use when terminating the program, EXIT_SUCCESS and EXIT_FAILURE. The might make main() a little more readable.

#include <stdlib.h>  int main(int argc, char **argv) {     int status = EXIT_SUCCESS;     if (argc <= 1) {         FILE *f = fopen(TIME_PATH, "r");         if (!f) {             fprintf(stderr, "Could not open time\n");             status = EXIT_FAILURE;         } else {             long t;             if (fscanf(f, "%ld", &t) != 1) {                 fprintf(stderr, "Could not read time\n");                 status = EXIT_FAILURE;             } else {                 time_t ref = (time_t) t;                 time_t now = time(NULL);                 if (now >= ref) fprintf(stdout, "It's over!\n");                 else printRemainingTime(ref - now);             }             fclose(f);         } 

Put Each Statement on its Own Line

This code might be more readable if each statement was on its own line:

static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining...\n";     int days = t / 86400; t -= days * 86400;     int hours = t / 3600; t -= hours * 3600;     int minutes = t / 60; t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 

Example:

static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining...\n";     int days = t / 86400;     t -= days * 86400;     int hours = t / 3600;     t -= hours * 3600;     int minutes = t / 60;     t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 

Compiler Warnings

The compiler I am using is flagging the following lines for implicit type conversion from long to int:

    int days = t / 86400;     int hours = t / 3600;     int minutes = t / 60;     int seconds = t; 

Perhaps it would be better to declare days, hours, minutes and seconds as long to match the same type as t can mutate to.

Inconsistent Variable Naming Conventions

In the function printRemainingTime() the code has the variables t, s, days, hours, minutes, seconds. This is inconsistent. There are some good variable names such as days, hours, minutes and seconds and then there are the variable names t (?time?) and s (?string?). Neither of these variable names are very descriptive. If s is for string, it might be better called formatString and if t is for time perhaps inputTime might be a better name.

Within the main() function there is the variable declaration int Y, M, D, h, m, s;. Perhaps more descriptive names would be year, month, day, hour, minute, second.

Reduce Complexity, Follow SRP

The Single Responsibility Principle states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

Robert C. Martin expresses the principle as follows:

A class should have only one reason to change.

While this is primarily targeted at classes in object oriented languages it applies to functions and subroutines in procedural languages like C as well.

The main function could be broken up into at least 3 functions:

int getInputFromStdin(char outputStringReadFromStdi[])              // return EXIT_SUCCESS or EXIT_FAILURE int getInputFromFile(char inputFileName[], char outputStringReadFromFile[]) // return success  void usage(char programName[]);             // prints the error message in the final else clause. 

The Error Message Isn't Quite Correct

These two error messages don't use the complete filename of time.txt:

            fprintf(stderr, "Could not open time\n"); 

and

                fprintf(stderr, "Could not read time\n"); 

The user could be mislead to add the file time, rather than the file time.txt

 
 
8
 
vote
  • No lo necesita realmente static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 5 para imprimir en static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 6 ; static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 7 hace esto de forma predeterminada y le ahorra un argumento. Aún lo necesita static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 8 para static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 9 , sin embargo.

  • Creo que le faltan static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 0 para algunos de los static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 7655543352 .

  • .
  • Si static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 3 es relacionado con el tiempo, entonces debe declararlo como un 99887776655443354 . Luego, puede lanzarlo a un static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 5 en static void printRemainingTime(time_t t) { const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... "; int days = t / 86400; t -= days * 86400; int hours = t / 3600; t -= hours * 3600; int minutes = t / 60; t -= minutes * 60; int seconds = t; fprintf(stdout, s, days, hours, minutes, seconds); } 6 en su lugar.

  • Esto no es consistente con su otra condición Formateo:

      static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400;     t -= days * 86400;     int hours = t / 3600;     t -= hours * 3600;     int minutes = t / 60;     t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 7  

    debería ser:

      static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400;     t -= days * 86400;     int hours = t / 3600;     t -= hours * 3600;     int minutes = t / 60;     t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 8  

    También hay esto:

      static void printRemainingTime(time_t t) {     const char *s = "%d days, %d hours, %d minutes, %d seconds remaining... ";     int days = t / 86400;     t -= days * 86400;     int hours = t / 3600;     t -= hours * 3600;     int minutes = t / 60;     t -= minutes * 60;     int seconds = t;     fprintf(stdout, s, days, hours, minutes, seconds);    } 9  

    que debe ser:

      long0  
 
  • You don't really need fprintf() for printing to stdout; printf() does this by default and saves you an argument. You do still need fprintf for stderr, though.

  • I think you are missing status = 1; for some of the stderrs in main().

  • If t is time-related, then you should declare it as a time_t. You can then cast it to a long in fscanf instead.

  • This isn't consistent with your other condition formatting:

    if (now >= ref) fprintf(stdout, "It's over!\n"); else printRemainingTime(ref - now); 

    It should be:

    if (now >= ref) {     fprintf(stdout, "It's over!\n") } else {     printRemainingTime(ref - now); } 

    There's also this:

    if (argv[0]) fprintf(stderr, "%s ", argv[0]); 

    which should be:

    if (argv[0]) {     fprintf(stderr, "%s ", argv[0]); } 
 
 
   
   
6
 
vote

Dado que esto aún no se ha mencionado, esta parte es problemática:

  else if (Y >= 2038) {   fprintf(stderr, "Do not plan too far ahead! "); }   

En primer lugar, la codificación dura la fecha requiere que cambie su programa en el futuro.

En segundo lugar, ¿por qué el límite en absoluto? Si es una razón técnica, debe decirle al usuario. Si no, simplemente limita la utilidad de la herramienta.

 

Since this has not been mentioned yet, this part is problematic:

else if (Y >= 2038) {   fprintf(stderr, "Do not plan too far ahead!\n"); } 

Firstly, hard-coding the date requires you to change your program in the future.

Secondly, why the limit at all? If it's a technical reason, you should tell the user. If not, it just limits the usefulness of the tool.

 
 
         
         
3
 
vote
  1. Permitir mktime() Validar rango. La prueba 2038 no es necesaria ya que mktime() informará un error si el año es demasiado grande.

      //} else if (Y >= 2038) { //    fprintf(stderr, "Do not plan too far ahead! "); //} else {     struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 };     time_t ut = mktime(&t);     if (ut < 0) {   
  2. El código supone time_t se mide en segundos con printRemainingTime(time_t t) . time_t es un escalar. Para convertirse portablemente a una diferencia de segundos , use difftime() .

      double difftime(time_t time1, time_t time0);   

    El difftime4 Calcula la diferencia entre dos tiempos de calendario: mktime()0 . C11 ยง 7.27.2.2 3

  3. Otro código asume mktime()1 es un recuento de segundos limitado por mktime()2 gama como mktime()3 99887776655443314 . Como mínimo, el código podría usar mktime()5 o mktime()6 para hacer frente a los sistemas que usan una representación de tiempo más ancha que 99887776655443317. El código altamente portátil usaría mktime()8 , pero la atención adicional es necesario manejar problemas de conversión. Considere que la plataforma que escribe el archivo puede no ser la plataforma que lee el archivo.

  4. El código asume el orden de mktime()9 , que no está especificado por C. podría usar a continuación o Cómo inicializar una estructura de acuerdo con las normas de lenguaje de programación de C

      mktime()0  
  5. mktime()1 Con su mktime()2 en el medio es una elección de separador curioso. La El formato estándar ymdhms es más como mktime()3 todavía es universal bien conocido El código que podría manejar una variedad de formatos de fecha (y con la detección de errores correspondiente) sería deseable.

      mktime()4  
  6. mktime()5 Permite la entrada con texto de arrastre como mktime()6 . Una solución simple es usar mktime()7

      mktime()8  
  7. nit: mktime()9 no es la condición de error especificada. El código altamente portátil usaría una prueba contra //} else if (Y >= 2038) { // fprintf(stderr, "Do not plan too far ahead! "); //} else { struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 }; time_t ut = mktime(&t); if (ut < 0) { 0 .

    Si el tiempo de calendario no se puede representar, la función devuelve el valor //} else if (Y >= 2038) { // fprintf(stderr, "Do not plan too far ahead! "); //} else { struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 }; time_t ut = mktime(&t); if (ut < 0) { 1 . C11 ยง 7.27.2.3 3.

  8. nit: 99887776655443332 puede desbordarse 16 bits //} else if (Y >= 2038) { // fprintf(stderr, "Do not plan too far ahead! "); //} else { struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 }; time_t ut = mktime(&t); if (ut < 0) { 3 , tal vez en el año 3535

 
  1. Let mktime() validate range. The 2038 test is not needed as mktime() will report an error if the year is too great.

    //} else if (Y >= 2038) { //    fprintf(stderr, "Do not plan too far ahead!\n"); //} else {     struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 };     time_t ut = mktime(&t);     if (ut < 0) { 
  2. Code assumes time_t is measured in seconds with printRemainingTime(time_t t). time_t is a scalar. To portably convert to a seconds difference, use difftime().

    double difftime(time_t time1, time_t time0); 

    The difftime function computes the difference between two calendar times: time1 - time0. C11 xc2xa77.27.2.2 3

  3. Other code assumes time_t is a seconds count bounded by long range like long t; ... time_t ref = (time_t) t; and fprintf(f, "%ld", (long) ut);. At a minimum, code could use long long or intmax_t to cope with systems that use a wider than long time representation. Highly portable code would use double, yet extra care is need to handle conversion issues. Consider that the platform that writes the file may not be the platform the reads the file.

  4. Code assumes the order of struct tm, which is not specified by C. Could use below or How to initialize a struct in accordance with C programming language standards

    // struct tm t = { s, m, h, D, M - 1, Y - 1900, -1, -1, -1 }; struct tm t = {0 }; t.tm_year = Y - 1900; ... t.tm_sec = s; t.tm_isdst = -1; 
  5. "%d/%d/%d;%d:%d:%d" with its ; in the middle is a curious separator choice. The standard YMDhms format is more like "2017-04-27T12:44:32" yet that is not universal well known. Code that could handle a variety of date formats (and with corresponding error detection) would be desirable.

     if (sscanf(argv[2], "%d/%d/%d;%d:%d:%d", &Y,&M,&D,&h,&m,&s) != 6) Good();  else if (sscanf(argv[2], "%d-%d-%dT%d:%d:%d", &Y,&M,&D,&h,&m,&s) != 6) Good();  else if (sscanf(argv[2], Other formats, ...) != 6) Good();  else Bad(); 
  6. sscanf(argv[2], "%d/%d/%d;%d:%d:%d", &Y,&M,&D,&h,&m,&s) != 6 allows input with trailing text like "2017/04/27;12:34:56xyz". A simple solution is to use %n

     int n  n = 0;   sscanf(argv[2], "%d/%d/%d;%d:%d:%d %n", &Y,&M,&D,&h,&m,&s,&n);  if (n > 0 && argv[2][n] == '\0') Good(); 
  7. Nit: if (ut < 0) { is not the specified error condition. Highly portable code would use a test against (time_t)(-1).

    If the calendar time cannot be represented, the function returns the value (time_t)(-1). C11 xc2xa77.27.2.3 3.

  8. Nit: int days = t / 86400; can overflow 16-bit int, maybe in the year 3535

 
 

Relacionados problema

4  Salida de una cuenta regresiva en un div  ( Outputting a countdown in a div ) 
Obtuve este código trabajando con el complemento de cuenta regresiva jQuery para tomar una entrada y salida una cadena cuenta regresiva en un div. ¿Hay una ...

8  Conversión de STD :: Chrono :: Time_Point to / from std :: string  ( Converting stdchronotime point to from stdstring ) 
Considere estas funciones que permitan convertir checkOnline.sh4 a / FROM checkOnline.sh5 Con un formato Fecha de fecha ". checkOnline.sh6 con uso:...

10  Obteniendo la última fecha donde ocurrió un día de la semana dado  ( Getting the last date where a given week day occurred ) 
Estoy tratando de aprender un poco sobre la programación funcional y como mi herramienta, elegí F # ya que soy un desarrollador de .NET y el medio ambiente es...

0  Valor numérico para una fecha, DataTado y Datediff  ( Numeric value for a date dateadd and datediff ) 
En MS Excel, una fecha también se representa como un valor numérico, con el 1-enero-1900 como el primer día. También en VBA hay funciones de DataLTD y Datedif...

5  Método de cálculo del día del año  ( Day of year calculation method ) 
El ejercicio que quería resolver es de aquí . Copiando desde esa página: public static int dayOfYear(int month, int dayOfMonth, int year) { if (month...

10  Obteniendo tiempo actual con milisegundos  ( Getting current time with milliseconds ) 
Estoy buscando una forma más eficiente o más corta de lograr la siguiente salida utilizando el siguiente código: timeval curTime; gettimeofday(&curTime, NU...

2  Obtén el primer patrimonio dado por los días de semana y un tiempo de inicio  ( Get first datetime by given weekdays and a starttime ) 
En el trabajo hay un sistema de entrada donde los clientes pueden especificar los días de semana y una hora de inicio para un evento. Los días de semana son e...

6  Compara el último tiempo de modificación con tiempo especificado  ( Compare last modification time with specfied time ) 
Estoy escribiendo una función en Python que compara el tiempo de modificación de un archivo en Linux (usando OS.STAT) con un tiempo específico y compare las f...

5  Calcular el tiempo transcurrido de los tiempos de entrada sin usar declaraciones condicionales  ( Calculate elapsed time from input times without using conditional statements ) 
Acabo de empezar la programación y nos estamos enseñando C ++. Después de nuestra 2ª conferencia, nos dieron una tarea para hacer un programa que tome dos val...

5  Representando el tiempo de apertura y cierre para un negocio  ( Representing the opening and closing time for a business ) 
Tengo una clase de openclose que solo representa las horas de operación de un negocio por la apertura y el tiempo de cierre. Toma los tiempos de apertura y ci...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos