在不丢失函数之前拥有的数据的情况下调用函数?

Calling a function without losing that data that the function had before?

我很早就染上了全局变量的坏习惯,所以我一直在尝试通过使用局部变量和学习 reference/value 的调用来拉近自己的距离,直到我 运行遇到这样的问题,假设我有一个函数 Menu(),它包含一个主菜单和一个数组,然后从菜单中我会转到一个函数并对数组做一些事情,现在我通常会卡在这里我的函数通常是 void 类型,但通常对于我的程序,我使用 if 选择返回菜单,例如 If(userinput ==2){Menu();} 通常这会导致两个问题 1. 当我进入菜单时,它会重置所有变量值 2.If 我在多个地方都有这个函数,它会开始给我参数错误。

这些问题让我很沮丧,让我倾向于全局变量。

Example:

menu(){
    int array[100];
    functionadd(array);
}

functionadd(array[])
{
    int userinput;
    do{ 
        //lets the just say here the program does things to my array.
        // usually when I want to go back to the menu I'd do something like this
        printf("Again or back to menu?1(Again) or 2(Menu)")
            scanf_s("%d%[^\n]", &userinput); '\n'==getchar();
    } while(userinput == 1)
    if(userinput != 2){Menu();} /*this would bring me back to
        the menu but my array would be back to as its original state
        when it was called in Menu I understand why this happens I
        just need to learn how to counter act it*/
}

一些伪代码没有变量 "reset" with static 关键字:

int Menu(){
    static int remember = 0;
    remember++;
    return remember;
}

int main(){
    printf("remember = %d\n", Menu());
    printf("remember = %d\n", Menu());
    printf("remember = %d", Menu());
}

输出:

记住 = 1

记住 = 2

记住 = 3

注意 全局变量,如 Ron 所说,是程序生命周期内的变量。静态变量也是如此,但在这种情况下,它不能在另一个函数中访问。此外,静态变量并不是真正的线程安全

"All non-local state must be accessed through atomic operations and the data-structures must also be reentrant."

人们不鼓励过度使用全局变量的原因是这些变量将在程序(实际上是进程)的生命周期内占用内存。

但是,在这种特定情况下,这就是您想要的行为。你想记住调用之间菜单的状态,你可以自己实现一个结构并将状态保存在调用函数中,或者你可以简单地全局声明变量。

令人厌烦的是 每个 变量都是全局变量,无论它们是否需要。在像 C 这样的语言中,它基本上只能因为能够以最高效率手动管理内存而得以生存,看到人们浪费它会伤害我们的大脑。通常,看到任何不是常量的全局变量都是一种代码味道。正如一位评论者所指出的,还有 避免使用全局变量的其他原因。我不会遍历所有这些,而是​​将其留在这里:why globals are bad

请注意,我并不是刻薄,只是不确定这些页面中的哪一个是最好的资源,所以我把它们都给了 OP。

编辑:其他几点。您也可以通过传递一个指针来轻松完成您需要的操作,该指针包含您可以在函数中编辑或不可以编辑的值作为参数,但是根据您所说的,我可能会实施的解决方案如下:

int choice = menu(); 
case (choice ):
//logic here

如果你保存一个像static这样的变量,你不会丢失函数之前的数据,因为如果函数和堆栈不被清理,变量不会在最后被销毁.示例:

static int var=0;
var++;
return var;

调用函数10次变量会增加10倍

您应该注意以下几点:

  • 在C语言中,所有参数都使用call by value传递。
  • 当您将数组作为参数传递给函数时,它会衰减为指向数组第一个元素的指针。

Call by value 并不意味着您不能从另一个函数修改某个函数的局部变量。为此,您传递一个指针作为参数,然后从被调用函数将值分配给它的取消引用状态。

例如:

void f(int *c)
{
    *c = 7;
}

int main(void)
{
    int count = 4;
    f(&count);
    printf("%d", count);
    return 0;
}

嗯,你打电话是这样的:

    main()
    {
       menu();
    }

    menu()
    {
       yourfunction();
    }

    yourfunction()
   {
      if(userinput==2)
           menu();
   }

在这里,您可以观察到您再次调用 menu() 但没有 return 返回.. 如果你在 menu() 的深度,如果你退出,将 return 到你的函数()而不是 main()。

我建议您使用类似于以下的代码:

menu()
{

     do
     {
        yourfunction();//call your function
        //after the completion ask to continue
        printf("Do you want to continue? (Y/N) ");
        fflush(stdin);
        scanf(" %c",&choice);
     }while(choice=='y'||choice=='Y');

 }

 void yourfunction()
{
         //do only functional job
}

这将帮助您 return 到 menu() 并要求您继续。 而且这些值将按照您的意愿保留。

编辑:

或者如果你想坚持你的编程习惯。 简单地告诉程序当用户输入为 1(即不等于 2)时要做什么 并且在输入 2 时不要定义任何内容。 它会自动return到menu()

 menu()
    {
       yourfunction();
    }

Yourfunction()
{
  if(userinput==1)
   {
    // do this
   }
}

或其他方式:

 menu()
    {
       yourfunction();
    }
Yourfuntion()
{
  if(userinput!=2)
   {
    //do this
   }
}

如果函数将用户输入设为 2,它将返回到 menu()。

结束..:-)