为什么我的程序在最后一次 scanf 之后就结束了?

问题描述 投票:0回答:1

我正在编写一个带有结构和指针的程序。正如您将在程序中看到的,我询问用户是否想继续添加学生。我想检查他的答案是

Yes
还是
No
。显然我做错了什么,因为我的程序在他回答后完成。所以我需要帮助来发现错误并找到正确编写代码的方法。

我还想问为什么

number[i].age
需要在
&
中的字体中添加
scanf
。我的意思是它是一个指针,所以为什么要使用
&

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student {

  char name[30];
  int age;

}student ;

int main(){
 typedef int size;
 int i;
 size siz=0;
 student *number;

   printf("Welcome\n\nEnter the number of student you want to evaluate: ");
   scanf("%d",&siz);

   printf("\n");


   number=malloc(siz*(sizeof(struct student)));


   for(i=0;i<siz;i++){

                      printf("Student name: ");
                      scanf("%s",number[i].name);

                      printf("Student age: ");
                      scanf("%d",&number[i].age);
                      printf("\n");
    }

      printf("Do you want to add Students(Yes or No)? ");

      void * answer;
      scanf("%s",*answer);
      
   if(strcmp(answer, "Yes")==0){

        printf("\n Give the number of the additional students: ");

        int adsize;

        scanf("%d",&adsize);

  student*realloc=(number,adsize*sizeof(int));
  int j=0;
  for(j=0;j<adsize;j++){
                           printf("Student name: ");
                           scanf("%c",number[j].name);

                           printf("Student age: ");
                           scanf("%d",number[j].age);
                           printf("\n");
  }
}
else
    printf("\nEnd of programm");





return 0;

}
arrays c pointers scanf ampersand
1个回答
0
投票

您必须学会正确缩进代码,以便您和其他人获得可读性。

这是代码的重新格式化版本:

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

typedef struct student {
    char name[30];
    int age;
} student;

int main() {
    typedef int size;
    int i;
    size siz = 0;
    student *number;

    printf("Welcome\n\nEnter the number of student you want to evaluate: ");
    scanf("%d", &siz);

    printf("\n");

    number = malloc(siz * (sizeof(struct student)));

    for (i = 0; i < siz; i++) {
        printf("Student name: ");
        scanf("%s", number[i].name);

        printf("Student age: ");
        scanf("%d", &number[i].age);
        printf("\n");
    }

    printf("Do you want to add Students(Yes or No)? ");

    void *answer;
    scanf("%s", *answer);

    if (strcmp(answer, "Yes") == 0) {

        printf("\n Give the number of the additional students: ");

        int adsize;
        scanf("%d", &adsize);

        student *realloc = (number, adsize * sizeof(int));
        int j = 0;
        for (j = 0; j < adsize; j++) {
            printf("Student name: ");
            scanf("%c", number[j].name);

            printf("Student age: ");
            scanf("%d", number[j].age);
            printf("\n");
        }
    } else
        printf("\nEnd of programm");

    return 0;
}

有些问题立即出现:

  • typedef int size;
    在函数
    main
    中定义了具有局部作用域的类型。避免这种令人困惑且容易出错的定义。

  • scanf("%d", &siz)
    中,您没有测试
    scanf()
    的返回值。这是有风险的,因为无效或丢失的输入将被忽略,如果代码后面没有未定义的行为,则会导致意外的行为。 始终测试并报告无效或丢失的输入:

      if (scanf("%d", &siz) != 1) {
          fprintf(stderr, "invalid or missing input\n");
          exit(1);
      }
    
  • 您使用

    malloc
    分配内存,但不检查分配失败。测试和报告内存分配失败也将有助于跟踪问题。

  • scanf("%s", number[i].name);
    不需要
    &
    ,因为
    number[i].name
    是一个数组,并且数组始终作为指向其第一个元素的指针传递。然而,这个
    scanf()
    调用是有风险的,因为您没有为
    scanf()
    提供防止超长输入缓冲区溢出的方法。用这个代替:

      if (scanf("%29s", number[i].name) != 1) {
          fprintf(stderr, "invalid or missing input for number[%d].name\n", i);
          exit(1);
      }
    
  • scanf("%d", &number[i].age);
    需要
    &
    ,因为
    number[i].age
    int
    成员,您必须将其地址传递给
    scanf
    才能存储转换后的值。当然,您必须测试返回值以检测并报告无效或丢失的输入。

  • void *answer; scanf("%s", *answer);
    完全是假的:您取消引用
    void
    指针,该指针无法在标准 C 中编译(您的编译器可能支持它的扩展)并且
    answer
    无论如何都未初始化,因此取消引用指针可能具有未定义的行为分段错误,这会导致您的程序按观察到的方式停止。你应该这样写:

      char answer[10];
      if (scanf("%9s", answer) != 1 || strcmp(answer, "Yes")) {
          printf("end of program\n");
          return 0;
      }
    
  • student*realloc=(number,adsize*sizeof(int));
    是最惊喜的!它实际上被解析为

      student *realloc = (number, adsize * sizeof(int));
    

    它将局部变量

    realloc
    定义为指向
    student
    的指针,通过将
    adsize * sizeof(int)
    转换为指针进行初始化...毫无意义,并且对
    number
    指向的数组没有副作用。

您绝对应该使用额外的警告进行编译,以使用 gcc -Wall -Wextra -Werror 或编译器的类似选项来检测此类错误。

© www.soinside.com 2019 - 2024. All rights reserved.