Mac终端运行C语言日期查询程序出现异常问题求助
问题:Mac终端运行C语言日期查询程序第二次结果错误
我是一名初学者,编写了用于查询2023年日期对应星期的C语言程序,该程序在Xcode及在线C语言工具中运行正常,但在Mac终端运行时,第二次查询结果错误(正确结果应为周四,却显示周一)。请问这是程序bug还是我操作有误?
程序代码
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define BOOL bool int main(void) { int month, date, day = 0, week = 0; int Jan=31, Feb=28, Mar=31, Apr=30, May=31, Jun=30, Jul=31, Aug=31, Sep=30, Oct=31, Nov=30, Dec=31; int cmonth[12]={Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec}; int k; char restart='e'; bool DoYouWantToRestart = true; printf("day searching system (2023)\n"); while (DoYouWantToRestart == true) { k=0; month=0;date=0; restart = 'e'; day=0;week=0; printf("what month is it:"); scanf("%d",&month); printf("what date is it:"); scanf("%d",&date); printf("loading......\n"); if(month<1 || month>12) printf("error!\n"); else if (date>31) printf("error!\n"); else if ((month==4 || month==6 || month==9 || month==11) && date>30) printf("error!\n"); else if (month==2 && date>28) printf("error!\n"); else { for(k=0;k<month-1;k++) { day=day+cmonth[0+k]; } day=day+date; week = day % 7 - 1; switch(week) { case 0: printf("%d/%d is on Sunday\n",month,date); break; case 1: printf("%d/%d is on Monday\n",month,date); break; case 2: printf("%d/%d is on Tuesday\n",month,date); break; case 3: printf("%d/%d is on Wednesday\n",month,date); break; case 4: printf("%d/%d is on Thursday\n",month,date); break; case 5: printf("%d/%d is on Friday\n",month,date); break; case 6: printf("%d/%d is on Saturday\n",month,date); break; } } while(restart == 'e') { printf("restart?(y/n):"); scanf("%s",&restart); if(restart == 'y' || restart == 'Y') DoYouWantToRestart=true; else if (restart == 'n' || restart == 'N') DoYouWantToRestart=false; else { printf("error\n"); restart = 'e'; } } } printf("Have a good day!\n"); return 0; }
问题原因
这是程序的内存溢出bug,根源在scanf("%s", &restart);这行代码:
restart是单个char类型变量,仅占用1字节内存%s格式符用于读取字符串,会把输入的字符(比如输入y后按回车,实际是'y'+'\n')写入内存,超出restart的1字节限制,破坏了相邻变量的内存值- 不同编译环境的内存布局不同,Xcode和在线工具可能刚好没影响到关键变量,但Mac终端的内存布局导致第二次循环时
day或其他计算星期的变量被篡改,从而输出错误结果
修复方案
把读取重启选择的代码改成:
scanf(" %c", &restart);
- 前面的空格
用于跳过输入缓冲区中的空白字符(比如之前输入日期后留下的换行符),避免读取到无效字符 %c是针对单个字符的格式符,匹配restart的char类型,不会出现内存溢出问题
内容的提问来源于stack exchange,提问作者臺灣魚Taiwan Fish
相关产品推荐
相关产品推荐

