首先,我需要创建并显示一个以数字1000结尾的列表。效果很好。
然后,我想创建一个仅在第一个列表中被3整除的数字的列表,但这不起作用。
最糟糕的是,它甚至没有告诉我发生了什么事。它只是在执行中产生错误,但控制台什么也没说。
我将非常感谢您的帮助。
我尽力了。
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define CANTIDAD_NUMEROS 13
#define CANTIDAD_NUMEROS2 6
#define DESDE 1
#define HASTA 10
typedef struct lista{
int num;
struct lista *sig;
}nodo;
void crear (nodo *pt, int, int);
void crear2 (nodo *pt, int, nodo *pt2);
void mostrar(nodo *pt);
int main()
{
int i=0;
int t=0;
nodo *prin;
nodo *prin2;
prin=(nodo*)malloc(sizeof(nodo));
prin2=(nodo*)malloc(sizeof(nodo));
crear(prin,i, t); //creates first list
mostrar (prin); //shows first list
crear2(prin,i, prin2); //gets 'divisible by 3' numbers
mostrar(prin2); // shows second list
return 0;
}
//creates list
void crear (nodo *registro, int cont, int t)
{
scanf("%d", &t);
registro->num = t;
if (registro->num == 1000)
registro->sig=NULL;
else
{
registro->sig=(nodo*)malloc(sizeof(nodo));
cont++;
crear (registro->sig,cont, t);
}
return;
}
//shows list
void mostrar (nodo *registro)
{
if (registro->sig !=NULL)
{
printf ("%d\n",registro->num);
mostrar (registro->sig);
}else{
printf("%d\n",registro->num);
}
return;
}
//creates second list with only numbers that are divisible by 3
void crear2 (nodo *registro, int cont, nodo *registroNuevo)
{
if ((registro->num % 3) == 0){
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
}
if(registro->sig != NULL){
crear2(registro->sig,cont, registroNuevo->sig);
}else{
return;
}
}
我希望显示第一个列表(正在发生),并且显示第二个列表,其中的数字可以被3整除,这不会发生。
答案 0 :(得分:1)
void crear2 (nodo *registro, int cont, nodo *registroNuevo) {
if ((registro->num % 3) == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo);
}
}
这是我的方法,但是您在最后一次mostrar()调用中仍然得到最终的意外0;而且您仍然需要进行“免费”通话。我认为您应该避免递归调用,有更简单的方法可以做到。致敬。
答案 1 :(得分:0)
首先,我很佩服您对递归的奉献!
问题是在crear2
中,registroNuevo->sig
未初始化,这会导致段错误。我几乎总是通过检查参数node是否为null来启动对递归链接数据结构进行操作的函数。如果是这样,我可以安全地继续使用该函数的主体。按照这种防止空值的逻辑,在registroNuevo
的情况下,我们需要传递registro->num % 3 != 0
节点而不接触它,并确保其所有字段都已初始化。
这是更正的功能:
void crear2(nodo *registro, int cont, nodo *registroNuevo)
{
if (registro) {
if (registro->num % 3 == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = NULL;
if (registro->sig) {
registroNuevo->sig = malloc(sizeof(nodo));
}
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
crear2(registro->sig, cont, registroNuevo);
}
}
}
尽管如此,由于一些原因,此功能仍不理想。首先,名称含糊不清,可以更好地描述行为。另外,如果没有可被三整除的项目,则在调用范围中有一个malloc
ed节点,它永远不会被初始化,因此这方面有点脆弱。第三,即使有一个参数,它仍然感觉像是一个非常具体的函数,没有很多可重用性因素,可以在调用范围内迭代编写,例如:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo
{
int num;
struct nodo *sig;
} nodo;
nodo *crear(nodo *registro, int num)
{
nodo *n = malloc(sizeof(nodo));
n->num = num;
n->sig = registro;
return n;
}
void mostrar(nodo *registro)
{
if (registro)
{
printf("%d->", registro->num);
mostrar(registro->sig);
}
else puts("");
}
void free_lista(nodo *registro)
{
if (registro)
{
free_lista(registro->sig);
free(registro);
}
}
int main()
{
nodo *prin = NULL;
nodo *prin_div_3 = NULL;
for (int t; scanf("%d", &t) && t != 1000;)
{
prin = crear(prin, t);
}
nodo *tmp = prin;
while (tmp)
{
if (tmp->num % 3 == 0)
{
prin_div_3 = crear(prin_div_3, tmp->num);
}
tmp = tmp->sig;
}
mostrar(prin);
mostrar(prin_div_3);
free_lista(prin);
free_lista(prin_div_3);
return 0;
}
这不是完美的-没有尾部节点,添加到列表中并不理想,但是消除了悬空的头部,希望它显示了组织程序逻辑和功能的另一种方法。
其他几点:
free_lista
。3
和1000
这样的硬编码值的高度特定的功能。设置这些参数以最大化可重用性。crear2
从不使用cont
成员,并且您有未使用的全局常量。清理它们是一个好主意,以帮助您弄清调试工作并减少视觉混乱。malloc
的结果。if (registro->sig !=NULL)
,因为函数的第一行将崩溃为null。您也不需要!= NULL
。 if (registro) { ... }
最清晰,可避免使用空参数。