首页 > 解决方案 > 将 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;

}

标签: cprintfscanffgets

解决方案


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'stdinfgets()'\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;
}

推荐阅读