gpt4 book ai didi

c - 如何使用函数从列表中删除字符串?

转载 作者:行者123 更新时间:2023-11-30 14:43:18 28 4
gpt4 key购买 nike

我已经尝试并搜索了此问题。如果我尝试从列表中删除一个字符串,则会收到“ 3221225477”作为返回值。

我已经尝试过使用其他方法,例如更改'return value [];'在const char * del(ListNodePtr * strPtr,value [])函数中将“返回* value;”如果您能告诉我我应该在代码中进行哪些更改,将不胜感激。

这就是我定义结构的方式。我不知道这是否真的很好。

        #include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct listnode
{
char data[100];
listnode *nextPtr;
};
typedef struct listnode ListNode;
typedef ListNode *ListNodePtr;


这是插入函数:

        void insert(ListNodePtr *strPtr, char value[])
{
ListNodePtr previousPtr, currentPtr, newPtr;

newPtr=(listnode*)malloc(sizeof(listnode));
strcpy(newPtr->data,value);
newPtr->nextPtr=NULL;

previousPtr=NULL;
currentPtr=*strPtr;
if(newPtr!=NULL)
{
while(currentPtr!=NULL &&
strcmp(currentPtr->data,value)<0)
{
previousPtr=currentPtr;
currentPtr=currentPtr->nextPtr;
}

if(previousPtr==NULL)
{
newPtr->nextPtr=*strPtr;
*strPtr=newPtr;
}
else
{
previousPtr->nextPtr=newPtr;
newPtr->nextPtr=currentPtr;
}
}else printf("%s was not inserted. Insuffiecient memory!",value);

}


这是“删除”功能:

        const char *del(ListNodePtr *strPtr, char value[])
{
ListNodePtr previousPtr, currentPtr, tempPtr;

if(strcmp(value, (*strPtr)->data)==0) /*if the
first node shall be deleted*/
{
/*delete node*/
tempPtr=*strPtr;
*strPtr=(*strPtr)->nextPtr;
free(tempPtr);
return *value;
}
else
{
previousPtr=*strPtr;
currentPtr=(*strPtr)->nextPtr;
while(currentPtr!=NULL && strcmp(value,
currentPtr->data)!=0)
{
previousPtr=currentPtr;
currentPtr=currentPtr->nextPtr;

}

if(currentPtr!=NULL)
{
tempPtr=currentPtr;
previousPtr- >nextPtr=currentPtr->nextPtr;
free(tempPtr);
return *value;
}
}


return '\0';//if the node is not found

}


这是main()函数:

int main()
{
ListNodePtr startPtr;
startPtr=NULL;

int optiune;
char nume[100];

instructions();
printf("? ");
scanf("%d",&optiune);

while(optiune!=3)
{
switch(optiune)
{
case 1:
printf("Enter name:");
fflush(stdin);
gets(nume);
insert(&startPtr, nume);
printList(startPtr);
break;

case 2:
fflush(stdin);
printf("Search by name to delete from list:");
gets(nume);
if(!Empty(startPtr))
{
if(del(&startPtr, nume))
{
printf("%s was deleted!\n");
printList(startPtr);
}else printf("%s was not found!\n",nume);

}else
printf("List is empty!");
break;

case 3:
break;
default:
printf("No such option!\n\n");
instructions();
break;
}
printf("\n? ");
scanf("%d",&optiune);
}
printf("Execution stopped.\n" );
return EXIT_SUCCESS;

最佳答案

问题中的代码有很多小问题,但是当这些问题被清除后,核心算法似乎可以正常工作。缩进在某些地方有点奇怪。从现在开始,我将忽略该问题。

不幸的是,批评可以很快开始:

struct listnode
{
char data[100];
listnode *nextPtr;
};
typedef struct listnode ListNode;
typedef ListNode *ListNodePtr;


这是一个C问题,但是如果代码曾经编译过,那是因为它是由C ++编译器编译的。 listnode *nextPtr;在C中无效(但在C ++中有效)。在那一行,名称 struct listnode是已知的,但是没有任何 listnode前缀的类型 struct在任何标准标头中都没有定义(通常情况下,无论如何)。您需要 struct listnode *nextPtr;是有效的C。或者您需要将 typedef struct listnode ListNode;移到结构定义之前,然后在结构中使用 ListNode *nextPtr;。您可能不应该定义或使用 ListNodePtr-有关原因的讨论,请参见 Is it a good idea to typedef pointers?。您可以像这样清理代码。请注意,结构标签(如 ListNode)位于标签名称空间(以及 union标签和 enum标签),但typedef名称 ListNode位于不同的“普通标识符”名称空间中-因此没有这段代码中 ListNode的使用之间存在冲突:

typedef struct ListNode ListNode;
struct ListNode
{
char data[100];
ListNode *nextPtr;
};


在下文中,“清理类型”是指使用 ListNode代替 ListNodePtr或任何其他变体拼写。

清除类型后, insert()中的代码就可以了;错误消息应打印到 stderr,并进行拼写检查,并以换行符结尾。

del()中的代码可能不在函数 delete()中,因为 delete是C ++编译器中的关键字,因此不能用作函数名。不要使用C ++编译器来编译C,否则会产生误导性的结果。

该函数的声明返回类型为 const char *,但是返回的值不是指针。最好更改该函数以返回 int或什至 bool以指示其是否成功删除了指定名称。

在以下位置还存在间距错误:

previousPtr - > nextPtr = currentPtr->nextPtr;


.或箭头 ->运算符之间不应有空格,并且 ->之间也没有空格,您甚至没有正式的箭头运算符。

但是, del()中的核心算法似乎可以正常工作。可能还有改进的空间。

您的代码引用了诸如 Empty()printList()instructions()之类的未定义(实际上是未声明)的函数-创建MCVE( Minimal, Complete, Verifiable Example)时,不应遗漏这样的内容。下面的代码为每种方法提供了简单的实现。

main()中的代码显示了各种问题。一种是通过不编写有用的功能来完成特定工作的代码重复。我不知道您对 instructions()函数的计划是什么,但是我保留了它,并将其简化为打印单个提示的 printf()(末尾没有换行符)。它本身是从处理许多复杂细节的函数 get_option()中使用的。

您永远不要使用 gets()函数;了解为什么 it is far too dangerous to use gets() — ever!。另外,将 scanf()fgets()之类的功能混合会有点麻烦,因为 scanf() leaves the newline in the input buffer。我创建了函数 get_option()get_string()来处理问题,并处理无效(非数字)输入和意外的EOF等。它们还刷新标准输出,但不刷新标准输入。参见 Using fflush(stdin)进行细微的讨论-可以说 fflush(stdin)不是可移植的,尽管它确实在Windows上定义了行为,但是除了调用未定义的行为外,它在其他任何地方都几乎没有做。通常,避免使用它。如果必须使用它,请注意限制了代码的可移植性(通常没有必要这样做)。

使用“输入和测试位于顶部的循环”, main()主体中的代码稍微简单一些。我在 case 2:代码中对测试进行了重新排序,以避免嵌套ifs。通常最好是在测试后做一些事情,而不是开始新的测试。

请注意,错误条件报告输入(读取)的值。这对用户来说很有价值-如果您看到意外的报告值,则可以更好地推断出出了什么问题。

将所有内容放在一起可以得到如下代码:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct ListNode ListNode;
struct ListNode
{
char data[100];
ListNode *nextPtr;
};

extern void insert(ListNode **strPtr, char value[]);
extern bool delete(ListNode **strPtr, char value[]);

void insert(ListNode **strPtr, char value[])
{
ListNode *previousPtr, *currentPtr, *newPtr;

newPtr = (ListNode *)malloc(sizeof(ListNode));
strcpy(newPtr->data, value);
newPtr->nextPtr = NULL;

previousPtr = NULL;
currentPtr = *strPtr;
if (newPtr != NULL)
{
while (currentPtr != NULL &&
strcmp(currentPtr->data, value) < 0)
{
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}

if (previousPtr == NULL)
{
newPtr->nextPtr = *strPtr;
*strPtr = newPtr;
}
else
{
previousPtr->nextPtr = newPtr;
newPtr->nextPtr = currentPtr;
}
}
else
fprintf(stderr, "%s was not inserted. Insufficient memory!\n", value);
}

bool delete(ListNode **strPtr, char value[])
{
ListNode *previousPtr, *currentPtr, *tempPtr;

if (strcmp(value, (*strPtr)->data) == 0)
{
tempPtr = *strPtr;
*strPtr = (*strPtr)->nextPtr;
free(tempPtr);
return true;
}
else
{
previousPtr = *strPtr;
currentPtr = (*strPtr)->nextPtr;
while (currentPtr != NULL && strcmp(value, currentPtr->data) != 0)
{
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if (currentPtr != NULL)
{
tempPtr = currentPtr;
previousPtr->nextPtr = currentPtr->nextPtr;
free(tempPtr);
return true;
}
}

return false;
}

static bool Empty(ListNode *ptr)
{
return(ptr == NULL);
}

static void get_string(size_t size, char buffer[size])
{
if (fgets(buffer, size, stdin) == 0)
{
fprintf(stderr, "Unexpected EOF on standard input\n");
exit(EXIT_FAILURE);
}
buffer[strcspn(buffer, "\n")] = '\0';
}

static void instructions(void)
{
printf("1 to add, 2 to delete, 3 to exit: ");
}

static int get_option(void)
{
int optiune;

instructions();
fflush(stdout);
if (scanf("%d", &optiune) != 1)
{
fprintf(stderr, "Failed to read option number\n");
exit(EXIT_FAILURE);
}
int c;
while ((c = getchar()) != EOF && c != '\n')
;
return optiune;
}

static void printList(ListNode *ptr)
{
for (int i = 0; ptr != NULL; i++)
{
printf("%d: %s\n", i, ptr->data);
ptr = ptr->nextPtr;
}
}

int main(void)
{
ListNode *startPtr;
startPtr = NULL;
int optiune;
char nume[100];

while ((optiune = get_option()) != 3)
{
switch (optiune)
{
case 1:
printf("Enter name: ");
fflush(stdout);
get_string(sizeof(nume), nume);
insert(&startPtr, nume);
printList(startPtr);
break;

case 2:
printf("Search by name to delete from list: ");
fflush(stdout);
get_string(sizeof(nume), nume);
if (Empty(startPtr))
printf("List is empty!\n");
else if (delete(&startPtr, nume))
{
printf("%s was deleted!\n", nume);
printList(startPtr);
}
else
printf("%s was not found!\n", nume);
break;

default:
fprintf(stderr, "No such option (%d)!\n\n", optiune);
break;
}
}

printf("Execution stopped.\n");
return EXIT_SUCCESS;
}


(我制作函数 static,除非有一个标头在其中声明它们,以及另一个将使用它们的源文件。这甚至可以帮助优化,因为编译器可以告知 static函数被调用的频率以及我的内联代码)

这是上面代码的示例运行:

1 to add, 2 to delete, 3 to exit: 1
Enter name: Patricia
0: Patricia
1 to add, 2 to delete, 3 to exit: 1
Enter name: Persephone
0: Patricia
1: Persephone
1 to add, 2 to delete, 3 to exit: 1
Enter name: Piglet
0: Patricia
1: Persephone
2: Piglet
1 to add, 2 to delete, 3 to exit: 1
Enter name: Pooh
0: Patricia
1: Persephone
2: Piglet
3: Pooh
1 to add, 2 to delete, 3 to exit: 1
Enter name: Puss In Boots
0: Patricia
1: Persephone
2: Piglet
3: Pooh
4: Puss In Boots
1 to add, 2 to delete, 3 to exit: 1
Enter name: Pygmalion
0: Patricia
1: Persephone
2: Piglet
3: Pooh
4: Puss In Boots
5: Pygmalion
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Pooh
Pooh was deleted!
0: Patricia
1: Persephone
2: Piglet
3: Puss In Boots
4: Pygmalion
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Pygmalion
Pygmalion was deleted!
0: Patricia
1: Persephone
2: Piglet
3: Puss In Boots
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Patricia
Patricia was deleted!
0: Persephone
1: Piglet
2: Puss In Boots
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Piglet
Piglet was deleted!
0: Persephone
1: Puss In Boots
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Puss In Boots
Puss In Boots was deleted!
0: Persephone
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Quantum Gold
Quantum Gold was not found!
1 to add, 2 to delete, 3 to exit: 2
Search by name to delete from list: Persephone
Persephone was deleted!
1 to add, 2 to delete, 3 to exit: 3
Execution stopped.

关于c - 如何使用函数从列表中删除字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53990832/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com