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
- 函数
:将学生x放在队列前面first
- 功能
:从行中删除学生xout
- 函数
:在行中打印学生backToClassroom
- 函数<代码>反转:反转学生在行中的顺序
- 功能
:学生x在他/她身后为学生y占据一个位置,如果学生y想加入队伍,他/她应该在x后面place
- 函数
:将学生x添加到行的末尾,除非学生为他/她自己安排了位置add
添加
和放置
,正如我在顶部解释的那样
#包括
#包括
#包括
结构线{
字符名[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)