无法从单个链接列表

时间:2016-10-20 23:24:02

标签: c gcc data-structures linked-list singly-linked-list

从链接列表中删除元音时遇到问题。程序接受命令行参数,将它们组合在一个字符串中,并将每个字符作为节点添加到链接列表中。

当我尝试使用命令行参数“lemon”运行程序时,成功删除元音。即如果参数不包含结果元音,程序将成功删除元音。 另一方面,如果我尝试使用命令行参数“aeiou”执行相同的操作,程序会崩溃并显示消息Segmentation fault(core dumped)..我不知道如何处理这个...

程序不能创建任何全局变量,所以我使用了双指针。 所有功能都正常工作这个问题可能是由于locate()和removeVowels()函数中的一些错误而发生的,但我无法弄清楚错误是什么。

可以用双指针解决这个问题吗? 我无法弄清楚这个程序有什么问题。我是c编程新手,请帮帮我..请纠正我.. 提前致谢。

完整的代码如下:

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

struct linkedList {
    char ch;
    struct linkedList *node;
};
void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locate(struct linkedList**);
int delHead(struct linkedList **);
void removeVowels(struct linkedList**);
int isEmpty(struct linkedList **);

int main(int argc, char *argv[]) {
    int choice, indexer = 0;
    struct linkedList *s;
    char *string;
    if (argc == 1) {
        printf("Parse a sentence");
    } else {
        s = (struct linkedList *) malloc(sizeof(struct linkedList));
        string = combineWithNoSpaces(argc, argv);
        addTolinkedList(string, &s, &indexer);
        while (1) {
            printMenu();
            scanf("%d", &choice);
            if (choice == 1) {
                printLinkedList(&s);
            } else if (choice == 2) {
                if (!delHead(&s))
                    printf("Failed.Empty linked list");
            } else if (choice == 3) {
                removeVowels(&s);

            } else if (choice == 4) {
                if(isEmpty(&s)){
                    printf("Empty LinkedList");
                }
                else
                    printf("Not Empty");
            } else if (choice == 5) {
                break;
            } else
                printf("Invalic choice");
            printf("\n");
        }
    }
    return 0;
}

int isEmpty(struct linkedList **s){
    if(*s == NULL)
        return 1;
    else
        return 0;
}

struct linkedList *locate(struct linkedList **s) {
    if ((*s)->node->ch == 'a' || (*s)->node->ch == 'e' || (*s)->node->ch == 'i'
            || (*s)->node->ch == 'o' || (*s)->node->ch == 'u'
            || (*s)->node->ch == 'A' || (*s)->node->ch == 'E'
            || (*s)->node->ch == 'I' || (*s)->node->ch == 'O'
            || (*s)->node->ch == 'U') {
        return *s;
    } else if ((*s)->node->node == NULL) {
        return NULL;
    } else
        return locate(&((*s)->node));
}
void removeVowels(struct linkedList **s) {
    struct linkedList *temp, *tag;
    /* Checking whether the first node is null or not */
    if ((*s)->ch == 'a' || (*s)->ch == 'e' || (*s)->ch == 'i'
            || (*s)->ch == 'o' || (*s)->ch == 'u'
            || (*s)->ch == 'A' || (*s)->ch == 'E'
            || (*s)->ch == 'I' || (*s)->ch == 'O'
            || (*s)->ch == 'U')
        delHead(s);
    do {
        tag = locate(s);
        if (tag != NULL) {
            temp = tag->node->node;
            free(tag->node);
            tag->node = temp;
        }

    } while (tag != NULL);
}
int delHead(struct linkedList **s) {
    struct linkedList *temp;
    if ((*s) == NULL) {
        return 0;
    } else {
        temp = (*s)->node;
        free(*s);
        *s = temp;
        return 1;
    }
}
void printLinkedList(struct linkedList **s) {
    if ((*s) != NULL) {
        printf("%c", (*s)->ch);
        printLinkedList(&(*s)->node);
    }
    return;
}
void addTolinkedList(char *str, struct linkedList **s, int *indexer) {
    if (*indexer == strlen(str)) {
        *s = NULL;
        return;
    } else {
        (*s)->ch = *(str + *indexer);
        (*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
        ++*indexer;
        addTolinkedList(str, &(*s)->node, indexer);
    }
}
char * combineWithNoSpaces(int argc, char *argv[]) {
    int i, j;
    int count = 0;
    int memory = 0;
    char *str;
    for (i = 1; i < argc; i++) {
        for (j = 0; j < strlen(argv[i]); j++) {
            ++memory;
        }
    }
    str = (char *) malloc(memory * sizeof(char) + 1);
    for (i = 1; i < argc; i++) {
        for (j = 0; j < strlen(argv[i]); j++) {
            *(str + count) = argv[i][j];
            ++count;
        }
    }
    return str;
}
void printMenu(void) {
    printf("\n\n"
            "1. print input arguments (no spaces)\n"
            "2. remove first character\n"
            "3. remove vowels\n"
            "4. is the linked list empty?\n"
            "5. exit program\n"
            "Enter your choice>");
}

输出的屏幕截图是:
对于参数柠檬 argument lemon
为了论证aeiou argument aeiou

2 个答案:

答案 0 :(得分:1)

这段代码令我满意。它更接近MCVE(Minimal, Complete, Verifiable Example

我打电话给程序rv19。当像这样运行时,它会显示输出:

$ rv19 apple
[apple]
[ppl]
$ rv19 nutmeg
[nutmeg]
[ntmg]
$ rv19 ply
[ply]
[ply]
$ rv19 aeiou
[aeiou]
[]
$ rv19 aardvark abstemiously facetiously aeiou minions lampoon shampoo
[aardvarkabstemiouslyfacetiouslyaeiouminionslampoonshampoo]
[rdvrkbstmslyfctslymnnslmpnshmp]
$ 

代码(rv19.c):

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

struct linkedList
{
    char ch;
    struct linkedList *node;
};

char *combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locate(struct linkedList **);
int delHead(struct linkedList **);
void removeVowels(struct linkedList **);
void freeLinkedList(struct linkedList *);

int main(int argc, char *argv[])
{
    int indexer = 0;
    struct linkedList *s;
    char *string;
    if (argc == 1)
    {
        printf("Parse a sentence.  Usage: %s word [word ...]\n", argv[0]);
    }
    else
    {
        s = (struct linkedList *) malloc(sizeof(struct linkedList));
        printf("s = %p\n", (void *)s);
        string = combineWithNoSpaces(argc, argv);
        addTolinkedList(string, &s, &indexer);
        printLinkedList(&s);
        removeVowels(&s);
        printLinkedList(&s);
        printf("s = %p\n", (void *)s);
        freeLinkedList(s);
        free(string);
    }
    return 0;
}

static inline int isvowel(char c)
{
    return(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
           c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U');
}

struct linkedList *locate(struct linkedList **s)
{
    if ((*s)->node == NULL)
        return NULL;
    if (isvowel((*s)->node->ch))
    {
        return *s;
    }
    else if ((*s)->node == NULL)
    {
        return NULL;
    }
    else
        return locate(&((*s)->node));
}

void removeVowels(struct linkedList **s)
{
    struct linkedList *temp, *tag;
    /* Remove leading vowels */
    while ((*s) != NULL && isvowel((*s)->ch))
    {
        //printf("Remove leading '%c'\n", (*s)->ch);
        struct linkedList *ts = *s;
        delHead(&ts);
        *s = ts;
    }
    struct linkedList *n = *s;
    while (n != NULL && (tag = locate(&n)) != NULL)
    {
        /* Remove multiple embedded or trailing vowels */
       while (tag->node != NULL && isvowel(tag->node->ch))
        {
            temp = tag->node;
            tag->node = tag->node->node;
            free(temp);
        }
        n = tag->node;
    }
}

int delHead(struct linkedList **s)
{
    struct linkedList *temp;
    if ((*s) == NULL)
        return 0;
    else
    {
        temp = (*s)->node;
        free(*s);
        *s = temp;
        return 1;
    }
}

void printLinkedList(struct linkedList **s)
{
    struct linkedList *n = *s;
    putchar('[');
    while (n != NULL)
    {
        putchar(n->ch);
        n = n->node;
    }
    putchar(']');
    putchar('\n');
}

void addTolinkedList(char *str, struct linkedList **s, int *indexer)
{
    if (*indexer == (int)strlen(str))
    {
        free(*s);
        *s = NULL;
    }
    else
    {
        (*s)->ch = *(str + *indexer);
        (*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
        ++*indexer;
        addTolinkedList(str, &(*s)->node, indexer);
    }
}

char *combineWithNoSpaces(int argc, char *argv[])
{
    int argl[argc+1];
    int memory = 0;
    for (int i = 1; i < argc; i++)
    {
        argl[i] = strlen(argv[i]);
        memory += argl[i];
    }
    char *str = (char *) malloc(memory + 1);
    char *base = str;
    for (int i = 1; i < argc; i++)
    {
        strcpy(base, argv[i]);
        base += argl[i];
    }
    return str;
}

void freeLinkedList(struct linkedList *node)
{
    while (node != NULL)
    {
        struct linkedList *next = node->node;
        free(node);
        node = next;
    }
}

这仍然不尽如人意。我更改了打印,以便在开始之前和输出结束之后获得标记;更容易看到不需要的空白和其他类似的角色。它现在是迭代的。我也将界面更改为该功能,因此需要struct linkedList *而不是struct linkedList **removeVowels()中的代码很棘手;它迭代去除重复的初始元音;它迭代以在非元音之后移除重复的元音。 locate()函数现在返回一个指向非元音节点的指针,该节点在下一个节点中有一个元音。此代码释放字符串和列表(使用新函数freeLinkedList()释放列表)。

我已经使用malloc()的几个调试版本检查了它,它似乎是无泄漏且无腐蚀。

我仍然无法使用valgrind运行它,因为在macOS Sierra 10.12上构建它之后我无法正常运行它:

valgrind: mmap-FIXED(0x0, 253952) failed in UME (load_segment1) with error 12 (Cannot allocate memory).

这是从SVN(修订版16097)下载的最新代码。

答案 1 :(得分:0)

我试图简化所有函数 - 有些人在他们不需要的时候将指针作为参数(指针)。

许多变化的一些亮点:

main:将主控制结构更改为switch语句。将linkedList指针初始化为NULL而不是malloc&#d; dd,因为输入空字符串会导致addTolinkedList()泄漏此内存。选择退出选项后,添加了对新功能freeLinkedList()的调用。

找到:重命名此locateVowel()并使用removeVowel()重新构建,只有一个实际查找元音的地方。消除了潜在的内存泄漏。

combineWithNoSpaces:将其重写为面向字符串而不是面向字符。

addTolinkedList:使索引(er)参数成为一个简单的int,在递归时递增,这简化了许多问题。

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

struct linkedList {
    char ch;
    struct linkedList *node;
};

void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int);
void printLinkedList(struct linkedList *);
struct linkedList **locateVowel(struct linkedList **);
bool delHead(struct linkedList **);
void removeVowels(struct linkedList **);
bool isEmpty(struct linkedList *);
void freeLinkedList(struct linkedList *);

int main(int argc, char *argv[]) {
    int choice;
    char *string;

    if (argc == 1) {
        fprintf(stderr, "Enter a sentence\n");
        return EXIT_FAILURE;
    }

    struct linkedList *s = NULL;

    string = combineWithNoSpaces(argc, argv);

    addTolinkedList(string, &s, 0);

    free(string);

    while (true) {
        printMenu();
        (void) scanf("%d", &choice);

        printf("\n");

        switch (choice) {
            case 1:
                printLinkedList(s);
                break;
            case 2:
                if (!delHead(&s)) {
                    printf("Failed. Empty linked list\n");
                }
                break;
            case 3:
                removeVowels(&s);
                break;
            case 4:
                if (isEmpty(s)) {
                    printf("Empty LinkedList\n");
                } else {
                    printf("Not Empty\n");
                }
                break;
            case 5: 
                freeLinkedList(s);
                return EXIT_SUCCESS;
            default:
                printf("Invalid choice\n");
        }
    }

    return EXIT_SUCCESS;
}

bool isEmpty(struct linkedList *s) {
    return (s == NULL);
}

struct linkedList **locateVowel(struct linkedList **s) {

    if (*s == NULL) {
        return NULL;
    }

    char ch = tolower((*s)->ch);

    if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
        return s;
    }

    return locateVowel(&((*s)->node));
}

void removeVowels(struct linkedList **s) {

    struct linkedList **vowel;

    while ((vowel = locateVowel(s)) != NULL) {
        struct linkedList *temporary = (*vowel)->node;

        if (temporary == NULL) {
            free(*vowel); // a vowel with nothing following it
            *vowel = NULL;
            break;
        }

        (*vowel)->ch = temporary->ch;
        (*vowel)->node = temporary->node;

        free(temporary);

        s = vowel;
    }
}

bool delHead(struct linkedList **s) {

    if (*s == NULL) {
        return false;
    }

    struct linkedList *temporary = (*s)->node;
    free(*s);
    *s = temporary;

    return true;
}

void printLinkedList(struct linkedList *s) {
    printf("\"");

    while (s != NULL) {
        printf("%c", s->ch);
        s = s->node;
    }

    printf("\"\n");
}

void addTolinkedList(char *string, struct linkedList **s, int index) {
    if (index == strlen(string)) {
        *s = NULL;
    } else {
        *s = malloc(sizeof(struct linkedList));

        (*s)->ch = string[index];
        (*s)->node = NULL;

        addTolinkedList(string, &(*s)->node, index + 1);
    }
}

char *combineWithNoSpaces(int argc, char *argv[]) {
    int characters = 0;

    for (int i = 1; i < argc; i++) {
        characters += strlen(argv[i]);
    }

    char *string = calloc(characters + 1, 1);

    for (int i = 1; i < argc; i++) {
        (void) strcat(string, argv[i]);
    }

    return string;
}

void freeLinkedList(struct linkedList *s) {
    while (s != NULL) {

        struct linkedList *temporary = s;

        s = s->node;

        free(temporary);
    }
}

void printMenu(void) {
    printf("\n"
        "1. print string (no spaces)\n"
        "2. remove first character\n"
        "3. remove vowels\n"
        "4. is the linked list empty?\n"
        "5. exit program\n"
        "Enter your choice: ");
}