C语言报错:invalid type argument of '->'(have 'Queue') 解决问询
问题分析与解决方案
首先,咱们来拆解你遇到的几个核心问题:
1. 编译错误的直接原因:结构体访问符号混用+类型不匹配
你在代码里写了:
p.pointer_instrucoes.head=atoi(s2); // 还有后面的 printf("%d\n",p->pointer_instrucoes->head);
- 首先,
PCB结构体里的pointer_instrucoes是**Queue类型的实例**(不是指针),所以访问它的成员应该用.而不是->,这就是编译报错「invalid type argument of '->'」的直接原因。 - 其次,
Queue的head是Node*类型(指向节点的指针),你直接给它赋值atoi(s2)得到的int值,这是严重的类型不匹配,就算编译过也会导致内存错误。
2. 设计层面的核心问题:队列的存储类型不符合需求
你想把指令数字存在PCB的队列里,但当前的Node结构体定义是存储PCB*指针,这完全和你的需求相悖——队列应该存储int类型的指令,而不是PCB对象。
3. PCB初始化错误
在new_pcb函数里,你写了p->pointer_instrucoes=0;,这是把整个Queue结构体赋值为0,属于非法操作,正确的做法是初始化一个空队列。
修正后的完整代码
第一步:修正queue2.h的结构体定义
调整Node和PCB的定义,让队列存储指令数字,同时把PCB里的队列改成指针类型:
#include <stdbool.h> // 先定义基础结构体 typedef struct Node Node; typedef struct Queue Queue; typedef struct PCB PCB; // Node存储int类型的指令 typedef struct Node { int instruction; Node *next; } Node; // Queue结构不变,但后续会添加入队函数 typedef struct Queue { int sizeQueue; int limit; Node *head; } Queue; // PCB里的队列改为指针类型 typedef struct PCB { int id; int program_counter; int size; Queue *pointer_instrucoes; int instante; } PCB; // 函数声明调整 PCB * new_pcb(int id); Node * new_node(int instr); Queue * new_queue(int limit); // 添加入队函数 bool enqueue(Queue *q, int instr);
第二步:修正queue2.c的实现
更新节点、队列、PCB的创建函数,添加入队逻辑:
#include <stdio.h> #include <stdlib.h> #include "queue2.h" Node * new_node(int instr) { Node *n = malloc(sizeof(Node)); if (!n) return NULL; // 检查内存分配 n->instruction = instr; n->next = NULL; return n; } Queue * new_queue(int limit) { Queue *q = malloc(sizeof(Queue)); if (!q) return NULL; q->limit = limit; q->head = NULL; q->sizeQueue = 0; return q; } PCB * new_pcb(int id) { PCB *p = malloc(sizeof(PCB)); if (!p) return NULL; p->id = id; // 初始化一个上限为100的队列(可根据需求调整) p->pointer_instrucoes = new_queue(100); p->program_counter = 0; p->size = 0; p->instante = 0; // 初始化默认值 return p; } // 实现入队函数:把指令添加到队列尾部 bool enqueue(Queue *q, int instr) { if (!q || q->sizeQueue >= q->limit) { return false; // 队列满或无效 } Node *newNode = new_node(instr); if (!newNode) return false; if (q->head == NULL) { q->head = newNode; } else { Node *temp = q->head; while (temp->next != NULL) { temp = temp->next; } temp->next = newNode; } q->sizeQueue++; return true; }
第三步:修正main.c的逻辑
修复结构体访问错误,正确解析每行的指令并加入队列:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "queue2.h" int le_ficheiro(char* filename) { FILE *ficheiro = fopen(filename, "r"); if (!ficheiro) { perror("Failed to open file"); exit(EXIT_FAILURE); } size_t len = 0; char *line = NULL; int contador = 1; while ((getline(&line, &len, ficheiro)) != -1) { // 创建新PCB PCB *p = new_pcb(contador); if (!p) { perror("Failed to create PCB"); exit(EXIT_FAILURE); } // 分割实例和指令部分 char *sp = strchr(line, ' '); if (!sp) { fprintf(stderr, "Invalid line format\n"); free(p); continue; } // 解析实例 char *s1 = strndup(line, sp - line); p->instante = atoi(s1); free(s1); // 用完释放内存 // 解析指令部分:分割每个数字 char *token = strtok(sp + 1, " \n"); while (token != NULL) { int instr = atoi(token); // 把指令加入PCB的队列 if (!enqueue(p->pointer_instrucoes, instr)) { fprintf(stderr, "Failed to enqueue instruction %d for PCB %d\n", instr, p->id); } token = strtok(NULL, " \n"); } // 打印测试信息 printf("PCB ID: %d\n", p->id); printf("Instante: %d\n", p->instante); printf("Number of instructions: %d\n", p->pointer_instrucoes->sizeQueue); // 遍历队列打印指令 Node *temp = p->pointer_instrucoes->head; printf("Instructions: "); while (temp != NULL) { printf("%d ", temp->instruction); temp = temp->next; } printf("\n-------------------------\n"); contador++; // 这里可以根据需求保存PCB到链表或数组,避免内存泄漏 // 示例中暂时不处理,实际项目需要管理这些内存 } fclose(ficheiro); if (line) free(line); return EXIT_SUCCESS; } int main() { char name[50]; printf("Name of the file: "); scanf("%s", name); return le_ficheiro(name); }
测试输入验证
用你提供的输入示例:
1 01 02 03 04 05 2 01 02 03 02 11
运行程序后会输出:
Name of the file: test.txt PCB ID: 1 Instante: 1 Number of instructions: 5 Instructions: 1 2 3 4 5 ------------------------- PCB ID: 2 Instante: 2 Number of instructions: 5 Instructions: 1 2 3 2 11 -------------------------
额外注意事项
- 内存管理:示例中创建的PCB和队列需要在程序结束前释放,避免内存泄漏,你可以添加一个
free_pcb函数来递归释放PCB和其队列的所有节点。 - 队列上限:
new_queue的limit参数可以根据你的实际需求调整,或者改成动态扩容的队列。
内容的提问来源于stack exchange,提问作者user7391306
相关产品推荐
相关产品推荐

