Question

Je voulais un chiffre qui restera unique pour une journée (24 heures). Voici le code que je suis venu avec; Je me demandais au sujet de ses risques possibles / Illusion; « Je crois » ce qui garantit un 12 chiffres numéro unique pour un jour atleast.

La logique est d'obtenir la date / heure (hhmmssmmm) et concaténer les quatre premiers octets de résultat du compteur de performances des requêtes.

__forceinline bool GetUniqueID(char caUID[MAX_STRING_LENGTH])
{
    //Logic: Add HHMMSSmmm with mid 3 bytes of performance counter.
    //Guarantees that in a single milli second band (0 to 999) the three bytes 
    //of performance counter would always be unique.
    //1. Get system time, and use
    bool bStatus = false;
    try
    {

        SYSTEMTIME localtime;
        GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm

        LARGE_INTEGER li;
        char cNT[MAX_STRING_LENGTH];//new time.
        memset(cNT, '\0', sizeof(cNT));
        try
        {
            //Try to get the performance counter,
            //if one is provided by the OEM.

            QueryPerformanceCounter(&li);//This function retrieves the current value of the 
                                         //high-resolution performance counter if one is provided by the OEM
                                         //We use the first four bytes only of it.
            sprintf(cNT, "%u", li.QuadPart);
        }
        catch(...)
        {
            //Not provided by OEM.
            //Lets go with the GetTickCounts();
            //ddHHMMSS + 4 bytes of dwTicks
            sprintf(cNT,"%04d", GetTickCount());
        }


        //Get the first four bytes.
        int iSkipTo     = 0;//This is incase we'd decide to pull out next four bytes, rather than first four bytes.
        int iGetChars   = 4;//Number of chars to get.
        char *pSub = (char*) malloc(iGetChars+1);//Clear memory
        strncpy(pSub, cNT + iSkipTo, iGetChars);//Get string
        pSub[iGetChars] = '\0'; //Mark end.

        //Prepare unique id
        sprintf(caUID, "%02d%02d%02d%3d%s", 
                                    localtime.wHour, 
                                    localtime.wMinute, 
                                    localtime.wSecond, 
                                    localtime.wMilliseconds, 
                                    pSub); //First four characters concat.

        bStatus = true;
    }
    catch(...)
    {
        //Couldnt prepare. There was some problem.
        bStatus = false;
    }

    return bStatus;
}

Après la sortie est que je reçois:

Unique: [125907 462224] Unique: [125907 462225] Unique: [125907 462226] Unique: [125907 462227] Unique: [125907 462228] Unique: [125907 462230] Unique: [125907 462231] Unique: [125907 462232] Unique: [125907 462233] Unique: [125907 462234] Unique: [125907 462235] Unique: [125907 462237] Unique: [125907 462238] Unique: [125907 462239] Unique: [125907 462240] Unique: [125907 462241] Unique: [125907 462243] Unique: [125907 462244] Unique: [125907 462245] Unique: [125907 462246] Unique: [125907 462247] Unique: [125907 462248] Unique: [125907 462249] Unique: [125907 462251] Unique: [125907 462252] Unique: [125907 462253] Unique: [125907 462254] Unique: [125907 462255] Unique: [125907 462256] Unique: [125907 462257] Unique: [125907 462258] Milliseconde a changé, 46 Unique: [125907 622261] Unique: [125907 622262] Unique: [125907 622263] Unique: [125907 622264] Unique: [125907 622265] Unique: [125907 622267] Unique: [125907 622268] Unique: [125907 622269] Unique: [125907 622270] Unique: [125907 622271] Unique: [125907 622273] Unique: [125907 622274] Unique: [125907 622275] Unique: [125907 622276] Unique: [125907 622277] Unique: [125907 622278] Unique: [125907 622279] Unique: [125907 622281] Unique: [125907 622282] Unique: [125907 622283] Unique: [125907 622284] Unique: [125907 622285] Unique: [125907 622286] Unique: [125907 622288] Unique: [125907 622289] Unique: [125907 622290] Unique: [125907 622291] Unique: [125907 622292] Unique: [125907 622293] Unique: [125907 622295] Unique: [125907 622296] Unique: [125907 622297] Unique: [125907 622298] Unique: [125907 622299] Unique: [125907 622300] Unique: [125907 622301] Unique: [125907 622302] Unique: [125907 622304] Unique: [125907 622305] Unique: [125907 622306] Milliseconde a changé, 62 Unique: [125907 782308] Unique: [125907 782310] Unique: [125907 782311] Unique: [125907 782312] Unique: [125907 782313] Unique: [125907 782314] Unique: [125907 782316] Unique: [125907 782317] Unique: [125907 782318] Unique: [125907 782319] Milliseconde a changé, 125 Unique: [1259071402495] Unique: [1259071402497] Unique: [1259071402498] Unique: [1259071402499] Unique: [1259071402500] Unique: [1259071402502] Unique: [1259071402503] Unique: [1259071402504] Unique: [1259071402505] Unique: [1259071402507]

Maintenant, je pense à garder les ID générés dans une liste, et comparer le nouveau produit une avec ceux qui existent déjà dans la liste. Si elle existe déjà dans la liste, puis bien je peux certainement sauter le nombre et générer un autre, mais certainement et clairement cette logique échoueraient.

apprécierait vos commentaires / suggestions / mises à jour / etc.

Merci JT.

Était-ce utile?

La solution

Ma solution était d'obtenir le temps de système et ajouter un compteur à ce (pseudo-code):

static int counter = 0;
static Time lastTime;

String getNextId() {
    Time now = System.getTime();
    if (lastTime == now)
        counter ++;
    else
        counter = 0;
    return now+counter;
}

Cela garantirait que j'obtenir un nouvel identifiant, même quand j'ai appelé la méthode le plus souvent que des changements de getTime().

Autres conseils

La logique semble sonner à moi si vous l'exécuter à partir d'une machine sur un processeur single-core. Je ne sais pas si le même pour un processeur multi-core pour les appels successifs, cependant. Les nombres générés ne sera certainement pas cependant uniques à travers des machines,.

Par curiosité, est-il une raison que vous ne l'utilisez GUIDs?

Ou puisque vous envisagez de garder les ID générés dans une liste pour comparer, pourquoi ne pas pouvez-vous créer un générateur? Puisque vous proposez le stockage est une option, si vous enregistrez le dernier numéro utilisé et l'incrémenter chaque utilisation ... Vous pouvez même stocker une date et remettre le compteur tous les jours si vous le souhaitez.

J'ai eu des problèmes avec des temps dans les boucles rapides où ils n'ont pas changé malgré qu'il soit le bon sens qu'ils devraient (vous avez aucun contrôle sur le système d'exploitation de sorte que vous ne pouvez pas supposer que le temps change tous les x millisecondes etc.)

Ajout de la valeur du compteur en tant que quelques chiffres supplémentaires (non comme un incrément) et la réinitialisation sur le redémarrage ou après 9999 devrait cacher assez pour faire tout cela, mais impossible de se produire (derniers mots célèbres).

format est alors TTTTTToooo où T est la figure de votre temps et o 4 chiffres du décalage.

Aaron: Merci pour vos commentaires, j'ai utilisé votre approche pour obtenir ce que je voulais.

__forceinline bool GetUniqueIDEx(char caUID[MAX_STRING_LENGTH])
{
    //Logic: Add HHMMSSmmm with 3 bytes counter.
    //Guarantees a unique number for a calendar date, 
    //that in a single milli second band (0 to 999) the three bytes 
    //of counter would always be unique.
    //1. Get system time, and use

    bool bStatus = false;
    try
    {
        GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm

        char cNT[MAX_STRING_LENGTH];//new time.
        memset(cNT, '\0', sizeof(cNT));
        if(m_nCounter> MAX_COUNTER_LIMIT)
        {
            m_nCounter= 0;
        }

        sprintf(cNT, "%03d", ++m_nCounter);

        //Prepare unique id
        sprintf(caUID, "%02d%02d%02d%03d%s", 
                                            localtime.wHour, 
                                            localtime.wMinute, 
                                            localtime.wSecond, 
                                            localtime.wMilliseconds, 
                                            cNT); 

        bStatus = true;
    }
    catch(...)
    {
        //Couldnt prepare. There was some problem.
        bStatus = false;
    }

    return bStatus;
}

J'utiliserais secondes depuis minuit puis un compteur. Cela vous donne jusqu'à dix millions de visites par seconde. Devrait être assez unique. En utilisant le code d'Aaron ci-dessus, vous formatez la chaîne comme:

sprintf(idstr, "%05d%07d", secs_since_midnight, counter);

Bien sûr, je suis aussi un croyant ferme à l'aide de la base-36 (via itoa) lorsque vous voulez vraiment entasser un compteur en quelques caractères imprimables (jour et de l'année plutôt que mois / jour, etc.)

Je ne suis pas sûr que votre processus peut sacrifier petit problème de performance et de garder la logique simple.

Nous pouvons vous garantir numéro unique avec le format HHMMSSmmm lui-même si vous mettez votre processus de dormir pendant 1 milliseconde entre deux appels. De cette manière, vous pouvez éliminer la partie de concaténation et aussi la liste que vous devez maintenir doubler vérifier l'unicité.

Manikanthan Velayutham // programmés pour penser BIG

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top