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

时间:2018-12-31 19:29:55

标签: c string list function

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

我已经尝试使用其他方法,例如更改“返回值[];”在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;

1 个答案:

答案 0 :(得分:1)

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

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

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.