c - 将 scanf 交换为 fgets 和随机符号
问题描述
我设置了一个挑战来创建一个简单的犯罪报告系统。我最初使用 scanf 输入数据,但在 fgets 上传输了一些数据,这导致 printf 的多个部分在不要求输入的情况下聚集在一起。此外,代码末尾的报告部分会打印随机符号,我不知道如何删除它们。
#include <stdio.h>
int main ()
{
int incident_day, incident_month, incident_year, incident_hour, incident_minute, dd, mm, yy;
long long int contact_number, wit_contact_number[12];
char safe_place, CRS_qu, medical_qu, incident_address, incident_address_house_no[10], incident_address_street[10], incident_address_postcode[10], assailant_qu;
char assailant_name[20], assailant_address[40], wit_qu, wit_name[20], weapon_description[50], armed_qu[3];
char first_name[20], surname[20];
start:
printf(" Are you in a safe place? (Y/N)\n");
scanf(" %[^\n]s", &safe_place);
while (safe_place == 'N' || safe_place == 'n')
{
printf(" Please contact the police Service immediatly on 999\n");
break;
}
printf(" This Crime Reporting System is for victims on assuault only, Are you a victim on assault? (Y/N)\n");
scanf(" %[^\n]s", &CRS_qu);
while (CRS_qu == 'N' || CRS_qu == 'n')
{
printf(" Please select the appropriate Crime Reporting System related to the crime you want to report\n");
goto start;
}
printf(" Have you had any medical treatment for any injurys sustained during the incident? (Y/N)\n");
scanf(" %[^\n]s", &medical_qu);
while (medical_qu == 'N' || medical_qu == 'n')
{
printf(" Please contact the Ambulance Service on 999 and get imediate medical attention\n");
break;
}
printf(" Please enter the date of the incident? (DD/MM/YY)\n");
scanf("%d/%d/%d", &incident_day, &incident_month, &incident_year);
start2:
printf(" Please enter an approximate time of the incident? Format 24:00\n");
scanf("%d:%d", &incident_hour, &incident_minute);
if (incident_hour <00 || incident_hour >23 || incident_minute <00 || incident_minute >59)
{
printf(" Please enter a valid time in a 24:00 format\n");
goto start2;
}
printf(" Do you know the address of the incident? (Y/N)\n");
scanf(" %[^\n]s", &incident_address);
while ( incident_address == 'Y'|| incident_address == 'y')
{
printf(" Please enter the House No.?\n");
fgets(incident_address_house_no, 10, stdin);
printf(" Please enter the Street Name?\n");
fgets(incident_address_street, 10, stdin);
printf(" Please enter the Postcode?\n");
fgets(incident_address_postcode, 10, stdin);
break;
}
printf(" Do you know the assailant? (Y/N)\n");
scanf(" %[^\n]s", &assailant_qu);
while ( assailant_qu == 'Y' || assailant_qu == 'y')
{
printf(" Enter the assailants name?\n");
fgets(assailant_name, 20, stdin);
printf(" Enter the assailants address?\n");
fgets(assailant_address, 40, stdin);
break;
}
while ( assailant_qu == 'N' || assailant_qu == 'n')
{
printf(" A detective will be incontact to get a description of the assailant\n");
break;
}
printf("Were there any witnesses to the incident? (Y/N)\n");
scanf(" %[^\n]s", &wit_qu);
while ( wit_qu == 'Y' || wit_qu == 'y')
{
printf(" Enter the witnesses name?\n");
fgets(wit_name, 20, stdin);
printf(" Enter the witnesses contact number?\n");
fgets(wit_contact_number, 12, stdin);
break;
}
printf(" Was the assailant armed? (Y/N)\n");
fgets(armed_qu, 3, stdin);
while ( *armed_qu == 'Y' || armed_qu == 'y')
{
printf(" Please describe what the assailant was armed with?\n");
fgets(weapon_description, 50, stdin);
break;
}
printf(" \nPlease enter yours details when prompted\n");
printf(" \nPlease enter your First Name\n");
scanf("%s", first_name);
printf(" \nPlease enter your Surname\n");
scanf("%s", surname);
printf(" \nPlease enter yours Date of Birth, format DD/MM/YYYY\n");
scanf("%d/%d/%d", &dd,&mm,&yy);
if(yy>=1900 && yy<=2018)
{
//check month
if(mm>=1 && mm<=12)
{
//check days
if((dd>=1 && dd<=31) && (mm==1 || mm==3 || mm==5 || mm==7 || mm==8 || mm==10 || mm==12))
printf("Date is valid\n");
else if ((dd>=1 && dd<=30) && (mm==4 || mm==6 || mm==9 || mm==11))
printf("date is valid\n");
else if ((dd>=1 && dd<=28) && (mm==2))
printf("Date is valid.\n");
else if ((dd==29 && mm==2 && (yy%400==0 || yy%4==0 && yy%100!=0)))
printf("Date is valid.\n");
else
printf("Date is invalid.\n");
}
}
mo:
printf("\nEnter Contact Number +44");
while ( !scanf("%lli",&contact_number))
{
fflush(stdin);
printf("\n Invalid Contact Number:\n\n");
printf(" Enter Contact Number Again : ");
}
if (contact_number < 1000000000 || contact_number > 9999999999)
{
printf("\n Please Enter only 10 digits.....\n");
goto mo;
}
printf(" Victims Details\n");
printf(" Full Name : %s %s \n", first_name, surname);
printf(" DOB : %d/%d/%d \n", dd,mm,yy);
printf(" Contact Number : +44%lld \n", contact_number);
printf(" Witness Details\n");
printf(" Full Name : %s\n", wit_name);
printf(" Contact Number : +44%lln\n", wit_contact_number);
printf(" Assailant Details\n");
printf(" Full Name : %s\n", assailant_name);
printf(" Address : %s\n", assailant_address);
printf(" Incident Details\n");
printf(" Date of Incident : %d/%d/%d \n", incident_day,incident_month, incident_year);
printf(" Time of Incident : %d:%d\n", incident_hour, incident_minute);
printf(" Street No. of Incident : %s\n", incident_address_house_no);
printf(" Address of Incident : %s\n", incident_address_street);
printf(" Postcode of Incident : %s\n", incident_address_postcode);
printf(" Was the Assailant Armed: %s\n", armed_qu);
printf(" Description of Weapon : %s\n", weapon_description);
return 0;
}
解决方案
OP的代码有各种类型的错误
不需要s
_scanf(" %[^\n]s"
s
没有任何目的
// scanf(" %[^\n]s", &safe_place);
scanf(" %[^\n]", &safe_place);
与scanf()
_fgets()
的使用scanf(" %[^\n]"...
会消耗包括先验在内的前导空格,但会在文本输入之后'\n'
留下任何空格。 读取并包括. right after只会读取先前输入的 left- over 。'\n'
stdin
fgets()
'\n'
fgets()
scanf(" %[^\n]"...
'\n'
缺乏宽度限制
缓冲区可能很容易溢出。
char first_name[20];
// scanf("%s", first_name);
scanf("%19s", first_name);
将字符串保存为单个char
safe_place
需要至少 2 的大小,一个用于'Y'
or'N'
和终止空字符。
// char safe_place;
char safe_place[10];
printf(" Are you in a safe place? (Y/N)\n");
// scanf(" %[^\n]s", &safe_place);
scanf(" %9[^\n]", &safe_place);
很少的错误检查
如果输入了意外的数据,代码不会验证输入是否正确,也不会消耗错误的输入。
// scanf("%d/%d/%d", &incident_day, &incident_month, &incident_year)
if (scanf("%d/%d/%d", &incident_day, &incident_month, &incident_year) != 3) {
Handle_Bad_Input_Somehow();
}
下面是一些替代代码,用于显示读取一行然后使用它。
int get_line(const char *prompt, char *dest, size_t size) {
printf("%s", prompt);
fflush(stdout);
if (fgets(dest, size, stdin) == NULL) {
dest[0] = '\0';
return 0;
}
dest[strcspn(dest, "\n")] = '\0'; // Lop off potential trailing '\n'
return 1;
}
int main(void) {
char safe_place[10];
get_line(" Are you in a safe place? (Y/N)\n", safe_place, sizeof safe_place);
if (safe_place[0] == 'N' || safe_place[0] == 'n') {
printf(" Please contact the police Service immediately on 999\n");
}
char date[20];
int incident_day, incident_month, incident_year;
do {
get_line(" Please enter the date of the incident? (DD/MM/YY)\n", date, sizeof date);
} while (sscanf(date, "%d/%d/%d", &incident_day, &incident_month, &incident_year) != 3);
char incident_address_house_no[20];
get_line(" Please enter the House No.?\n", incident_address_house_no,
sizeof incident_address_house_no);
printf(" Date of Incident : %d/%d/%d \n", incident_day, incident_month,
incident_year);
printf(" Street No. of Incident : %s\n", incident_address_house_no);
return 0;
}
推荐阅读
- microsoft-graph-api - MS-Graph 和带附件的 sendmail 失败
- angular - 如何将 Ajax 获取请求转换为 Angular 7 http 获取请求
- apache-poi - 获取较低级别的 XML 对象以将图像插入到 Apache POI 中的图表中?
- kdb - 如何比较查询中的特殊字符串
- html - 更改导航栏文本颜色
- r - R如何创建一个新变量,该变量引用另一个数据框中的特定值
- algorithm - AC-3算法的时间复杂度
- sql-server - 无法将大型数据库附加到在 docker 容器进程中运行的 SQL Server 引擎
- python - 将 wordpress xml 文件导入 Python 项目
- svelte - 尝试在 svelte 组件运行之前加载 js 文件