搜索链表c内的元素



所以我有一个带有结构的链表实现的头文件,问题是当我想找到一个元素是否已经在链表中时,如果我在主函数中执行了所有步骤,它会起作用,但如果我在单独的函数中执行,它就不起作用,我不知道为什么。

程序:

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>
#include "Listas_ligadas2.h"
/*
ident: val[0]
linha: val[1]
*/
void remove_esp(char str[]); // removes the first char of the scanned string beacuse its of being a ' '
int equipa_in(link_v head, char nome[]);// the function with the problem
void A(char equipa[],int val[],link_v headv);
//basically while c != x it applies the switch
int main()
{
char c;char nome[1023];
link_v head2 = NULL;
int valores[2] = {0,1};
while ((c = getchar())!= 'x') {
switch (c) 
{
case 'A':
{
scanf("%1023[^:n]",nome);
remove_esp(nome);
if (equipa_in(head2,nome) == 1)
{
printf("%d Equipa existente.n",valores[1]);
valores[1]++;
}
else
{
head2 = insertEnd_v(head2,nome,valores);
valores[1]++;
}
break;
}
}
}
return 0;
}
int equipa_in(link_v head, char nome[])
{
link_v t;
for(t = head; t != NULL; t = t->next)
if(strcmp(t->v.nome,nome) == 0)
return 1;
return 0;
}
void remove_esp (char str[])
{
int i;
if (str[0] == ' ')
{
for (i = 0; str[i] != ''; ++i)
str[i] = str[i + 1];
}
}

所以如果我这样做,效果很好,但如果我这样这样做:

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>
#include "Listas_ligadas2.h"
/*
ident: val[0]
linha: val[1]
*/
void remove_esp(char str[]); // removes the first char of the scanned string beacuse its of being a ' '
int equipa_in(link_v head, char nome[]);// the function with the problem
void A(char nome[],int valores[],link_v head2);

//basically while c != x it applies the switch
int main()
{
char c;char nome[1023];
link_v head2 = NULL;
int valores[2] = {0,1};
while ((c = getchar())!= 'x') {
switch (c) 
{
case 'A':
{
scanf("%1023[^:n]",nome);
remove_esp(nome);
A(nome,valores,head2);
break;
}
}
}
return 0;
}
int equipa_in(link_v head, char nome[])
{
link_v t;
for(t = head; t != NULL; t = t->next)
if(strcmp(t->v.nome,nome) == 0)
return 1;
return 0;
}
void remove_esp (char str[])
{
int i;
if (str[0] == ' ')
{
for (i = 0; str[i] != ''; ++i)
str[i] = str[i + 1];
}
}
void A(char nome[],int valores[],link_v head2)
{
if (equipa_in(head2,nome) == 1)
{
printf("%d Equipa existente.n",valores[1]);
valores[1]++;
}
else
{
head2 = insertEnd_v(head2,nome,valores);
valores[1]++;
}
}

它不起作用,我不明白为什么。

头文件:

#ifndef _Listas_ligadas2_
#define _Listas_ligadas2_
#include<stdlib.h> 
#include<stdio.h>
#include <string.h>
typedef struct vit
{
int id;
char *nome;
int vit;
} vit;
typedef struct node_v
{
vit v;
struct node_v *next;
} *link_v;

//this function removes a certin char at a given index
void removechar_v(char *orig, int index, char *newStr)
{
if(!orig){};
if(!newStr){};
int i=0, j=0;
while (*(orig+i) != '')
{
if (i != index)
{
*(newStr+j) = *(orig+i);
j++;
i++;
}
else i++;
}
*(newStr+j) = '';
}
link_v NEW_vit(char *nome,int val[])
{
int i;
link_v x = (link_v) malloc(sizeof(struct node_v));
x->v.nome = (char*) malloc(sizeof(char)*(strlen(nome)+1));
strcpy(x->v.nome,nome);
x->v.vit = 0;
x->v.id = val[0];
x->next = NULL;
val[0]++;
return x;
}
link_v insertEnd_v(link_v head,char *nome,int val[])
{
link_v x;
if(head == NULL)
return NEW_vit(nome,val);
for(x = head; x->next != NULL; x = x->next)
;
x->next = NEW_vit(nome,val);
return head;
}
int length_v(link_v head)
{
int count=0;
link_v x;
for(x=head ; x!=NULL; x=x->next)
count++;
return count;
}
//prints the elements in the list and copies its name to another string because
//for some reason if i want to print t->v.nome and the nome is abc it prints abcc
void print_lista_v(link_v head,int val[])
{
link_v t;char *nnome;
for(t = head; t != NULL; t = t->next){
nnome = (char*) malloc(strlen(t->v.nome)*sizeof(char));
strcpy(nnome,t->v.nome);
removechar_v(nnome,strlen(t->v.nome)-1,nnome);
printf("%d %d %s %dn",val[1],t->v.id,nnome,t->v.vit);
}
}
//after removing an element it puts the corresponding indexes of the list
void baixa_id_v(link_v head)
{
link_v t;int i;
i = 0;
for(t = head; t != NULL; t = t->next){
t->v.id = i++;
}
}
void FREEnode_v(link_v t)
{
free(t->v.nome);
free(t);
}
link_v delete_el_v(link_v head,char *nome)
{
link_v t, prev;
for(t = head, prev = NULL; t != NULL;
prev = t, t = t->next) {
if(strcmp(t->v.nome,nome) == 0) {
if(t == head)
head = t->next;
else
prev->next = t->next;
FREEnode_v(t);
break;
}
}
return head;
}
link_v lookup_v(link_v head, char *nome)
{
link_v t;
for(t = head; t != NULL; t = t->next)
if(strcmp(t->v.nome,nome) == 0)
return t;
return NULL;
}
#endif

我尝试过复制然后编译/运行您的代码。除了一些拼写错误(代码中有一些对link_char的引用,我将其更改为link_v,我还声明了char nome_jg[1023]link_v head),它对我很有用

我确实写了以下函数:

void remove_esp (char str[])
{
int i;
if (str[0] == ' ')
{
for (i = 0; str[i] != ''; ++i)
str[i] = str[i + 1];
}
}

这似乎就是函数所需的注释。

问题可能与remove_esp的实现有关。

正如注释部分已经指出的那样,问题是函数main将指向链表头的指针按值传递给函数A。这意味着函数A将拥有指向链表头的指针的自己的副本。因此,对函数A中的该指针的任何修改都不会改变函数main中的指针。

如果希望函数main接收指向链表头的指针的更新值,则必须为函数main提供某种方式来接收此值。你有三个选项可以实现这一点:

  1. 更改函数"A"的原型以返回指向链表头的新指针的值
  2. 更改函数"A"的原型,使指向链表头的指针通过指针而不是通过值传递
  3. 将指向链表头的指针存储在函数mainA都将使用的全局可验证文件中

一般来说,我不推荐选项#3,因为使用全局变量通常是糟糕的编程风格。选项#1更好,但是使用返回值不是很灵活,因为函数只能返回一个值。因此,最灵活的选择是选择#2。

为了实现选项#2,您必须将功能原型从更改为

void A(char nome[],int valores[],link_v head2);

至:

void A(char nome[],int valores[],link_v *head2);

然而,这是令人困惑的,因为link_v已经是一个指针;它是CCD_ 18的typedef。因此,link_v *实际上是struct node_v **,所以它是一个双指针。为了明确它是一个双指针,我不会使用link_vtypedef,而是使用struct node_v **。此外,为了明确它是一个双指针,我还将通过前缀"pp_"来更改变量的名称,如下所示:

void A(char nome[],int valores[], struct node_v **pp_head2);

现在,您可以重写行

A(nome,valores,head2);

在函数main中转换为以下内容:

A(nome,valores,&head2);

现在通过指针而不是通过值传递变量head2,这样就不会复制该变量。这样,函数A对该变量的任何改变也将改变函数main中该变量的值。

但是,由于函数Ahead2参数现在是一个双指针,因此在该函数内部必须使用不同的参数。线路

head2 = insertEnd_v(head2,nome,valores);

必须更改为:

*pp_head2 = insertEnd_v(*pp_head2,nome,valores);

请注意,我不得不添加*来取消引用双指针一次。我还必须更改那一行中的变量名,因为我更改了函数参数的名称。

相关内容

  • 没有找到相关文章

最新更新