c - 打印随机数到列表
问题描述
我的任务是生成 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;
}
解决方案
您的代码有几个错误:
第一个错误:
循环
while (count_even < 10 & count_odd < 10) {
count_even
或count_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;
}
推荐阅读
- discord.js - 在特定公会的特定频道中编辑消息 | 不和谐.js
- python - PyQt 使用向导和单选按钮
- python - Del 命令未正确执行 Pandas
- google-cloud-platform - ownCloud 10.0.7 连接数据库失败
- ios - 领域数据库过滤后重新加载 TableView 时如何解决“索引越界”错误?
- javascript - 为什么我无法在事件回调中捕获 discord.js 承诺拒绝?
- javascript - 通过 JavaScript 中的递归使用 DOM 节点填充线性数组
- flutter - 如何编辑颤振“barcode_scan 1.0.0”插件
- jscript - JScript 转义 URL 有效负载数据中的 & 符号
- c# - “对象引用未设置为对象的实例”,但在检查器中找不到对象引用