首页 > 解决方案 > 打印随机数到列表

问题描述

我的任务是生成 50 到 80 范围内的随机数,如果生成的数字是偶数,则将其添加到偶数列表中,如果是奇数,则将其添加到奇数列表中。程序应该一直运行到两个列表都填满 10 个数字。列表中不允许重复。此代码打印 20 个不同的数字,并将重复项存储在列表中。所以我认为问题出在 count_odd、count_even 和检查重复项上,但我找不到解决方案。我还必须打印所有生成的数字以及最后的两个列表。链表中的数字应按降序排列

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>

typedef struct list numbers;
typedef struct list* Pos;

int PrintRandom();
Pos CreateNew();
int PrintList(Pos);

struct list {
    int number;
    Pos next;
};

int PrintList(Pos P) {
    if (P == NULL)
        printf("Empty list.\n");
    while (P != NULL) {
        printf("%d\n", P->number);
        P = P->next;
    }
    return 0;
}

Pos CreateNew() {
    Pos q = NULL;
    q = (Pos)malloc(sizeof(struct list));
    if (q == NULL) return NULL;
    q->next = NULL;
    return q;
}

int PrintRandom() {
    int x = 0, max = 80, min = 50;
    x = (rand() % (max - min + 1) + min);
    printf("Random number is : %d\n", x);
    
    return x;
}

int main() {
    srand(time(0));
    Pos even, odd, q = NULL;
    even = malloc(sizeof(numbers));
    odd = malloc(sizeof(numbers));
    even->next = odd->next = NULL;
    int count_even = 0, count_odd = 0, j;
    Pos head_p =even, head_n=odd;

    while (count_even < 10 & count_odd < 10) {
        j = PrintRandom();
        if (j % 2 == 0) {
            q = CreateNew();
            if (q == NULL) return -1;
            q->number = j;
            while (even->next != NULL && even->next->number > q->number) {
                even = even->next;
            }
            if (even->number== q->number)
                free(q);
            else
                q->next = even->next;
            even->next = q;
            even =head_p;
            count_even++;
        }
        else {
            q = CreateNew();
            if (q == NULL) return -1;
            q->number = j;
            while (odd->next != NULL && odd->next->number > q->number) {
                odd = odd->next;
            }
            if (odd->number == q->number)
                free(q);
            else
                q->next = odd->next;
            odd->next = q;
            odd = head_n;
            count_odd++;
        }
    }

    printf("Even numbers in list are:\n");
    PrintList(head_p->next);
    printf("Odd numbers in list are:n");
    PrintList(head_n->next);

    return 0;
}

标签: clistrandomduplicates

解决方案


您的代码有几个错误:


第一个错误:

循环

while (count_even < 10 & count_odd < 10) {

count_evencount_odd到达时将停止10。但是,在您的问题中,您表示只有在两者都达到时才应停止循环10

因此,您应该将该行更改为以下内容:

while ( count_even < 10 || count_odd < 10 ) {

此外,值得指出的&是按位与运算符。您可能打算使用逻辑与运算符,即&&.


第二个错误:

在评论部分,您声明如果其中一个列表已满(有 10 个元素),则应丢弃属于该列表的所有其他数字。但是,您的程序不包含任何代码来检查这一点。相反,您的程序将继续向列表中添加新元素,即使它已经有 10 个元素。


第三个错误:

以下代码是错误的:

if (even->number== q->number)
    free(q);
else
    q->next = even->next;
even->next = q;
even =head_p;
count_even++;

首先,你应该改变表达

even->number== q->number

至:

even->next->number== q->number

但是,由于even->next可能为 null,因此您必须事先对其进行测试,以便整行看起来像这样:

if ( even->next != NULL && even->next->number== q->number)

此外,线条

even->next = q;

count_even++;

如果数字已经存在,则不应执行。else因此,您应该在块内移动这些行。执行这些更改后,您的代码应如下所示:

if ( even->next != NULL && even->next->number== q->number)
{
    free(q);
}
else
{
    q->next = even->next;
    even->next = q;
    count_even++;
}
even =head_p;

应该在奇数的代码分支上执行相同的更改。


第四个错误:

以下行中缺少反斜杠字符:

printf("Odd numbers in list are:n");

您应该将其更改为:

printf("Odd numbers in list are:\n");


补充说明:

我认为您的代码中还有两件事可以改进:

  • 链表的第一个元素只是一个number没有初始化字段的虚拟节点。除了将头指针指向实际的链表之外,您似乎只是使用此节点。

  • 你有很多代码重复。您不必使用相同的代码来处理偶数和奇数,而是使用单独但非常相似的代码来处理每种情况。

在下面的代码中,我重写了您的大部分代码,以向您展示我将如何解决这个问题。如果您发现它难以理解,请不要感到惊讶,因为我使用的是指向指针的指针,这对于初学者来说可能很难理解。如您所见,我没有使用任何虚拟节点,并且我也使用相同的代码来处理偶数和奇数。只有在我的代码的两个地方我有不同的代码来处理偶数和奇数。

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

struct list_node
{
    int number;
    struct list_node *next;
};

int PrintRandom();
int PrintList( struct list_node * );

int PrintList( struct list_node *p)
{
    if ( p == NULL )
    {
        printf( "Empty list.\n" );
    }
    else
    {
        while ( p != NULL )
        {
            printf( "%d\n", p->number );
            p = p->next;
        }
    }
    return 0;
}

int PrintRandom() {
    int x = 0, max = 80, min = 50;
    x = (rand() % (max - min + 1) + min);
    printf("Random number is : %d\n", x);

    return x;
}

int main()
{
    srand( (unsigned)time(NULL) );

    struct list_node *head_even = NULL, *head_odd = NULL;
    int count_even = 0, count_odd = 0, random;
    bool is_even;

    while ( count_even < 10 || count_odd < 10 )
    {
        struct list_node **pp, *p, *q;

        //generate and print random number
        random = PrintRandom();

        //determine whether number is even or odd
        is_even = random % 2 == 0;

        //set pp to point to head pointer of the appropriate list
        //and check whether the appropriate list is already full
        if ( is_even )
        {
            if ( count_even >= 10 )
                continue;
            pp = &head_even;
        }
        else
        {
            if ( count_odd >= 10 )
                continue;
            pp = &head_odd;
        }

        for (;;) //infinite loop, equivalent to while (1)
        {
            p = *pp;

            //if we reached the end of the list, break out of the loop
            if ( p == NULL )
                break;

            if ( p->number <= random )
            {
                if ( p->number == random )
                {
                    //discard number, because it already exists in list

                    //cannot use `continue` here, because that would go to
                    //the next iteration of the innermost loop, but we
                    //want to go to the next iteration of the outer loop
                    goto next_outer_loop_iteration;
                }
                else
                {
                    break;
                }
            }

            pp = &p->next;
        }

        //allocate memory for new node
        q = malloc( sizeof *q );
        if ( q == NULL)
        {
            fprintf( stderr, "error allocating memory for new node!\n" );
            exit( EXIT_FAILURE );
        }

        //initialize new node
        q->number = random;
        q->next = p;

        //insert node into list
        *pp = q;

        //increment the appropriate counter
        if ( is_even )
            count_even++;
        else
            count_odd++;

    next_outer_loop_iteration:
        continue;
    }

    printf("Even numbers in list are:\n");
    PrintList( head_even );
    printf("Odd numbers in list are:\n");
    PrintList( head_odd );

    //NOTE: The memory of the linked lists is not being freed

    return 0;
}

推荐阅读