C编程 - Scanf /获得意外行为

时间:2013-11-08 09:29:11

标签: c

该程序应该执行以下操作:

添加主要详细信息

添加大学详细信息

将专业添加到大学

更新主要费用

搜索专业

在完成主要功能之前,我遇到了一个问题:

当我使用scanf而不是函数时,它会询问2个问题而不让我填写前一个问题。例如:输入大学名称:输入大学的地址: 当我使用时,我遇到了同样的问题。

如果还有其他错误,请提示我

提前致谢!

#include <stdio.h>
#include <string.h>

//Define Structures
typedef struct {
    char name[30];
    char department[30];
    int nb_students;
    int credits;
    float cost;
    char adv_name[15];
}Major;
typedef struct {
    char name[50];
    char address[30];
    Major uni_majors[50];
    int nb_majors;
}University;

// Define Functions Prototypes
Major majors_function();
University university_function();
void AddMajor(Major *major,University *university);
University UpdateMajor(char nameMajor[], University U, float newCost);
void SearchMajor(Major major,University university);

int main(int argc, const char * argv[])
{
    Major new_major;
    University new_university;

    new_major = majors_function();
    new_university = university_function();


    return 0;
}

// Fills The Major Details Function
Major majors_function() {

    Major major;

    printf("Enter Major name: ");
    gets(major.name);

    printf("Enter Department name: ");
    gets(major.department);

    printf("Enter number of students: ");
    scanf("%d",&major.nb_students);

    printf("Enter number of credits: ");
    scanf("%d",&major.credits);

    printf("Enter the cost of credit: ");
    scanf("%f",&major.cost);

    printf("Enter the Advisor's Last Name: ");
    scanf("%s",major.adv_name);

    return major;
}

// Fills the university details Function
University university_function() {
    University university;



    printf("Enter university's name: ");
    gets(university.name);

    printf("Enter university's address: ");
    gets(university.address);

    printf("Enter number of majors in this univeristy: ");
    scanf("%d",&university.nb_majors);


    return university;
}

// Adds Major to a university
void AddMajor(Major *major,University *university) {

    university->nb_majors = 0;
    if(university->nb_majors <50) {
        university->uni_majors[university->nb_majors] = *major;
    }
    else
        printf("No Available space");

    university->nb_majors++;


}

// Update Major's Cost
University UpdateMajor(char nameMajor[], University U, float newCost) {

    if(strcmp(nameMajor,U.uni_majors->name)) {
        U.uni_majors->cost = newCost;
    }
    return U;
}

// Searches for a major in a university
void SearchMajor(Major major,University university) {
    if(strcmp(university.uni_majors->name,major.name))
        printf("The total cost of this major is %.2f",(major.cost*major.credits));
    else
        printf("There is no such major!");
}

2 个答案:

答案 0 :(得分:2)

使用scanf扫描字符串或字符时。您可能希望跳过前导空格(如换行符)。这可以通过要求scanf跳过空格,通过在格式代码前面添加一个空格来完成,例如

scanf(" %s",major.adv_name);
/*     ^      */
/*     |      */
/* Note space */

您可能想要了解更多有关scanf及其兄弟姐妹的信息。 this reference page

答案 1 :(得分:0)

永远不会永远不会永远不会使用gets,而不是用于家庭作业,即使是玩具代码也是如此。它在1999年标准中被弃用,已从2011年标准中删除。它在您的程序中引入一个主要的失败点。请改用fgets

fgets( major.name, sizeof major.name, stdin );

并检查返回值以确保它成功。

或者,您可以使用scanf,但是您需要在转换说明符中指定最大缓冲区大小:

scanf( "%29s", major.name ); // leave 1 space for the 0 terminator

唯一的问题是尺寸必须是硬编码的;你不能像使用printf一样将它作为参数传递。或者,您可以在运行时构建格式字符串,例如:

char fmt[5]; // good for %0s to %99s
sprintf( fmt, "%%%zus", sizeof major.name );
...
scanf( fmt, major.name );

坦率地说,你最好使用fgets来处理所有事情,包括数字输入。

char inbuf[10];
char *chk;

// Read the number of students as text, then convert with the
// strtol library function; allows us to catch and reject
// non-numeric input. 
printf( "Enter number of students: " );
fflush( stdout );
if ( fgets( inbuf, sizeof inbuf, stdin ) != EOF )
{
  int tmp = (int) strtol( inbuf, &chk, 10 );
  if ( isspace( *chk ) || *chk == 0 )
  {
    major.nb_students = tmp;
  }
  else
  {
    fprintf( stderr, "%s is not a valid number\n", inbuf );
  }
}