C语言FCFS进程调度程序中For循环仅执行一次的问题
问题排查与修复方案
首先不用致歉,刚接触C语言遇到这类问题太正常了,咱们一步步来解决~
循环仅执行一次的核心原因:全局变量i被意外篡改
你代码里的i是全局变量,这就导致在smallestentry()函数里的循环会直接修改这个全局的i值,进而破坏calculate()里for循环的计数器逻辑:
- 当
calculate()里的for循环第一次执行时(i=1),会调用smallestentry() - 在
smallestentry()的for(i=0; i<processes; i++)循环结束后,全局i的值会变成processes(循环终止条件) - 回到
calculate()的for循环,执行i++,此时i变成processes+1,直接不满足i < processes的条件,循环就此终止
除此之外,还有几个小逻辑问题需要调整,比如等待时间的计算边界、输出表头的重复问题等。
具体修复步骤
1. 把全局变量i改为局部变量
所有函数里的循环计数器i都单独声明为局部变量,避免全局变量的副作用:
- 删除全局声明里的
i - 在
input()、changeline()、smallestentry()、calculate()里各自声明int i;
2. 修正smallestentry()的初始值逻辑
当第一个进程被处理后,at[0]会被设为999,为了避免极端情况,先找到第一个未被处理的进程作为初始最小值,再遍历找真正的最小到达时间:
void smallestentry() { int i; // 先找到第一个未被处理的进程作为初始最小值 for(i = 0; i < processes; i++){ if(at[i] != 999){ smallest = at[i]; position = i; break; } } // 再遍历找真正的最小值 for(i = 0; i < processes; i++) { if(at[i] != 999 && smallest > at[i]) { smallest = at[i]; position = i; } } }
3. 修正输出表头的重复问题
changeline()里的表头AT\tBT\tWT\tTAT\tAT重复了AT,改成Original AT对应atperm存储的原始到达时间:
printf("Current AT\tBT\tWT\tTAT\tOriginal AT\n");
4. 调整calculate()里的初始化与等待时间逻辑
确保awt初始化为0,同时处理进程到达时间晚于当前总Burst时间的边界情况(避免等待时间为负数):
void calculate() { awt = 0; // 初始化平均等待时间为0 smallestentry(); wt[position] = 0; tat[position] = bt[position]; atat = tat[position]; int btt = bt[position]; atperm[position] = at[position]; changeline(position); int i; for (i = 1; i < processes; i++) { smallestentry(); // 处理进程到达时间晚于当前总Burst时间的情况 wt[position] = (btt >= at[position]) ? (btt - at[position]) : 0; btt += bt[position]; awt += wt[position]; tat[position] = wt[position] + bt[position]; atat += tat[position]; atperm[position] = at[position]; changeline(position); } atat /= processes; awt /= processes; // 新增最终平均时间输出 printf("平均等待时间: %.2f\n", awt); printf("平均周转时间: %.2f\n", atat); }
修改后的完整代码
#include <stdio.h> #include <stdlib.h> /* * WT - 等待时间 (TAT - BT) * BT - 执行时间(Burst Time) * AT - 到达时间(Arrival Time) * TAT - 周转时间 (CT - AT) * AWT - 平均等待时间 * ATAT - 平均周转时间 */ int wt[10], bt[10], at[10], atperm[10], tat[10], processes, smallest, position; float awt, atat; void input() { printf("输入进程数量:\n"); scanf("%d", &processes); int i; for (i = 0; i < processes; i++) { printf("输入进程%d的Burst时间:", i + 1); scanf("%d", &bt[i]); printf("输入进程%d的到达时间:", i + 1); scanf("%d", &at[i]); } } void changeline(int position) { at[position] = 999; printf("Current AT\tBT\tWT\tTAT\tOriginal AT\n"); int i; for (i = 0; i < processes; i++) { printf("%d\t\t%d\t%d\t%d\t%d\n", at[i], bt[i], wt[i], tat[i], atperm[i]); } printf("----------------------------------------\n"); } void smallestentry() { int i; // 找到第一个未被处理的进程作为初始值 for(i = 0; i < processes; i++){ if(at[i] != 999){ smallest = at[i]; position = i; break; } } // 遍历寻找最小到达时间的进程 for (i = 0; i < processes; i++) { if(at[i] != 999 && smallest > at[i]) { smallest = at[i]; position = i; } } } void calculate() { awt = 0; smallestentry(); wt[position] = 0; // 第一个进程等待时间为0 tat[position] = bt[position]; atat = tat[position]; int btt = bt[position]; atperm[position] = at[position]; changeline(position); int i; for (i = 1; i < processes; i++) { smallestentry(); // 处理进程到达时间晚于当前总Burst时间的情况 wt[position] = (btt >= at[position]) ? (btt - at[position]) : 0; btt += bt[position]; awt += wt[position]; tat[position] = wt[position] + bt[position]; atat += tat[position]; atperm[position] = at[position]; changeline(position); } atat /= processes; awt /= processes; // 最后输出平均时间 printf("平均等待时间: %.2f\n", awt); printf("平均周转时间: %.2f\n", atat); } int main() { printf("FCFS CPU调度算法\n"); input(); calculate(); return 0; }
额外说明
- 新增了平均等待时间和周转时间的最终输出,方便查看结果
- 优化了等待时间的计算逻辑,避免出现负数
- 所有循环计数器都改为局部变量,彻底解决了全局变量导致的逻辑冲突
内容的提问来源于stack exchange,提问作者tkiddy95
相关产品推荐
相关产品推荐

