0

私はこのコードで 3 日間座っていました。問題は、私がどん底に達したことであり、皆さんの助けなしにこれをどのように解決できるかわかりません。タイプchar name、surname、persnbrの配列を持つ構造体があります。

  struct pers
{
    char name[7];
    char last_name[10];
    char id_nbr[12];

};

name surname と persnbr を配列に追加することで問題を解決しましたが、それらを削除する方法がわかりません。

これはqueueEn関数です

 void queueEn(person p1){


    strcpy(queue[last].name, p1.name);
    strcpy(queue[last].last_name, p1.last_name);
    strcpy(queue[last].id_nbr, p1.id_nbr);



}

および queueAdd 関数

 void queueAdd(person person1)
{
    if(last<MAX_SIZE_QUEUE){
        printf("Name: ");
        scanf("%s", person1.name);
        printf("Last name: ");
        scanf("%s", person1.sur_name);
        printf("Id-number: ");
        scanf("%s", person1.id_nbr);
        last++;
    }else {

        printf("Queue is full\n");
    }
    queueEn(person1);
}

このコードはうまく機能します。

今、私は機能を持っていqueueDeますqueueRemove

これは私がこれまでに行ったことです:

 void queueDe(person *personPoint){
    first = (first + 1)% MAX_SIZE_QUEUE;
    *personPoint = queue[first];
    strcpy(personPoint->name, queue[first].name);
    strcpy(personPoint->last_name, queue[first].last_name);
    strcpy(personPoint->id_nbr, queue[first].id_nbr);
}

問題は、配列から情報をコピーする必要があるため、それがあなたのやり方だと思いました。情報はユーザー(キューの最後の人(FIFO構造))に表示されます

ここに関数がありますremove_from_queue

void queueRemove(person personRem){
    if(first < MAX_SIZE_QUEUE){

    printf("Name: %s", personRem.name);
    printf("Last Name: %s", personRem.last_name);
    printf("Id-Number: %s", personRem.id_nbr);
    first++;
    }else{
        printf("Queue is empty");
    }
    queueDe(&personRem);
}

変数 first と last は、配列の末尾と配列の先頭に相当します。配列の最後の人物を削除するには、最初に人物を削除する必要があります。どちらの変数も最初は 0 に初期化されています。ポインター *personPoint を malloc に初期化する必要があることを読みましたが、この特定の状況でそれを使用する方法がわかりません。

プログラムを実行して人を削除したい場合、何も起こりません。

答えてくれてありがとう。

4

1 に答える 1

1

循環キューは合理的なデータ構造ですが、キューが「空」でキューが「満杯」の状態を明確に把握する必要があります。最初に、first、last、および queue[] 配列要素を保持する循環キュー構造体を定義します。

typedef struct circular_array_queue_s
{
    person* queue[MAX_SIZE_QUEUE];
    int first;
    int last;
} CirQueue;
CirQueue cirq;

これで、キューが空か満杯かを報告し、要素数のカウントを報告する関数を定義できます。

int queueEmpty()
{
    if( cirq.first == cirq.last ) //queue empty
    {
        printf("Queue is empty");
        return 1;
    }
    return 0;
}
int queueFull()
{
    if( ((cirq.last+1%MAX_SIZE_QUEUE)) == cirq.first ) //queue full
    {
        printf("Queue is full\n");
        return 1;
    }
    return 0;
}
int queueCount()
{
    int count=0;
    if( cirq.first<=cirq.last )
        count=(cirq.last-cirq.first);
    else //if ( cirq.first>cirq.last )
        count=(cirq.last+MAX_SIZE_QUEUE)-cirq.first;
    return count;
}

キューの最後の位置でエンキューし、キューの最初の位置からデキューするため、エンキューとデキューのキュー操作が簡素化されます。循環キューがあるため、最初と最後のインデックスの移動は、1 ずつインクリメントし、最後にラップすることによって行われます (モジュラス MAX_SIZE_QUEUE を使用)。

person*
queueEn(person* p)
{
    //err
    if( queueFull() ) { return NULL; } //queue full, fail
    cirq.queue[cirq.last] = p;
    cirq.last = (cirq.last+1)%MAX_SIZE_QUEUE; //one
    return p;
}
person*
queueDe()
{
    person* p;
    //err
    if( queueEmpty() ) { return NULL; } //queue empty, fail
    p = cirq.queue[cirq.first];
    cirq.queue[cirq.first] = NULL;
    cirq.first = (cirq.first+1)%MAX_SIZE_QUEUE;
    return p;
}

全体のウォーキング (反復) は、次のような関数を使用して実行できます。

person*
queueIterate()
{
    person* p;
    int iter;
    if( queueEmpty() ) { return NULL; } //queue empty, skip
    for( iter=cirq.first; iter!=cirq.last; iter=(++iter)%MAX_SIZE_QUEUE )
    {
        personPrint(p = cirq.queue[iter]);
    }
    return p;
}

要素をキューに追加するには、追加する要素を作成し (malloc)、要素を削除するときに要素を適切に破棄する (無料) 必要があります。

void queueAdd(person person1)
{
    if( queueFull() ) { return; } //queue full, cannot add
    personRead(&person1);
    person* p;
    queueEn(personCopy(p=personNew(),&person1));
}
person*
queueRemove(person* personRem)
{
    person* p;
    if(p = queueDe())
    {
        if(personRem) {
            personCopy(personRem,p); personDel(p);
        }
        //if you don't give a personRem, you must free person p removed from queue
        else
            personRem=p;
    }
    return personRem;
}

これらのキュー機能をテストしたい場合、

int
main()
{
    person per;
    person* perp;
    int done=0;
    while(!done)
    {
        queueAdd(per);
        if( queueFull() ) done=1;
        if( queueCount() >= 3 ) done=1; //just do three
    }
    queueIterate();
    while(!queueEmpty())
    {
        personPrint(perp=queueRemove(&per));
    }
}

C 文字列は null で終了することを理解してください。そのため、N+1 イディオムを使用して char[] を宣言すると、使用可能な文字列サイズが明確に伝達されます。

typedef struct person_s
{
    char name[9+1];         //size to N+1, makes clear the space, "Alexander"(9)
    char last_name[10+1];   //room for null-terminator
    char id_nbr[12+1];      //you really want to room for null-terminator
} person;

メンバー アクセスをカプセル化する関数を使用すると、コードが読みやすくなり、DRY (Dont Repeat Yourself) アプローチがサポートされ、どこでも公開して処理したくない詳細を非表示にできることがわかります。

person*
personNew()
{
    person* pnew;
    if( !(pnew=malloc(sizeof(person))) ) return NULL;
    strncpy(pnew->name, ">name", sizeof(pnew->name));
    strncpy(pnew->last_name, ">last_name", sizeof(pnew->last_name));
    strncpy(pnew->id_nbr, ">id_nbr", sizeof(pnew->id_nbr));
    return(pnew);
}
void personDel(person* p)
{
    if( !p ) return; //fail, must have valid pointer
    free(p);
    return;
}
person*
personCopy(person* pd, person* ps)
{
    if(!pd || !ps) return;
    strncpy(pd->name, ps->name, sizeof(pd->name));
    strncpy(pd->last_name, ps->last_name, sizeof(pd->last_name));
    strncpy(pd->id_nbr, ps->id_nbr, sizeof(pd->id_nbr));
    return(pd);
}

メンバー値を設定する関数 (セッターまたはミューテーターと呼ばれることが多い) は次のとおりです。

person*
personName(person* p1, char* name)
{
    if(!p1 || !name) return p1;
    strncpy(p1->name, name, sizeof(p1->name));
    return(p1);
}
person*
personLastName(person* p1, char* last_name)
{
    if(!p1 || !last_name) return p1;
    strncpy(p1->last_name, last_name, sizeof(p1->last_name));
    return(p1);
}
person*
personIdNbr(person* p1, char* id_nbr)
{
    if(!p1 || !id_nbr) return p1;
    strncpy(p1->id_nbr, id_nbr, sizeof(p1->id_nbr));
    return(p1);
}

そしてここにあなたの人の構造体を読んで印刷する関数があります、

person*
personRead(person* personp) //two
{
    if(!personp) return personp;
    //you really should allow for more space here
    char name[99+1];
    char last_name[99+1];
    char id_nbr[99+1];
    printf("Name: ");        scanf("%s", name);
    printf("Last name: ");        scanf("%s", last_name);
    printf("Id-number: ");        scanf("%s", id_nbr);
    personName(personp,name);
    personLastName(personp,last_name);
    personIdNbr(personp,id_nbr);
    return(personp);
}
void personPrint(person* personp) //five
{
    if(!personp) return personp;
    printf("Name: %s,", personp->name);
    printf("Last Name: %s,", personp->last_name);
    printf("Id-Number: %s\n", personp->id_nbr);
}

全体を通してmalloc/free と person (person 構造体へのポインタ) を使用したことに注意してください。C でプログラミングする場合は、ポインターについて学習する必要があります。*

于 2013-11-13T03:07:04.463 に答える