所以我有一个带有结构的链表实现的头文件,问题是当我想找到一个元素是否已经在链表中时,如果我在主函数中执行了所有步骤,它会起作用,但如果我在单独的函数中执行,它就不起作用,我不知道为什么。
程序:
#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
提供某种方式来接收此值。你有三个选项可以实现这一点:
- 更改函数"A"的原型以返回指向链表头的新指针的值
- 更改函数"A"的原型,使指向链表头的指针通过指针而不是通过值传递
- 将指向链表头的指针存储在函数
main
和A
都将使用的全局可验证文件中
一般来说,我不推荐选项#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_v
typedef,而是使用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
中该变量的值。
但是,由于函数A
的head2
参数现在是一个双指针,因此在该函数内部必须使用不同的参数。线路
head2 = insertEnd_v(head2,nome,valores);
必须更改为:
*pp_head2 = insertEnd_v(*pp_head2,nome,valores);
请注意,我不得不添加*
来取消引用双指针一次。我还必须更改那一行中的变量名,因为我更改了函数参数的名称。