在 C++ 中自动生成 ID

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10124609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:38:54  来源:igfitidea点击:

Auto generate ID in C++

c++auto-generate

提问by sahapersian

// AnE.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
using namespace std;


// The maximum number of patients in queue
#define MAXPATIENTS 30


// define structure for patient information
struct patient

{
   char FirstName[50];
   char LastName[50];
   char ID[20];
};


// define class for queue
class queue
{
   public:
   queue (void);
   int RegisterPatien (patient p);
   int RegisterPatientAtBeginning (patient p);
   patient GetNextPatient (void);
   int CancelAll (patient * p);
   void OutputList (void);
   char DepartmentName[50];
   private:
   int ShowAllPatient;
   patient List[MAXPATIENTS];
};


// declare member functions for queue

queue::queue ()
{
   // Constructor
   ShowAllPatient = 0;
}


int queue::RegisterPatien (patient p)
{
   // To add a patient (normally) to the queue (to the end).
   // returns 1 if successful, 0 if queue is full.
  if (ShowAllPatient >= MAXPATIENTS)
   {
      // queue is full
      return 0;
   }
      // put in new patient
      else
      List[ShowAllPatient] = p;  ShowAllPatient++;
      return 1;
}


int queue::RegisterPatientAtBeginning (patient p)
{
   // adds a critically ill patient to the beginning of the queue.
   // returns 1 if successful, 0 if queue is full.
   int i;
   if (ShowAllPatient >= MAXPATIENTS)
   {
      // queue is full
      return 0;
   }

   // move all patients one position back in queue
   for (i = ShowAllPatient-1; i >= 0; i--)
   {
      List[i+1] = List[i];
   }
   // put in new patient
   List[0] = p;  ShowAllPatient++;
   return 1;
}


patient queue::GetNextPatient (void)
{
   // gets the patient that is first in the queue.
   // returns patient with no ID if queue is empty

   int i;  patient p;
   if (ShowAllPatient == 0) {
   // queue is empty
   strcpy(p.ID,"");
   return p;}
   // get first patient
   p = List[0];
   // move all remaining patients one position forward in queue
   ShowAllPatient--;
   for (i=0; i<ShowAllPatient; i++)
   {
      List[i] = List[i+1];
   }
   // return patient
   return p;
}


int queue::CancelAll (patient * p)

{
   // removes a patient from queue.
   // returns 1 if successful, 0 if patient not found
   int i, j, found = 0;
   // search for patient
   for (i=0; i<ShowAllPatient; i++)
    {
            if (stricmp(List[i].ID, p->ID) == 0)
        {
        // patient found in queue
        *p = List[i];  found = 1;
        // move all following patients one position forward in queue
        ShowAllPatient--;

    for (j=i; j<ShowAllPatient; j++)
                {
                        List[j] = List[j+1];
                }
        }
    }
   return found;
}


void queue::OutputList (void)
{
   // lists entire queue on screen
   int i;
   if (ShowAllPatient == 0)
    {
            cout<< "Queue is empty";
    }
   else
    {

        for (i=0; i<ShowAllPatient; i++)
        {
            cout << "First Name : " << List[i].FirstName<<endl;
            cout << "Last Name : " << List[i].LastName<<endl;
        }
    }
}


// declare functions used by main:

patient InputPatient (void)

{
   // this function asks user for patient data.
   patient p;
   cout<<endl<<endl;
   cout << "Please enter the information of the Patient"<<endl<<endl;
   cout << "First name: "<<endl<<endl;
   cin.getline(p.FirstName, sizeof(p.FirstName));
   cout << "Last name: "<<endl<<endl;
   cin.getline(p.LastName, sizeof(p.LastName));
   // check if data valid
   if (p.FirstName[0]==0 || p.LastName[0]==0 || p.ID[0]==0)
    {
            // rejected
            strcpy(p.ID,"");
            cout << "Error: Data not valid. Operation cancelled.";
            getch();
    }
   return p;
}


void OutputPatient (patient * p)
{
   // this function outputs patient data to the screen
   if (p == NULL || p->ID[0]==0)
    {
            cout << "No patient";

    return;
    }
   else
   cout << "Patient Information:"<<endl<<endl;
   cout << "First name: " << p->FirstName<<endl<<endl;
   cout << "Last name: " << p->LastName<<endl<<endl;
}


int ReadNumber()
{
   // this function reads an integer number from the keyboard.
   // it is used because input with cin >> doesn't work properly!
   char buffer[20];
   cin.getline(buffer, sizeof(buffer));
   return atoi(buffer);
}


void DepartmentMenu (queue * q)
{
   // this function defines the user interface with menu for one department
   int choice = 0, success;  patient p;
   while (choice != 6)
    {
        // print menu
           system("CLS");
           cout << "<< || Welcome || >> "<<endl << q->DepartmentName<<endl;
           cout << "Please enter your choice:"<<endl<<endl;
           cout << "1:  Register patient"<<endl;
           cout << "2:  Serve patient "<<endl;
           cout << "3:  Cancel all patients from queue"<<endl;
           cout << "4:  Show all patient"<<endl;
           cout << "5:  Exit"<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl;

           choice = ReadNumber();

        switch (choice)
      {
            case 1:   // Add new patient
        p = InputPatient();
        if (p.ID[0])
           {
                success = q->RegisterPatien(p);
                system("CLS");
                if (success)
                {
                    cout << "Patient added:"<<endl<<endl;

                }
            else
           {
                // error
                cout << "Sorry: The queue is full. We Cannot add any patient:";
           }
                OutputPatient(&p);
                cout << "Press any key";
                getch();
      }
     break;

      case 2:   // Call patient for operation /First Come First Surve
     p = q->GetNextPatient();
     system("CLS");
     if (p.ID[0])
        {
           cout << "Patient to operate:";
           OutputPatient(&p);
     }
     else
        {
           cout << "Currently there is no patient to operate.";
     }
           cout << "Press any key to contiune";
           getch();
           break;

      case 3:   // Cancel all from queue
     p = InputPatient();
     if (p.ID[0])
       {
            success = q->CancelAll(&p);
            system("CLS");          
            if (success)
              {
                cout << "Patient removed:";
              }
              else
              {
                // error
                cout << "Sort: We cannot find patient:";
              }
        OutputPatient(&p);
            cout << "Press any key to contiune";
            getch();
       }
     break;

      case 4:   // Show all patient -> queues
          system("CLS");
          q->OutputList();
     cout << "Press any key";
     getch();  break;
     }
      }
}


// the main function defining queues and main menu
void main ()
{
   int i, MenuChoice = 0;
   // define  queue
   queue department[1];
   // set department name
   strcpy_s (department[0].DepartmentName, "To Emergency Department");

   while (MenuChoice != 2)
    {
        system("CLS");

// Cout menu
           cout<<"\n------------------------------------\n";
           cout << "Welcome to Waiting Room Management System"<<endl;
           cout<<"---------------------------------------\n";
           cout << "Please Select a Number from the following menu:"<<endl<<endl;
          for (i = 0; i < 1; i++)

    {
           // write menu item for department i
           cout<< "" << (i+1) << ":  "<< department[i].DepartmentName;
           cout<<endl;
          }
          cout << "2:  Exit"<<endl;
          // get user choice
          MenuChoice = ReadNumber();
          // is it a department name?
            if (MenuChoice >= 1 && MenuChoice <= 1)
            {
            // call submenu for department
            // (using pointer arithmetics here:)
            DepartmentMenu (department + (MenuChoice-1));
            }
    }
}

Okay, it's Vc++ for waiting room. You can see the code is working well, but I have problem with generating ID! I need to generate ID for each patient (auto-generate by system). How I can generate ID for my queue? Thanks alot !

好吧,这是等候室的Vc++。您可以看到代码运行良好,但我在生成 ID 时遇到问题!我需要为每个患者生成 ID(由系统自动生成)。如何为我的队列生成 ID?非常感谢 !

回答by Jerry Coffin

Usually, you'd do it by putting a staticvariable in that class, and each time you get a new patient, you assign its current value to the current patient, then increment it.

通常,您会通过static在该类中放置一个变量来实现,每次获得新患者时,您将其当前值分配给当前患者,然后将其递增。

class patient { 
    // ...
    int id;

    static int current_id; // added

    patient() : id(current_id++) {} // added
};

int patient::current_id; // added

回答by maniak

You can use a static variable when you create a patient (if you want it there) that increment itself in the constructor, or a variable in you're queue that increment when you add a patient (if you want to only assign an ID when in the queue).

您可以在创建患者时使用静态变量(如果您想要它)在构造函数中增加自身,或者在您排队时使用一个变量,当您添加患者时增加该变量(如果您只想在在队列中)。

But in your case, I think you want the first solution (static variable in the constructor).

但是在您的情况下,我认为您需要第一个解决方案(构造函数中的静态变量)。

回答by mvanlint

I had the same need for an SQL-database and ended up with this...

我对 SQL 数据库有同样的需求,最终得到了这个......

Warning: Mostly an example of bad programming with mixing C and C++ (still need to convert old code), but it was meant to convey the idea. I am sure better solutions exist...

警告:主要是混合 C 和 C++ 的不良编程示例(仍然需要转换旧代码),但它旨在传达这个想法。我确信存在更好的解决方案......

It generates (unfortunately) large character based ID's, based on current date and time. This means that every next auto-generated ID needs to be bigger: if it is equal or smaller, a millisecond timer is appended and the code will wait until the ID has become unique. It works without the milliseconds as well, but this will lead to long delays if you need to generate many ID's at once (a second for each pause). If desired, it will also add an optional postfix (can help omit the milliseconds).

它根据当前日期和时间生成(不幸的是)基于大字符的 ID。这意味着每个下一个自动生成的 ID 都需要更大:如果它等于或更小,则附加一个毫秒计时器,代码将等待直到 ID 变得唯一。它也可以在没有毫秒的情况下工作,但是如果您需要一次生成许多 ID(每次暂停一秒),这将导致长时间的延迟。如果需要,它还将添加一个可选的后缀(可以帮助省略毫秒)。

My experience with simple counters is, that they might duplicate under certain circumstances, which had me look for an alternative.

我对简单计数器的经验是,它们在某些情况下可能会重复,这让我寻找替代方案。

Careful: Another user on another computer might generate equal ID's... (same second or millisecond)

小心:另一台计算机上的另一个用户可能会生成相同的 ID...(同一秒或毫秒)

TUID::TUID()

{
 *LastID = 0; // char [80] - Global within object
}    


void TUID::GetToday (int *d, int *m, int *y)

{
  time_t now;
  struct tm *ltm;

  time (&now);
  ltm = localtime (&now);

  *y = ltm->tm_year + 1900;
  *m = ltm->tm_mon + 1;
  *d = ltm->tm_mday;
}


void GetTime (int *h, int *m, int *s)

{
time_t t = time(0);   // get time now
struct tm * now = localtime( & t );

*h = now->tm_hour;
*m = now->tm_min;
*s = now->tm_sec;
}


const char *TUID::NewUID (bool bPreviousAttemptFailed, const char *_postfix)

{
  int d, m, y,
      _h, _m, _s;
  bool bSameAsLastUID;
  char _uid [80];

  GetToday (&d, &m, &y);

  do
    {
      GetTime (&_h, &_m, &_s);
      sprintf (_uid, "%04d%02d%02d_%02d%02d%02d%s", y, m, d, _h, _m, _s, _postfix);
      bSameAsLastUID = (strcmp (_uid, LastUID) <= 0);
      if (bPreviousAttemptFailed || bSameAsLastUID)
        sprintf (_uid + strlen (_uid), "_%d", 
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count());
    }
  while (strcmp (_uid, LastUID) <= 0);

  strcpy (LastUID, _uid);

  return LastUID;
}

This results in ID's like this:

这导致 ID 是这样的:

20170816_115904 (no post-fix)
20170816_115904i (with post-fix keeping id unique, preventing milliseconds)
20170816_115904i_6427264 (auto-added milliseconds to keep ID unique)
20170816_115904i_6427265
20170816_115904i_6427266

回答by Luchian Grigore

If you want unique ids, you can generate a GUIDs. For VC++, you can use:

如果你想要唯一的 id,你可以生成一个 GUID。对于 VC++,您可以使用:

extern C
{
   #include <Rpc.h>
}

//...
UUID id;
UuidCreate ( &id );