1
votes

Comment ajouter des minutes en C

J'ai une fonction pour ajouter des minutes à une date en C en utilisant struct tm et maketime. la fonction prend la date et l'heure en chaîne et les minutes en entier puis ajoute les minutes à l'heure de la date puis renvoie une chaîne.

input 2018 12 12 04 31
input 2018 11 12 4 61
input 2018 11 12 5 41
atb 201811120541

Voici mon résultat si j'appelle la fonction ci-dessus strcpy (atb30, addMinutes ("201812120431", 30));

char *addMinutes(char *dateTime, int mins)
{
    /* Intput & Output: YYYYMMDDHHMM */
    char year[5];
    char month[3];
    char day[3];
    char HH[3];
    char MM[3];
    char newDateTime[13];
    struct tm t;

    STRMCPY(year,   dateTime,    4);
    STRMCPY(month, &dateTime[4], 2);
    STRMCPY(day,   &dateTime[6], 2);
    STRMCPY(HH,    &dateTime[8], 2);
    STRMCPY(MM,    &dateTime[10],2);

    printf("input %s %s %s %s %s\n",year,month,day,HH,MM);
    t.tm_year = atoi(year);
    t.tm_mon = atoi(month)-1;
    t.tm_mday = atoi(day);
    t.tm_hour = atoi(HH);
    t.tm_min = atoi(MM)+mins;

    printf("input %d %d %d %d %d\n",t.tm_year,t.tm_mon,t.tm_mday,t.tm_hour,t.tm_min);

    mktime(&t);
    printf("input %d %d %d %d %d\n",t.tm_year,t.tm_mon,t.tm_mday,t.tm_hour,t.tm_min);

    sprintf(newDateTime, "%04d%02d%02d%02d%02d", t.tm_year, t.tm_mon,
                            t.tm_mday,t.tm_hour,t.tm_min);

    return newDateTime;
}

Je ne comprends pas pourquoi mon programme ne fonctionne pas. Et quelle est la bonne façon d'écrire une fonction addMinutes en utilisant C.

c

3 commentaires

Vous devriez vérifier l'une des fonctions qui appelle un ptr à un objet tm. Il normalise toutes les valeurs de l'objet tm. C'est le moyen le plus simple de le faire.


tm_year correspond aux "années depuis 1900". Vous devez soustraire 1900 de l'année complète lors de l'écriture et ajouter 1900 lors de la lecture. Notez également que votre fonction renvoie un pointeur vers une valeur dans la pile locale de la fonction. L'utilisation de ce pointeur après le retour de votre fonction n'est pas un comportement défini.


Salut paddy, merci j'ai noté l'avertissement: avertissement: la fonction renvoie l'adresse de la variable locale [-Wreturn-local-addr] return newDateTime; lorsque je compile le programme. Voudrais savoir comment puis-je éviter cela


4 Réponses :


0
votes

Selon tp, le paramètre tm_min ne prend que des entiers de 0 à 59. Pensez à traiter votre entrée avec des instructions if / while pour vous assurer que l'heure et les minutes sont correctement stockées avant d'appeler mktime (& t);


1 commentaires

"le paramètre tm_min ne prend que des entiers de 0 à 59" -> Non. C le point l'exige. Toutes les valeurs int sont valides pour .tm_min avec gmtime () . "... et les valeurs d'origine des autres composants ne sont pas limitées aux plages indiquées ci-dessus." C11 §7.26.2.3 2



2
votes

Ne réinventez pas la roue et acceptez une chaîne que vous devez analyser. Au lieu de cela, prenez un pointeur vers struct tm . De cette façon, "quelqu'un d'autre" peut s'occuper de la gestion des entrées de chaîne.

struct tm *addMinutes(const struct tm *time, int nMin)
{
    time_t equivalent = mktime(time);
    equivalent += (nMin*60);

    return localtime(&equivalent);
}


3 commentaires

Je lis une date et une heure à partir d'un fichier plat, j'ai besoin de la convertir en struct tm type que j'utilise make time pour convertir une chaîne en struct tm la valeur de l'heure semble être modifiée par le programme.


@XiamengLi Considérez strftime ou asctime (regardez-les dans les pages de manuel). La conversion de chaînes de date en nombres entiers est extrêmement compliquée et vous n'avez pas besoin de le faire


équivalent + = (nMin * 60); suppose que time_t est un nombre de secondes. Commun, mais non spécifié par C. Cette hypothèse n'est pas nécessaire, copiez simplement time et ajoutez nMin à son .tm_min , puis appelez mktime () .



1
votes

De nombreux problèmes

Mauvaise époque

Le membre .tm_year date de 1900. @ paddy

// char newDateTime[13];
// sprintf(newDateTime, "%04d%02d%02d%02d%02d", 
//     t.tm_year, t.tm_mon, t.tm_mday,t.tm_hour,t.tm_min);
char newDateTime[13 * 2];
snprintf(newDateTime, sizeof newDateTime, "%04d%02d%02d%02d%02d", 
     t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min);

Vérifier le succès

// struct tm t;
struct tm t = { 0 };

t.tm_isdst = -1; // add
t.tm_year = atoi(year)  - 1900;
t.tm_mon = atoi(month) - 1;
t.tm_mday = atoi(day);
t.tm_hour = atoi(HH);
t.tm_min = atoi(MM) + mins;
if (mktime(&t) == -1) {
  puts("Failed conversion");
  exit(EXIT_FAILURE);
}

Affectation incomplète

Le code OP n'attribue pas les autres membres de t code>, conduisant à un résultat douteux. À la place, attribuez complètement t et utilisez -1 pour .tm_isdst si vous ne connaissez pas le paramètre de lumière du jour pour la date.

// mktime(&t);
if (mktime(&t) == -1) {
  puts("Failed conversion");
  exit(EXIT_FAILURE);
}

Retour d'un pointeur non valide

return newDateTime; tente de renvoyer un pointeur vers un tableau local. Il s'agit d'un comportement indéfini . Le code a besoin d'une nouvelle approche. Recommander de passer dans l'allocation de fonction pour stocker le nouveau newDateTime.

Taille de la mémoire tampon Stingy

char newDateTime [13 ]; est limite suffisante. Que se passe-t-il si l'année dépasse 4 caractères?

// t.tm_year = atoi(year);
t.tm_year = atoi(year) - 1900;

Recherchez également strftime().


1 commentaires

Merci chux j'ai mis à jour mon code en fonction de vos commentaires.



0
votes

Après avoir lu toutes les réponses, j'ai mis à jour mon code ci-dessous.

void addMinutes(char *dateTime, int mins,char *newDateTime)
{
    /* Intput & Output: YYYYMMDDHHMM */
char year[5];
char month[3];
char day[3];
char HH[3];
char MM[3];
struct tm *info;

STRMCPY(year,   dateTime,    4);
STRMCPY(month, &dateTime[4], 2);
STRMCPY(day,   &dateTime[6], 2);
STRMCPY(HH,    &dateTime[8], 2);
STRMCPY(MM,    &dateTime[10],2);

struct tm t = { 0 };
t.tm_isdst = -1;
t.tm_year = atoi(year)-1900;
t.tm_mon = atoi(month)-1;
t.tm_mday = atoi(day);
t.tm_hour = atoi(HH);
t.tm_min = atoi(MM)+mins;
t.tm_sec = 0;

if (mktime(&t) == -1) {
    printf("Failed conversion\n");
    exit(-1);
}
    time_t equivalent = mktime(&t);
    strftime(newDateTime,80,"%Y%m%d%H%M", localtime(&equivalent));  
}


0 commentaires