Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么从main()向函数传递链表指针会影响main中的链表?_C_List_Pointers - Fatal编程技术网

C 为什么从main()向函数传递链表指针会影响main中的链表?

C 为什么从main()向函数传递链表指针会影响main中的链表?,c,list,pointers,C,List,Pointers,我正在用C写一个程序。这个程序接收从标准输入到包含数据的文件的文件路径。然后根据数据构建链表。链表必须是循环的,但是为了简单起见(为了添加节点、打印列表),我正在将循环列表转换为常规的非循环链表。这是通过unscrc功能完成的。最后,我使用circ函数将列表组装回循环结构 我将指向链接列表的指针传递给函数printList,该函数将打印列表的内容。但是,在从内部printList使用unsrc后,列表实际上仍然是“unsrc”——即使是主列表也是如此。据我所知,指针是按值传递的,因此对print

我正在用C写一个程序。这个程序接收从标准输入到包含数据的文件的文件路径。然后根据数据构建链表。链表必须是循环的,但是为了简单起见(为了添加节点、打印列表),我正在将循环列表转换为常规的非循环链表。这是通过
unscrc
功能完成的。最后,我使用
circ
函数将列表组装回循环结构

我将指向链接列表的指针传递给函数
printList
,该函数将打印列表的内容。但是,在从内部
printList
使用
unsrc
后,列表实际上仍然是“unsrc”——即使是主列表也是如此。据我所知,指针是按值传递的,因此对
printList
中的列表执行任何操作都不会影响原始列表

下面是代码(我只包含了与问题相关的基本函数,否则代码会非常大)。我怀疑,如果你可以说,我可以很容易地打印列表,即使是在循环结构,但真正困扰我的是,原来的列表是改变了指针

#include <stdio.h>
#include <stdlib.h>
#define MAX_FILE_NAME_LEN 300
#define MAX_LINE_LEN 300
#define MATERIAL_LEN 100
#define FIELDS_IN_LIGHTING_NUM 8

enum l_type {
    TABLE = 1, WALL, CEILING
};

typedef struct Lighting {
    enum l_type type;
    int length;
    int width;
    int height;
    int bulbs;
    char material[MATERIAL_LEN];
    int strength;
    struct Lighting * next;
} Lighting;

char * getFileName();
int getVolume(Lighting * light);
Lighting * uncirc(Lighting * light);
Lighting * circ(Lighting *light);
void addNode(Lighting **head,  FILE *fd);
void printNode(Lighting * light);
void printList(Lighting * light);
int countLines(FILE *fd);
void printMaxLight(Lighting * light);

int main() {
    FILE * fd;
    char * path;
    Lighting * n1 = NULL;
    int linesInFile, lightNum, i;
    path = getFileName();
    if(!(fd = fopen(path, "r+"))) {
        printf("Cannot open file %s\n", path);
        fprintf(stderr, "Cannot open file %s\n", path);
        exit(0);
    }

    linesInFile = countLines(fd);
    lightNum = linesInFile / 7;

    for(i = 0; !(feof(fd)) && i < lightNum; i++) {
        addNode(&n1, fd); //read file data and create node
                          //7 lines of data are required to create node                                                     
    }

    fclose(fd);
    printList(n1); //print the linked list
    return 0;
}

Lighting * uncirc(Lighting * light) {
    Lighting * p = light;

    if(p == NULL) {
        return p;
    }
    while(p -> next != light) {
        p = p -> next;
    }

    p -> next = NULL;
    return light;
}

Lighting * circ(Lighting *light) {
    Lighting * p = light;

    if(p == NULL) {
        return p;
    }
    while(p -> next != NULL) {
        p = p -> next;
    }
    p -> next = light;
    return light;
}

void printList(Lighting * light) {
    Lighting * p;
    p = uncirc(light);
    if(p == NULL) {
        printf("Empty list\n");
        return;
    }

    while(p != NULL) {
        printNode(p);
        p = p -> next;
    }
}
#包括
#包括
#定义最大文件名\u LEN 300
#定义最大线长度300
#定义材料规格100
#在照明数量8中定义字段
枚举l_类型{
表=1,墙壁、天花板
};
typedef结构照明{
枚举l_类型;
整数长度;
整数宽度;
内部高度;
int灯泡;
炭材料[材料];
内在力量;
结构照明*下一步;
}照明;
char*getFileName();
int getVolume(照明*灯光);
照明*UNCRC(照明*light);
照明*电路(照明*灯);
void addNode(照明**头部,文件*fd);
void打印节点(照明*灯光);
无效打印列表(照明*灯光);
int countLines(文件*fd);
void printMaxLight(照明*灯光);
int main(){
文件*fd;
字符*路径;
照明*n1=零;
int linesInFile,lightNum,i;
path=getFileName();
如果(!(fd=fopen(路径,“r+”)){
printf(“无法打开文件%s\n”,路径);
fprintf(stderr,“无法打开文件%s\n”,路径);
出口(0);
}
linesInFile=计数行(fd);
lightNum=linesInFile/7;
对于(i=0;!(feof(fd))&&inext!=灯){
p=p->next;
}
p->next=NULL;
返回灯;
}
照明*电路(照明*灯){
照明*p=照明;
if(p==NULL){
返回p;
}
while(p->next!=NULL){
p=p->next;
}
p->next=灯;
返回灯;
}
无效打印列表(照明*灯光){
照明*p;
p=UNCRC(光);
if(p==NULL){
printf(“空列表”);
返回;
}
while(p!=NULL){
printNode(p);
p=p->next;
}
}

指针中不包含列表。只有第一个元素的地址在那里。并且您不会试图修改main中指针在任何点包含的地址

如果您传递第一个元素的地址,然后使用它遍历列表并修改元素,那么当您再次使用相同的地址进行遍历时,它自然会可见


旁注

while(p -> next != light) {
如果您传递的列表不是循环的,这将是一个无限循环。

是“指针按值传递”,但指针指向的任何对象都不是“按值传递”。也就是说,列表本身不会被复制


因此,如果您更改函数中指向的列表,该列表将被更改

当你说
时,列表实际上保持“unsrc”-即使是主
,这是什么意思?当
unscrc
函数只返回其参数时,使用该函数有什么意义?与此相关,
unscrc
的意义值得怀疑,因为从外观上看,唯一的目的是为了打破枚举循环列表的循环性质,这也可以通过一开始就打破循环的枚举逻辑来完成。@WhozCraig你是对的,但后来我偶然发现了这个问题,这对我理解很重要。我不需要向是否对原始列表执行更改?是的,您需要执行更改,因为列表的起始元素也可以更改,这不会反映在调用函数中。我不明白:如果我在
printList
中迭代列表,对于迭代,我将使用
light=light->next
,这是
printList
接收的参数,那么
main
中的原始列表不会收缩为零。但是
unscrc
会留下永久性的更改。@Yos-您会感到困惑,因为您将指针视为您的列表,而它不是。
circ
unsrc
都不会试图更改指针包含的地址。他们只会修改内存。这样想:如果我重新安排我的房子,并不意味着它的地址改变,我需要更新我所有的熟人。他们仍然可以在同一个地址找到我。@Yos-因为你把第一栋房子的地址写在了一张纸上。然后你去了那里,得到了第二所房子的地址。你在自己的一张纸上写的,你没有在第一个房子里修改这张纸。所以列表的逻辑结构保持不变。@Yos-Yup。有人不仅给你复印了他们的论文,还把原件递给了你。如果你一直覆盖它