简体   繁体   English

我在这里做错了什么? 无论我做什么,function askSubscriptionQuestions 都不会存储 4 个浮点数的值

[英]What am I doing wrong here? No matter what I do, the function askSubscriptionQuestions does not store the values of the 4 floats

So this is a program that calculates the sum of all monthly subscriptions.所以这是一个计算所有每月订阅总和的程序。 But the problem is that the values of.netflixBill, disneyBill etc. are 0 at the function call so the sum is only the struct elements.但问题是 .netflixBill、disneyBill 等的值在 function 调用时为 0,因此总和只是结构元素。 I have tried everything I know but I don't understand why it does not work.我已经尝试了我所知道的一切,但我不明白为什么它不起作用。 enter image description here在此处输入图像描述

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

struct Subscription {
  char name[100];
  float price;
};



int check_login(char *, char *);
void askSubscriptionQuestions(bool *, bool *, bool *, bool *);
struct Subscription ask_subscription();
float total_price(struct Subscription subscriptions[], int num_subscriptions, float netflixBill, float disneyBill, float hboBill, float spotifyBill);


struct Subscription ask_subscription(void) {
  struct Subscription subscription;
  printf("What is the name of the subscription? ");
  scanf("%s", subscription.name);
  printf("How much do you pay every month for it? ");
  scanf("%f", &subscription.price);
  return subscription;
}

int main()
{
  float netflixBill = 0.0f, disneyBill = 0.0f, hboBill = 0.0f, spotifyBill = 0.0f;
  char id[20];
  char password[20];
  bool hasPassed;
  bool hasNetflix;
  bool hasDisneyPlus;
  bool hasHBO;
  bool hasSpotify;
  char response;
  struct Subscription subscriptions[100];
  int num_subscriptions = 0;
  while (1) {
    printf("Enter your ID: ");
    scanf("%s", id);

    printf("Enter your password: ");
    scanf("%s", password);

    if (check_login(id, password)) {
      printf("Access granted.\n");
      hasPassed = true;
      break;
    } else {
      hasPassed = false;
      printf("Access denied.\n");
    }
  }



  printf("Do you have any monthly subscriptions? (y/n) ");
  char c;

  while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
    scanf("%s", &c);
    if (c != 'y' && c != 'Y' && c != 'n' && c != 'N'){
      printf("Invalid input. Please enter 'y' or 'n': ");
    }
  }
printf("%f %f %f %f", netflixBill, disneyBill, hboBill, spotifyBill);
  if (c == 'y' || c == 'Y') {
    askSubscriptionQuestions(&hasNetflix, &hasDisneyPlus, &hasHBO, &hasSpotify);
  } else if (c == 'n' || c == 'N') {
    printf("OK, thank you for your answer.\n");
  }printf("%f %f %f %f", netflixBill, disneyBill, hboBill, spotifyBill);

  printf("Do you have any other monthly subscriptions (Y/N)? ex: YT Premium, iCloud, etc.\n");
  scanf("%s", &response);


  while (response == 'Y' || response == 'y') {
    subscriptions[num_subscriptions] = ask_subscription();
    num_subscriptions++;

    printf("Do you have any other monthly subscriptions (Y/N)? ");
    scanf("%s", &response);
  }

  if (num_subscriptions > 0) {
    printf("Your subscriptions are:\n");
    for (int i = 0; i < num_subscriptions; i++) {
      printf("- %s: $%.2f\n", subscriptions[i].name, subscriptions[i].price);
    }
  } else {
    printf("You do not have any other monthly subscriptions.\n");
  }

  float total = total_price(subscriptions, num_subscriptions, netflixBill, disneyBill, hboBill, spotifyBill);
    printf("The total cost of all your subscriptions is $%.2f\n", total);
  return 0;
}

int check_login(char *id, char *password) {
  if (strcmp(id, "admin") == 0 && strcmp(password, "pass123") == 0) {
    return 1;
  } else {
    return 0;
  }
}

void askSubscriptionQuestions(bool *hasNetflix, bool *hasDisneyPlus, bool *hasHBO, bool *hasSpotify) {
  char c;
  int netflixPlan, spotifyPlan;
  float netflixBill = 0.0f, disneyBill = 0.0f, hboBill = 0.0f, spotifyBill = 0.0f;
  printf("Do you have a subscription to Netflix? (y/n) ");
  scanf("%s", &c);
  if (c == 'y' || c == 'Y') {
    *hasNetflix = true;
    printf("Which monthly plan do you have? Here is a list: \n");
    printf("\t 1 for Minimum = 7.99$/month\n");
    printf("\t 2 for Standard = 9.99$/month\n");
    printf("\t 3 for Premium = 11.99/month\n");
    scanf("%d", &netflixPlan);
    if(netflixPlan == 1){
        netflixBill = 7.99;
    }
        else if(netflixPlan == 2){
            netflixBill = 9.99;
        }
            else
                netflixBill = 11.99;
        } else {
    *hasNetflix = false;
    printf("You don't have a Netflix subscription. \n");
  }

  printf("Do you have a subscription to Disney+? (y/n)\n ");
  scanf("%s", &c);
  if (c == 'y' || c == 'Y') {
    *hasDisneyPlus = true;
    disneyBill = 5.99;
    printf("The subscription for Disney+ is 5.99$/month.\n");
  } else {
    *hasDisneyPlus = false;
    printf("You don't have a Disney+ subscription. \n");
  }

  printf("Do you have a subscription to HBO? (y/n)\n ");
  scanf("%s", &c);
  if (c == 'y' || c == 'Y') {
    *hasHBO = true;
    hboBill = 4.99;
    printf("The subscription for HBO is 4.99$/month.\n");
  } else {
    *hasHBO = false;
    *hasHBO = false;
    printf("You don't have a HBO subscription. \n");
  }

  printf("Do you have a subscription to Spotify? (y/n) ");
  scanf("%s", &c);
  if (c == 'y' || c == 'Y') {
    *hasSpotify = true;
    printf("Which monthly plan do you have? Here is a list: \n");
    printf("\t 1 for Premium = 4.99$/month\n");
    printf("\t 2 for Premium for students = 2.49$/month\n");
    scanf("%d", &spotifyPlan);
    if(spotifyPlan == 1)
        spotifyBill = 4.99;
        else
            spotifyBill = 2.49;
  } else {
     printf("You don't have a Spotify subscription. \n");
    *hasSpotify = false;
  }
}

float total_price(struct Subscription subscriptions[], int num_subscriptions, float netflixBill, float disneyBill, float hboBill, float spotifyBill) {
  float total = netflixBill + disneyBill + hboBill + spotifyBill;
  for (int i = 0; i < num_subscriptions; i++) {
    total += subscriptions[i].price;
  }
  return total;
}  

i've tried using pointers(idk if i did it right).我试过使用指针(idk 如果我做对了)。 tried using chatgpt but it does not know what the problem is either.尝试使用 chatgpt 但它也不知道问题出在哪里。

Uninitialised Variable:未初始化的变量:

char c;
while (c != 'y' && c != 'Y' && c != 'n' && c != 'N')

This loop invokes undefined behaviour as c was never initialised.此循环调用未定义的行为,因为c从未被初始化。

Incorrect format specifier:格式说明符不正确:

scanf("%s", &c); 

The call to scanf also invokes Undefined Behaviour, as c has been declared as a char , and the %s format specifier is for strings.scanf的调用还会调用未定义的行为,因为c已声明为char ,并且%s格式说明符用于字符串。

I counted 7 other instances where you made the same mistake.我数了7次你犯同样错误的其他情况。


Once the abstract state machine reaches an undefined state, no further assumption about the continuation of the execution of the program can be made.一旦抽象 state 机器达到未定义的 state,就无法进一步假设程序继续执行。


Variable scope:变量 scope:

The variables defined in main are local to main only. main中定义的变量仅对main是局部的。 You declared another instance of spotifyBill... in askSubcriptionQuestions , these variables are local to askSubcriptionQuestions only.您在askSubcriptionQuestions中声明了spotifyBill...的另一个实例,这些变量askSubcriptionQuestions是本地的。 They're not visible in main , and the variables declared in main aren't visible in other functions.它们在main中不可见,并且在main中声明的变量在其他函数中不可见。

  • Identifiers only have visibility inside their scope, starting at their declarations.标识符仅在其 scope 内部可见,从其声明开始。

  • Objects have a lifetime outside of which they can't be accessed.对象有一个生命周期,超过这个生命周期它们就不能被访问。

  • Referring to an object outside of its lifetime has Undefined Behaviour.在其生命周期之外引用 object 具有未定义的行为。

  • Unless they are VLA or temporary objects, automatic variables have a lifetime corresponding to the execution of their block of defination除非它们是VLA或临时对象,否则自动变量的生命周期与其定义块的执行相对应

If you want to work with the same variables declared in main, you'd have to pass them by reference to other functions.如果要使用在 main 中声明的相同变量,则必须by reference将它们传递给其他函数。 That way, the changes made to those variables will be permanent.这样,对这些变量所做的更改将是永久性的。

Your problem is related with the scope of the variables .您的问题与变量的 scope 有关

Essentially what is happening is that you are using local variables for assigning the values that you want inside the function askSubscriptionQuestions , but when you terminate this function, all the local variables are lost.本质上发生的事情是您使用局部变量在 function askSubscriptionQuestions中分配您想要的值,但是当您终止此 function 时,所有局部变量都将丢失。 Don't be confused because you named them the same way as the variables declared in the main.不要混淆,因为你命名它们的方式与在 main 中声明的变量相同。 That doesn't matter.那没关系。 What matter is the scope of the variables.重要的是变量的 scope。

Once you have declared your netflixBill variable in the main, you need to pass it by-reference, that means, passing the address of the variable instead of the value.在 main 中声明netflixBill变量后,您需要通过引用传递它,这意味着传递变量的地址而不是值。 You do this using "&".您可以使用“&”来执行此操作。 That way, if you properly modify value to which this address points to inside the function, when it finishes you won't loose the value of your variable.这样,如果您正确修改此地址指向 function 内部的值,当它完成时您不会丢失变量的值。

You need to do several changes:您需要做几处更改:

  • Re-write your function so the header includes these variables (to define the arguments as addresses):重写您的 function,以便 header 包含这些变量(将 arguments 定义为地址):

    void askSubscriptionQuestions(..., .netflixBill, *disneyBill, *hboBill, *spotifyBill) void askSubscriptionQuestions(..., .netflixBill, *disneyBill, *hboBill, *spotifyBill)

  • Call your function as (to send the address instead of the value):将您的 function 称为(发送地址而不是值):

    askSubscriptionQuestions(..., .netflixBill, &disneyBill, &hboBill, &spotifyBill) askSubscriptionQuestions(..., .netflixBill, &disneyBill, &hboBill, &spotifyBill)

  • Inside your function, every time you want to change the value of these variables, you need to call the "value" that the address is pointing to.在你的function里面,每次要改变这些变量的值,都需要调用地址指向的“值”。 So, the change would be to add always a "*" before each time you call these variables inside this function. For example:因此,更改是在每次调用此function中的这些变量之前始终添加一个“*”。例如:

    .netflixBill = 7.99; .netflixBill = 7.99;

  • Remove the local declaration that you are doing of the netflixBill variable and similar inside your function.删除您正在对 function 中的netflixBill变量和类似变量所做的本地声明。

I highly recommend you study and understand the concept of passing variables by-reference and by-value to the functions, it is essential coding in C.我强烈建议您学习并理解将变量按引用和按值传递给函数的概念,这是 C 中必不可少的编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM