【问题标题】:Program not outputting at all when first argument begins with an even integer当第一个参数以偶数开头时程序根本不输出
【发布时间】:2022-12-01 04:16:40
【问题描述】:

下面的程序从命令行读取一个非负整数数组。我的目标是使用双向链表删除所有偶数整数,并仅逐行输出奇数整数,最后输出奇数整数之和。

`

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

typedef struct Node { // Defining a double linked list through struct. Node  ->  | llink | data | rlink |
    int data;
    struct Node *rlink;
    struct Node *llink;
} Node;

// Declaring function prototypes.
Node *nodeAdder (char *argv[], int len);
int evenCounter (char *argv[], int len);
Node *evenRemover (Node *initial);
void llSum (int *sum, Node *initial);
void oddPrint (Node *initial);

Node *nodeAdder (char *argv[], int len) 

    Node *initial, *llink, *current;
    initial = (Node*)calloc(1, sizeof(Node));
    current = initial;
    current->data = atoi(argv[1]);
    int i;

    for(i=0; i < len-1; i++) {
        current->rlink = (Node*)calloc(1, sizeof(Node));
        llink = current;
        current = current->rlink;
        current->data = atoi(argv[i+2]);
        current->llink = llink;
    }
    current->rlink = NULL;
    return initial;
}

int evenCounter (char *argv[], int len) {
    
    int i, count=0;

    for(i=0; i < len; i++) {
        if(atoi(argv[i+1]) % 2 == 0) {
            count = count + 1;
        }
    }
    return count;
}

Node *evenRemover (Node *initial) {

    Node *leftLink=NULL, *rightLink=NULL, *remove=initial;

    while(remove->data % 2 != 0 && remove->rlink != NULL) {
        remove = remove->rlink;
    }

    if(remove->llink == NULL) {
        initial = remove->llink; 
        initial->llink = NULL;
    }
    else if(remove->rlink == NULL) {
        leftLink = remove->llink;
        leftLink->rlink = NULL;
    }
    else {
        leftLink = remove->llink;
        rightLink = remove->rlink;
        leftLink->rlink = rightLink;
        rightLink->llink = leftLink;
    }
    free(remove);
    return initial;
}

void llSum (int *sum, Node *initial) {

    Node *ptr=initial;

    while(ptr != NULL) {
        *sum = *sum + ptr->data;
        ptr = ptr->rlink;
    }
}

void oddPrint (Node *initial) {

    Node *ptr = NULL;

    for(ptr=initial; ptr != NULL; ptr = ptr->rlink) {
        printf("%i\n", ptr->data);
    }
}

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

    Node *initial = NULL;
    int total=0, len=argc-1, i=0;
    int evens = evenCounter(argv, len);
    initial = nodeAdder(argv, len);

    for(i; i < evens; i++) {
        initial = evenRemover(initial);
    }

    llSum(&total, initial);
    oddPrint(initial);
    printf("%i\n", total);
    return 0;
}

`

示例输入:10 15 20 25 30

示例输出:

15
25
40

如果输入中的整数以奇数开头,则一切正常,但是当它以偶数开头时,它不会打印任何内容。

我想知道是否有人可以帮助我找到我的错误?

我花了一段时间才想出我现在拥有的东西,而且我看不出这种方法有什么问题。我肯定某处只是一个小错误

【问题讨论】:

标签: c data-structures linked-list dynamic-memory-allocation


【解决方案1】:

考虑如果 initial 等于 remove 会发生什么。您将释放指针,然后返回它。

Node *evenRemover (Node *initial)
{
    Node *leftLink=NULL, *rightLink=NULL, *remove=initial;

    // ...

    free(remove);
    return initial;
}

问题是内存不再可用,你的列表是一个悬空指针。访问它是未定义的行为。解决方案是确保在这种情况下移动列表的头部:

Node *evenRemover (Node *initial)
{
    Node *leftLink=NULL, *rightLink=NULL, *remove=initial;

    // ...

    if (initial == remove)
       initial = initial->rlink;

    free(remove);
    return initial;
}

这不是该功能的唯一问题。如果您传入 NULL 列表,您也可能会在此处取消引用 NULL 指针。如果指针有效,则该循环的结束条件将使 remove 指向最后一个节点,无论它是否为偶数。所以你很可能最终会删除一个奇数:

while(remove->data % 2 != 0 && remove->rlink != NULL) {
    remove = remove->rlink;
}

您可以按如下方式修复:

while(remove != NULL && remove->data % 2 != 0) {
    remove = remove->rlink;
}

// No even node found
if (remove == NULL)
    return initial;

一旦您的程序开始运行,就该考虑您的方法了。这没有利用链表提供的功能。您正在遍历列表以计算内容,然后多次独立遍历整个列表以删除内容。这是非常浪费的(时间复杂度是 O(N^2))。

相反,您应该编写一个删除列表元素的通用函数。然后,遍历您的列表并任何当您看到偶数元素时,将其删除并继续遍历列表。这具有时间复杂度 O(N)。

【讨论】:

    猜你喜欢
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 2016-12-21
    • 1970-01-01
    相关资源
    最近更新 更多