c语言函数,求和?!

请问这个程序的运行结果为什么是8 17啊,不应该是8 11吗?

#include<stdio.h>
int func (int ,int);
int main ( )
{    int k=4,m=1,p1,p2;
    p1=func(k,m) ; //i=2+0+1=3;m=3+4+1=8;返回m=8 给p1 
    p2=func(k,m) ;//i=2+0+1=3;m=3+4+8
    printf("%d,%d\n",p1,p2) ;
    return 0;
}
int func (int a,int b)
{   static int m=0,i=2;
    i+=m+1;
    m=i+a+b;
    return (m);
}




第一次
func(4,1)
i=2,i=2+0+1=3,m=3+4+1=8
第二次
func(4,1)
i=3+8+1=12,m=12+4+1=17
所以是8 17
注意static的变量的用法

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7605993
  • 这篇博客也不错, 你可以看下【C语言】判断一个大整数能否被11整除,可以通过以下方法:将该数的十进制表示从右端开始,每两位一组构成一个整数,然后将这些数累加,判断其和能否被11整除。
  • 除此之外, 这篇博客: C语言实现可写入文件的账号密码登录系统,密码输入时掩盖,登录界面菜单选择,更改密码系统,课设必备。中的 7.完整代码!!!!! 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • //引头文件
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <windows.h>
    
    //定义宏常量
    #define MAX_ID 11
    #define MAX_PWD 20
    #define MAX_NAME 15
    #define MAX_SEX 5
    #define MAX_PHONE 12
    
    
    //创建用户的结构体
    typedef struct Users
    {
    	char id[MAX_ID];
    	char pwd[MAX_PWD];
    	char name[MAX_NAME];
    	char sex[MAX_SEX];
    	char phone[MAX_PHONE];
    }Users;
    
    
    
    //声明函数
    
    //打印菜单
    void menu();
    
    //用户注册
    void Register();
    
    //登录
    void Login();
    
    //找回密码
    void Reback();
    
    //定位光标
    void gotoxy();
    
    //获取x的位置
    int posx();
    
    //获取y的位置
    int posy();
    
    //密码输入(含掩盖功能)
    void Getpwd(char* pwd);
    
    int main()//主函数
    {
    	char input;
    	do
    	{
    		menu();
    		setbuf(stdin, NULL);
    		input = getchar();
    		switch (input)
    		{
    		case '1':
    			Register();
    			break;
    		case '2':
    			Login();
    			break;
    		case '3':
    			Reback();
    			break;
    		case '0':
    			printf("退出成功!\n");
    			break;
    		default:
    			printf("选择错误,请重新选择!\n");
    			break;
    		}
    	} while (input!='0');
    }
    
    //打印菜单
    void menu()
    {
    	printf("************************************\n");
    	printf("************************************\n");
    	printf("*****1.Register         2.Login*****\n");
    	printf("*****3.Reback           0.exit *****\n");
    	printf("************************************\n");
    	printf("************************************\n");
    }
     
    //注册系统
    void Register()
    {
    	Users a, b;//创建用户结构体临时变量,a是用来接收用户输入的,b是用来从文件中读取的,来和a作比较
    
    	char tmp[20]="";//用着下面判断的
    
    	printf("欢迎来到注册界面!\n");
    	FILE* pf = fopen("users.dat", "rb");//"rb"是以二进制只读方式打开文件的意思
    	fread(&b, sizeof(Users), 1, pf);//将数据读入b中
    	if (!pf)//如果打开失败
    	{
    		printf("%s", strerror(errno));//errno可以理解是报的错误对应的编号,strerror可以把这个编号翻译出来,输出在屏幕上
    		return;
    	}
    	Sleep(800);
    
    	printf("请输入您的账号>>");
    	scanf("%s", a.id);
    	while (1)
    	{
    		if (strcmp(a.id, b.id))//两个用户名不相等
    		{
    			if (!feof(pf))//没读到文件末尾
    			{
    				fread(&b, sizeof(Users), 1, pf);//继续读取文件中的用户到b中
    			}
    			else//读到文件末尾了,确认没有重复的id
    			{
    				break;
    			}
    		}
    		else//有两个用户名相等
    		{
    			printf("此用户名已存在在,请重新输入!\n");
    			Sleep(1000);
    			fclose(pf);//关闭文件
    			pf = NULL;//pf置空,避免野指针
    			return;
    		}
    	}
    	printf("请输入您的姓名>>");
    	scanf("%s", a.name);
    	printf("请输入您的性别>>");
    	scanf("%s", a.sex);
    	printf("请输入您的电话号码>>");
    	scanf("%s", a.phone);
    	printf("请输入您的密码>>");
    	Getpwd(a.pwd);//输入密码的函数,有掩盖功能,下面会介绍
    	printf("\n请再次确认您的密码>>");
    	Getpwd(tmp);
    	do
    	{
    		if (!strcmp(a.pwd, tmp))//两次密码相等
    		{
    			pf = fopen("users.dat", "ab");
    			fwrite(&a, sizeof(Users), 1, pf);
    			printf("\n账号注册成功,请登录!\n");
    			Sleep(500);
    			fclose(pf);
    			pf = NULL;
    			return;
    		}
    		else
    		{
    			printf("\n两次密码不匹配!请重新输入>>");
    			Getpwd(a.pwd);
    			printf("\n请再次确认>>");
    			Getpwd(tmp);
    		}
    	} while (1);
    }
    
    //登录系统
    void Login()
    {
    	Users a, b;//同理,a是用来给用户输入的,b是用来是水的(从文件中读取到b中,用b和a匹配比较)
    
    	FILE* pf = fopen("users.dat", "rb");//以只读的方式打开文件
    	if (!pf)//如果读取失败
    	{
    		printf("%s\n", strerror(errno));//上面有讲过~
    		return;
    	}
    	printf("欢迎来到登录界面!\n");
    	Sleep(1000);
    
    	fread(&b, sizeof(Users), 1, pf);//先从文件中读取一个用户试试水
    
    	printf("请输入账号>>");
    	scanf("%s", a.id);
    
    	while (1)
    	{
    		if (!strcmp(a.id, b.id))//在文件中找到了与用户输入相同的id
    		{
    			break;
    		}
    		else
    		{
    			if (!feof(pf))//没读到文件末尾,继续读取文件中的id到b中
    			{
    				fread(&b, sizeof(Users), 1, pf);//继续从文件中读取用户信息进b,直到在文件中找到一个和a的信息相同的
    			}
    			else//读到文件末尾了,没有找到与用户输入相同的账号
    			{
    				printf("此账号不存在!请重新输入!\n");
    				Sleep(500);
    				fclose(pf);
    				pf = NULL;
    				return;
    			}
    		}
    	}
    	do
    	{
    		printf("请输入密码>>");
    		Getpwd(a.pwd);//获取密码,在下面会讲
    		if (!strcmp(a.pwd, b.pwd))//输入的密码与文件中的相同
    		{
    			printf("\n登录成功!欢迎使用!\n");
    			Sleep(500);
    			fclose(pf);//用完当然要把文件关啦
    			pf = NULL;//置空,避免野指针
    			return;
    		}
    		else
    		{
    			printf("\n密码输入错误,请重新输入\n");
    		}
    	} while (strcmp(a.pwd, b.pwd));
    }
    
    //找回密码
    void Reback()
    {
    	char tmp[20] = "";//密码匹配用的
    	Users a, b;
    
    	FILE* pf = fopen("users.dat", "rb+");//"rb+"是为了读和写以二进制打开文件的意思
    
    	if (!pf)//老样子,先判断能不能顺利打开
    	{
    		printf("%s", strerror(errno));
    		return;
    	}
    
    	fread(&b, sizeof(Users), 1, pf);//照样,读一个试试水
    
    	printf("请输入您的账号>>");
    	Sleep(800);
    
    	scanf("%s", a.id);
    
    	while (1)//在文件中找到与用户输入相同的id
    	{
    		if (!strcmp(a.id, b.id))//如果读取到了相同的id(在文件中找到了和用户输入一样的)
    		{
    			break;
    		}
    		else
    		{
    			if (!feof(pf))//没读到文件尾,继续读
    			{
    				fread(&b, sizeof(Users), 1, pf);
    			}
    			else
    			{
    				printf("您输入的账号不存在!请重新输入!\n");
    				Sleep(500);
    				fclose(pf);
    				pf = NULL;
    				break;
    			}
    		}
    	}
    
    	//下面是信息匹配验证
    	do//匹配姓名
    	{
    		printf("请输入您的姓名>>");
    		scanf("%s", a.name);
    		if (!strcmp(a.name, b.name))
    		{
    			break;
    		}
    		else
    		{
    			printf("输入错误,请重新输入!\n");
    		}
    	} while (strcmp(a.name, b.name));
    
    	do//匹配性别
    	{
    		printf("请输入您的性别>>");
    		scanf("%s", a.sex);
    		if (!strcmp(a.sex, b.sex))
    		{
    			break;
    		}
    		else
    		{
    			printf("输入错误,请重新输入!\n");
    		}
    	} while (strcmp(a.sex, b.sex));
    	do//匹配电话号码
    	{
    		printf("请输入您的电话号码>>");
    		scanf("%s", a.phone);
    		if (!strcmp(a.phone, b.phone))
    		{
    			break;
    		}
    		else
    		{
    			printf("输入错误,请重新输入!\n");
    		}
    	} while (strcmp(a.phone, b.phone));
    
    	//更改密码
    	printf("验证成功!请修改您的密码!\n");
    	printf("请输入您的密码>>");
    	Getpwd(a.id);
    	printf("请再次确认您的密码>>");
    	Getpwd(tmp);
    	if (!pf)
    	{
    		printf("%s", strerror(errno));
    		return;
    	}
        //将原来的密码覆盖掉
    	do
    	{
    		if (!strcmp(a.pwd, tmp))//两次密码相等
    		{
    			fseek(pf,-((int)(sizeof(Users)-MAX_ID)), SEEK_CUR);//将文件流调回到要修改的密码的位置
    			fprintf(pf, "%s", a.pwd);//覆盖原来的密码
    			printf("密码修改成功,请登录!\n");
    			Sleep(500);
    			fclose(pf);
    			pf = NULL;
    			return;
    		}
    		else
    		{
    			printf("两次密码不匹配!请重新输入>>");
    			scanf("%s", a.pwd);
    			printf("请再次确认>>");
    			scanf("%s", tmp);
    		}
    	} while (1);
    }
    
    //定位光标
    void gotoxy(int x, int y)
    {
    	//更新光标位置
    	COORD pos;
    	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle是一个Windows API函数。
    	pos.X = x;
    	pos.Y = y;
    	SetConsoleCursorPosition(hOutput, pos);
    }
    //获取光标x坐标
    int posx()
    {
    	CONSOLE_SCREEN_BUFFER_INFO ptr;
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
    	return (ptr.dwCursorPosition.X);
    }
    //获取光标y坐标
    int posy()
    {
    	CONSOLE_SCREEN_BUFFER_INFO ptr;
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
    	return (ptr.dwCursorPosition.Y);
    }
    
    //输入密码
    void Getpwd(char* pwd)
    {
    	int i = 0;
    	int x, y;
    	while (1)
    	{
    		pwd[i] = getch();//获取单个密码(字符)
    		if (pwd[i] == VK_BACK && i >= 0)//如果输入的是回退键,VK_BACK是键盘的键值,ASCII码值为8
    		{
    			if (i > 0)//i>0说明有输入东西了,则回退前一格
    			{
    				i--;
    				x = posx() - 1;//定位x并回退一格
    				y = posy();//定位y
    				gotoxy(x, y);//定位光标
    				printf(" ");//将*用空格掩盖
    				x = posx() - 1;//再次回退,下次输入时光标才会显示在正确的位置
    				y = posy();//定位y
    				gotoxy(x, y);
    				continue;//然后跳过此次循环
    			}
    			else if (i == 0)//i==0说明没输入东西,直接跳过此次循环即可
    			{
    				continue;
    			}
    		}
    		if (i >= 0 && pwd[i] != VK_RETURN && pwd[i] != VK_BACK)//输入东西了
    		{
    			x = posx();
    			y = posy();
    			gotoxy(x, y);
    			printf("*");
    		}
    		if (i == 0 && pwd[i] == VK_RETURN)//如果没输入东西直接按回车,直接跳过此次循环,避免程序把回车当密码了
    		{
    			continue;
    		}
    		if (pwd[i] == VK_RETURN||i==MAX_PWD-2)//输入回车了或者到上限了
    		{
    			i++;
    			pwd[i] = '\0';//结尾放'\0'
    			break;
    		}
    		i++;
    	}
    }

  • 您还可以看一下 黄强老师的30分钟彻底学会C语言指针视频教程课程中的 指针玩转一维数组小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    问题的具体原因是代码中对数组元素的初始化操作有误,导致数组中的元素并非想要的值。具体地,代码中使用指针变量 p 进行倒序遍历数组 a,对数组元素执行赋值操作,但是循环变量 p 开始时指向数组后面的位置,导致第一个被赋值的数组元素并非 a[0],而是一个随机地址中的数据,因此程序输出的结果与期望值不同。

    解决该问题的具体方案为修改遍历数组的起始位置,使其始于数组的最后一个元素,然后循环递减指针变量,对当前元素执行赋值操作即可。具体代码如下:

    float collect(float s, float t, int n, float (*p)(float x))
    {
        float result = 0;
        float step = (t-s)/n;
        float x = s;
        for(int i=0; i<n; i++){
            result += (*p)(x);
            x += step;
        }
        return result*step;
    }
    
    // 调用 collect 函数
    float a = collect(0, 1.0, 2, fun1);
    float b = collect(0, 1.0, 4, fun2);
    float c = collect(0, 1.0, 10, fun3);
    float d = collect(0, 2.0, 100, fun4);
    
    // 修改数组初始化代码
    float a[5] = {0};
    float *p;
    for (p = &a[4]; p >= &a[0]; p--){
        *p = 0;
    }
    

    在以上代码中,collect 函数的实现逻辑与之前相同,只是稍作修改,去掉了对循环变量 p 的自减操作,而是改为递减操作,同时循环起始位置也改成了数组的最后一个元素。

    对于数组初始化操作,我们同样使用指针进行倒序遍历,但是起始位置改为数组的最后一个元素,循环条件是指针变量大于等于数组首元素的地址,循环递减即可。最终输出结果符合期望值。