C 使用链表建模教室线

C 使用链表建模教室线,c,data-structures,linked-list,C,Data Structures,Linked List,我想用我的程序模拟一个简单的教室线 函数first:将学生x放在队列前面 功能out:从行中删除学生x 函数backToClassroom:在行中打印学生 函数反转:反转学生在行中的顺序 功能place:学生x在他/她身后为学生y占据一个位置,如果学生y想加入队伍,他/她应该在x后面 函数add:将学生x添加到行的末尾,除非学生为他/她自己安排了位置 我的问题是: 我不知道如何正确编码函数添加和放置,正如我在顶部解释的那样 #包括 #包括 #包括 结构线{ 字符名[100]; 结构行*ne

我想用我的程序模拟一个简单的教室线

  • 函数
    first
    :将学生x放在队列前面

  • 功能
    out
    :从行中删除学生x

  • 函数
    backToClassroom
    :在行中打印学生

  • 函数<代码>反转:反转学生在行中的顺序

  • 功能
    place
    :学生x在他/她身后为学生y占据一个位置,如果学生y想加入队伍,他/她应该在x后面

  • 函数
    add
    :将学生x添加到行的末尾,除非学生为他/她自己安排了位置

我的问题是:

我不知道如何正确编码函数
添加
放置
,正如我在顶部解释的那样


#包括
#包括
#包括
结构线{
字符名[100];
结构行*nextPtr;
};
typedef结构行;
类型定义行*LinePtr;
void add(LinePtr*lPtr,字符数组[100]);
作废(LinePtr*lPtr,字符数组[100]);
int isEmpty(LinePtr lPtr);
无效返回教室(LinePtr currentPtr);
void first(LinePtr*lPtr,char数组[100]);
无效位置(LinePtr-previousPtr,字符数组[100]);
静态无效反转(LinePtr*lPtr);
int main(int argc,char*argv[]){
字符顺序[25];
LinePtr startPtr=NULL;
字符tempName1[100];
字符tempName2[100];
获取(订单);
while(strcmp(订单,“返回教室”)!=0){
如果(strcmp(订单,“添加”)==0){
scanf(“%s”,tempName1);
添加(&startPtr,tempName1);
}
如果(strcmp(订单,“输出”)==0){
scanf(“%s”,tempName1);
out(和startPtr,临时名称1);
}
if(strcmp(顺序,“第一”)==0){
scanf(“%s”,tempName1);
第一个(&startPtr,tempName1);
}
if(strcmp(订单,“地点”)==0){
scanf(“%s”,tempName1);
scanf(“%s”,tempName2);
地点(startPtr,临时名称2);
}
如果(strcmp(顺序,“反向”)==0){
反向(&startPtr);
}
获取(订单);
}
if(strcmp(订单,“返回教室”)==0){
返回教室(startPtr);
}
返回0;
}
int isEmpty(LinePtr lPtr){
返回(lPtr==NULL);
}
返回教室无效(LinePtr currentPtr){
如果(isEmpty(currentPtr)){
printf(“行为空。\n”);
}
否则{
while(currentPtr!=NULL){
printf(“%s\n”,currentPtr->name);
currentPtr=currentPtr->nextPtr;
}
}
}
静态无效反转(LinePtr*lPtr){
LinePtr-previousPtr=NULL;
LinePtr currentPtr=*lPtr;
行PTR后PTR;
while(currentPtr!=NULL){
afterPtr=当前PTR->nextPtr;
当前PTR->nextPtr=上一个PTR;
先前的PTR=当前的PTR;
当前PTR=后PTR;
}
*lPtr=先前的PTR;
}
作废(LinePtr*lPtr,字符数组[100]){
LinePtr-temptr;
if(strcmp(数组,(*lPtr)->name)==0){
temptr=*lPtr;
*lPtr=(*lPtr)->NEXTPTTR;
免费(tempPtr);
}
否则{
LinePtr-previousPtr=*lPtr;
LinePtr currentPtr=(*lPtr)->nextPtr;
而((currentPtr!=NULL)&((strcmp(currentPtr->name,array))!=0)){
先前的PTR=当前的PTR;
currentPtr=currentPtr->nextPtr;
}
如果(currentPtr!=NULL){
temptr=当前ptr;
上一个PTR->nextPtr=当前PTR->nextPtr;
免费(tempPtr);
}
}
}
void first(LinePtr*lPtr,字符数组[100]){
LinePtr newPtr=malloc(sizeof(Line));
strcpy(newPtr->name,array);
newPtr->nextPtr=(*lPtr);
(*lPtr)=新PTR;
}
无效位置(LinePtr-previousPtr,字符数组[100]){
如果(previousPtr==NULL){
printf(“给定的前一个节点不能为空”);
返回;
}  
LinePtr newPtr=(LinePtr)malloc(sizeof(Line));
strcpy(newPtr->name,array);
newPtr->nextPtr=previousPtr->nextPtr;
上一个PTR->下一个PTR=newPtr;
}
void add(LinePtr*lPtr,字符数组[100]){
LinePtr newPtr=malloc(sizeof(Line));
LinePtr lastPtr=*lPtr;
strcpy(newPtr->name,array);
newPtr->nextPtr=NULL;
如果(*lPtr==NULL){
*lPtr=newPtr;
返回;
}  
while(lastpr->nextPtr!=NULL){
lastPtr=lastPtr->nextPtr;
}
lastpr->nextPtr=newPtr;
}

我想你所需要的就是:

void place(LinePtr previousPtr, char array[100]) 
{
    return add (previousPtr, array);
}

// If lPtr == null then this is an insertion at the end of the list
// If lPtr != null then this is an insertion into the list after lPtr.
void add(LinePtr *lPtr, char array[100]) 
{
    LinePtr newPtr = malloc(sizeof(Line));
    strcpy(newPtr->name, array);
    newPtr->nextPtr = NULL;

    LinePtr lastPtr = *lPtr;
    if(*lPtr == NULL) 
    {
       *lPtr = newPtr;
       return;
    }  
    while(lastPtr->nextPtr != NULL) {
        lastPtr = lastPtr->nextPtr;
    }
    lastPtr->nextPtr = newPtr;
}

您的add函数已经执行了add或insert操作

place函数必须知道旧节点。您可以提供新名称和旧名称

//place before the other name
void place(LinePtr *list, char *newName, char *otherName)
{
    if(list == NULL)
    {
        printf("the given previous node cannot be NULL");
        return;
    }

    Line *walk = *list;
    Line *prev = NULL;
    while(walk)
    {
        if(strcmp(walk->name, otherName) == 0)
        {
            //found
            LinePtr newPtr = (LinePtr)malloc(sizeof(Line));
            strcpy(newPtr->name, newName);
            newPtr->nextPtr = walk;
            if(prev)
                prev->nextPtr = newPtr;
            else
                *list = newPtr;
            break;
        }
        prev = walk;
        walk = walk->nextPtr;
    }
}

void place_after_otherName(LinePtr *list, char *newName, char *otherName)
{
    if(list == NULL)
    {
        printf("the given previous node cannot be NULL");
        return;
    }

    Line *walk = *list;
    while(walk)
    {
        if(strcmp(walk->name, otherName) == 0)
        {
            //found
            LinePtr newPtr = (LinePtr)malloc(sizeof(Line));
            strcpy(newPtr->name, newName);
            newPtr->nextPtr = walk->nextPtr;
            walk->nextPtr = newPtr;
            break;
        }
        walk = walk->nextPtr;
    }
}
add
功能按预期工作。例如:

int main(void) 
{
    LinePtr startPtr = NULL;
    add(&startPtr, "x");
    add(&startPtr, "y");
    add(&startPtr, "z");

    place(&startPtr, "A", "z");
    place_after_otherName(&startPtr, "B", "z");

    LinePtr p = startPtr;
    while(p)
    {
        printf(p->name);
        p = p->nextPtr;
    }

    printf("\n");
    return 0;
}

John,您的代码非常笨拙,
place
out
命令不能按预期工作,
out
返回教室
释放您分配的任何内存。现在就要养成跟踪每次分配的习惯,然后在计划结束前给每个分配
免费
。是的,当您的程序退出时,内存会被释放,但是当您开始编写分配内存的函数(如此处所示)时,您必须
释放该内存,否则随着代码的增长,内存管理将很快变得无法管理。(所以帮自己一个忙,从一开始就学会正确地做)

接下来,在您希望用户输入的任何界面中,提示用户输入。否则,用户会看到屏幕上闪烁的光标,怀疑程序是否卡住

思考您需要什么样的数据,并在逻辑上向用户提供提示,这将有助于您以一种不那么尴尬的方式布局代码


。(例如,
typedef Line*LinePtr;
)只会混淆
int main(void) 
{
    LinePtr startPtr = NULL;
    add(&startPtr, "x");
    add(&startPtr, "y");
    add(&startPtr, "z");

    place(&startPtr, "A", "z");
    place_after_otherName(&startPtr, "B", "z");

    LinePtr p = startPtr;
    while(p)
    {
        printf(p->name);
        p = p->nextPtr;
    }

    printf("\n");
    return 0;
}
#define ORDC  25    /* if you need constants, define them or use an enum */
#define NAMC 100    /*      (don't use magic numbers in your code!)     */
...
int main (void) {

    char order[ORDC] = "",  /* initialize all strings to zeros */
        name1[NAMC] = "",
        name2[NAMC] = "";
    line *startptr = NULL;

    /* provide an initial prompt showing valid orders to place */
    printf ("orders [add, out, first, place, reverse, back to classroom]\n");

    for (;;) {  /* loop until done or user cancels input */

        printf ("\norder: ");               /* prompt for order: each iteration */
        if (!fgets (order, sizeof order, stdin)) {  /* use fgets for user input */
            fprintf (stderr, "note: user canceled input.\n");
            return 1;
        }
        rmcrlf (order);        /* trim the trailing '\n' (returning the length) */

        if (strcmp (order, "back to classroom") == 0) {         /* are we done? */
            backtoclassroom (startptr);
            break;
        }

        if (strcmp (order, "reverse") == 0) {          /* reverse takes no name */
            reverse (&startptr);
            continue;
        }

        printf ("name : ");        /* every other function takes a student name */
        if (!fgets (name1, sizeof name1, stdin)) {
            fprintf (stderr, "note: user canceled input.\n");
            return 1;
        }
        rmcrlf (name1);

        if (strcmp (order, "add") == 0)          /* use if, else if, else logic */
            add (&startptr, name1);
        else if (strcmp (order, "out") == 0)
            out (&startptr, name1);
        else if (strcmp (order, "first") == 0)
            first (&startptr, name1);
        else if (strcmp (order, "place") == 0) {      /* place takes two names */
            printf ("after: ");
            if (!fgets (name2, sizeof name2, stdin)) {       /* get name2 here */
                fprintf (stderr, "note: user canceled input.\n");
                return 1;
            }
            rmcrlf (name2);
            place (startptr, name1, name2);
        }
        else    /* handle the Bad Input case */
            fprintf (stderr, "error: invalid order, try again.\n");
    }

    return 0;
}
void first (line **lptr, char *name);
void place (line *lptr, char *name1, char *name2);
void out (line **lptr, char *name) 
{
    line *iter = *lptr,
        *prev  = *lptr;

    if (strcmp ((*lptr)->name, name) == 0) {    /* name is first node */
        iter = iter->nextptr;                   /* save pointer to next */
        free (*lptr);                           /* free first */
        *lptr = iter;                           /* set first = saved */
        return;
    }

    while (iter && strcmp (iter->name, name)) { /* find node with name */
        prev = iter;                            /* save previousptr */
        iter = iter->nextptr;
    }
    if (!iter) {    /* handle name not found */
        fprintf (stderr, "error: %s not in list - can't remove.\n", name);
        return;
    }

    prev->nextptr = iter->nextptr;      /* previousptr = nextptr */
    free (iter);                        /* free current */
}
void place (line *lptr, char *name1, char *name2) 
{
    line *iter = lptr;
    line *newptr = malloc (sizeof *newptr);
    strcpy (newptr->name, name1);
    newptr->nextptr = NULL;

    while (iter && strcmp (iter->name, name2))  /* locate after: name */
        iter = iter->nextptr;

    if (!iter) {    /* handle name2 not found */
        fprintf (stderr, "error: %s not in list - can't place %s.\n", 
                name2, name1);
        return;
    }

    newptr->nextptr = iter->nextptr;
    iter->nextptr = newptr;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ORDC  25    /* if you need constants, define them or use an enum */
#define NAMC 100    /*      (don't use magic numbers in your code!)     */

typedef struct line {
    char name[NAMC];
    struct line *nextptr;
} line;

size_t rmcrlf (char *s);

void add (line **lptr, char *name);
void out (line **lptr, char *name);
int isempty (line *lptr);
void backtoclassroom (line *currentptr);
void first (line **lptr, char *name);
void place (line *lptr, char *name1, char *name2);
static void reverse (line **lptr);

int main (void) {

    char order[ORDC] = "",  /* initialize all strings to zeros */
        name1[NAMC] = "",
        name2[NAMC] = "";
    line *startptr = NULL;

    /* provide an initial prompt showing valid orders to place */
    printf ("orders [add, out, first, place, reverse, back to classroom]\n");

    for (;;) {  /* loop until done or user cancels input */

        printf ("\norder: ");               /* prompt for order: each iteration */
        if (!fgets (order, sizeof order, stdin)) {  /* use fgets for user input */
            fprintf (stderr, "note: user canceled input.\n");
            return 1;
        }
        rmcrlf (order);        /* trim the trailing '\n' (returning the length) */

        if (strcmp (order, "back to classroom") == 0) {         /* are we done? */
            backtoclassroom (startptr);
            break;
        }

        if (strcmp (order, "reverse") == 0) {          /* reverse takes no name */
            reverse (&startptr);
            continue;
        }

        printf ("name : ");        /* every other function takes a student name */
        if (!fgets (name1, sizeof name1, stdin)) {
            fprintf (stderr, "note: user canceled input.\n");
            return 1;
        }
        rmcrlf (name1);

        if (strcmp (order, "add") == 0)          /* use if, else if, else logic */
            add (&startptr, name1);
        else if (strcmp (order, "out") == 0)
            out (&startptr, name1);
        else if (strcmp (order, "first") == 0)
            first (&startptr, name1);
        else if (strcmp (order, "place") == 0) {      /* place takes two names */
            printf ("after: ");
            if (!fgets (name2, sizeof name2, stdin)) {       /* get name2 here */
                fprintf (stderr, "note: user canceled input.\n");
                return 1;
            }
            rmcrlf (name2);
            place (startptr, name1, name2);
        }
        else    /* handle the Bad Input case */
            fprintf (stderr, "error: invalid order, try again.\n");
    }

    return 0;
}

/** remove newline or carriage-return from 's'.
 *  returns new length. 's' must not be NULL.
 */
size_t rmcrlf (char *s)
{
    char *p = s;

    if (!*s)        /* s is empty-string */
        return 0;

    /* find eol or nul-terminating char */
    for (; *p && *p != '\n' && *p != '\r'; p++) {}

    if (*p == '\n' || *p == '\r')   /* validate eol & overwrite */
        *p = 0;
    else                            /* warn - no end-of-line */
        fprintf (stderr, "rmcrlf() warning: no eol detected.\n");

    return (size_t)(p - s);
}

int isempty (line *lptr) 
{
    return (lptr == NULL);
}

void backtoclassroom (line *currentptr) 
{
    printf ("\nline returning to classroom:\n\n");
    if (isempty (currentptr)) {
        printf ("line is empty.\n");
    }
    else {
        while (currentptr != NULL) {
            line *victim = currentptr;          /* ptr to node to free */
            printf ("  %s\n", currentptr->name);
            currentptr = currentptr->nextptr;
            free (victim);                      /* free your memory! */
        }
    }
}

static void reverse (line **lptr) 
{
    line *previousptr = NULL,
        *currentptr = *lptr,
        *afterptr;

    while (currentptr != NULL) {
        afterptr  = currentptr->nextptr;  
        currentptr->nextptr = previousptr;   
        previousptr = currentptr;
        currentptr = afterptr;
    }
    *lptr = previousptr;
}

void out (line **lptr, char *name) 
{
    line *iter = *lptr,
        *prev  = *lptr;

    if (strcmp ((*lptr)->name, name) == 0) {    /* name is first node */
        iter = iter->nextptr;                   /* save pointer to next */
        free (*lptr);                           /* free first */
        *lptr = iter;                           /* set first = saved */
        return;
    }

    while (iter && strcmp (iter->name, name)) { /* find node with name */
        prev = iter;                            /* save previousptr */
        iter = iter->nextptr;
    }
    if (!iter) {    /* handle name not found */
        fprintf (stderr, "error: %s not in list - can't remove.\n", name);
        return;
    }

    prev->nextptr = iter->nextptr;      /* previousptr = nextptr */
    free (iter);                        /* free current */
}

void first (line **lptr, char *name) 
{
    line *newptr = malloc (sizeof *newptr);     /* set size on current *ptr */
    strcpy (newptr->name, name);
    newptr->nextptr = *lptr;
    *lptr = newptr;
}

void place (line *lptr, char *name1, char *name2) 
{
    line *iter = lptr;
    line *newptr = malloc (sizeof *newptr);
    strcpy (newptr->name, name1);
    newptr->nextptr = NULL;

    while (iter && strcmp (iter->name, name2))  /* locate after: name */
        iter = iter->nextptr;

    if (!iter) {    /* handle name2 not found */
        fprintf (stderr, "error: %s not in list - can't place %s.\n", 
                name2, name1);
        return;
    }

    newptr->nextptr = iter->nextptr;
    iter->nextptr = newptr;
}

void add (line **lptr, char *name) 
{
    line *newptr = malloc (sizeof *newptr);     /* set size on current *ptr */
    line *lastptr = *lptr;
    strcpy (newptr->name, name);
    newptr->nextptr = NULL;
    if (*lptr == NULL) {
        *lptr = newptr;
        return;
    }  
    while (lastptr->nextptr != NULL) {
        lastptr = lastptr->nextptr;
    }
    lastptr->nextptr = newptr;    
}
$ ./bin/classline
orders [add, out, first, place, reverse, back to classroom]

order: add
name : john doe

order: add
name : mary smith

order: first
name : nancy first

order: place
name : sally second
after: nancy first

order: out
name : john doe

order: back to classroom

line returning to classroom:

  nancy first
  sally second
  mary smith
$ valgrind ./bin/classline
==22574== Memcheck, a memory error detector
==22574== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22574== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==22574== Command: ./bin/classline
==22574==
orders [add, out, first, place, reverse, back to classroom]
<snip>
line returning to classroom:

  nancy first
  sally second
  mary smith
==22574==
==22574== HEAP SUMMARY:
==22574==     in use at exit: 0 bytes in 0 blocks
==22574==   total heap usage: 4 allocs, 4 frees, 448 bytes allocated
==22574==
==22574== All heap blocks were freed -- no leaks are possible
==22574==
==22574== For counts of detected and suppressed errors, rerun with: -v
==22574== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)