三道题入门C语言

三道题入门C语言

判断输入天数为当年的第几天

输入一个日期,格式为xxxx-xx-xx,判断这一天为当年的第几天?

输入:2019-1-2

输出:2

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

int main()
/*
用譬如2019-12-31的格式输入日期,返回这是一年的第几天,打印。
为了简洁,对于输入,没有写异常判断,直接用的c抛出的错误。
命名法:下划线命名法。
*/
{
	/*使用安全的strtok_s函数,把字符串中的年份、月份、日提取出来,
	放入数组date中。*/
	//char input[] = "2019-12-31";
	char input[11];//不会超过11位
	gets_s(input, 10);
	const char delim[2] = "-";
	char *date_p;
	char *date_left_p = NULL;
	int date[3];
	int i = 0;
	date_p = strtok_s(input, delim, &date_left_p);
	date[i] = atoi(date_p);
	for (i = 0; i < 2; i++)
	{
		date_p = strtok_s(NULL, delim, &date_left_p);
		date[i + 1] = atoi(date_p);
	}
	//for (i = 0; i < 3; i++)
	//{
	//	printf("%d\n", date[i]);
	//}
	/*因为后面反复用年月日信息,date赋值到变量。*/

	int year = date[0];
	int month = date[1];
	int day = date[2];

	/*为了提高计算速度,把月份天数累加手算出来列这(平年)。*/
	int date_cumsum[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };//每月天数累加
	int output = 0;

	/*计算是第几天。*/
	output = date_cumsum[month - 1];
	output = output + day;

	/*判断是否是闰年,如是,三月份之后的累加天数+1。*/
	if (((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) && month > 2)
	{
		output = output + 1;
	}
	printf("%d", output);
	getchar();
	return 0;
}

在这里插入图片描述

别人的代码(工程级别):

 日期是全年第几天.cpp : 定义控制台应用程序的入口点。



//

#include "stdafx.h"

#include <iostream>

#include <stdio.h>

using namespace std;



struct indata   //定义输入的年月日结构体;

{

unsigned int year;

unsigned int month;

unsigned int date;

};



int main()

{


for (int i = 0; i < 100; i++)        //100次循环输入。

{

//变量定义及初始化

    struct indata indata[1] = { 0, 0, 0 };  

unsigned int yday = 0;



// 日期的输入,格式为年-月-日

reinput:

{

cout << "请输入一个格式为年-月-日的日期:" << endl;         //提示用户输入格式为年-月-日的信息。



键盘输入给年月日变量赋值,并判断日期格式是否正确。正确则应用此赋值;错误则提示"格式错误,请重新输入!" 且变量清零,清除缓冲区。

if (scanf("%d-%d-%d", &indata[1].year, &indata[1].month, &indata[1].date) != 3)  //键盘输入给年月日变量赋值,并判断日期格式是否正确。

{

cout << "格式错误,请重新输入!" << endl;                                  //格式错误则提示重新输入且变量清零。





indata[1] = { 0, 0, 0 };                //变量清零。

yday = 0;                                //变量清零。

_flushall();                            //清除缓冲区。

}



}




判断月份是否正确。正确则应用此赋值;错误则提示  "月份错误,请重新输入!" ,且变量清零,清除缓冲区。

if (indata[1].month > 12)

{

cout << "月份错误,请重新输入!" << endl;



indata[1] = { 0, 0, 0 };                //变量清零。

yday = 0;                                //变量清零。

_flushall();                            //清除缓冲区。



goto reinput;                          //重新输入。

}



//定义平年、闰年每月最大日数组。

unsigned int arrmonthP[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  //平年每月最大日。

unsigned int arrmonthR[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  //闰年每月最大日。








//判断年份是平年还是闰年?闰年2月29天,平年28天。

if ((indata[1].year % 4 == 0 && indata[1].year % 100 != 0) || (indata[1].year % 400 == 0 && indata[1].year % 3200 != 0) || indata[1].year % 172800 == 0)  //判断是否为闰年?

{


//闰年,统计输入天数为当年的第几天。

//cout << indata[1].year << "年是闰年" << endl;


for (unsigned int i = 0; i < indata[1].month; i++)    //i为月份。

{



//判断输入日期是否正确,即日期是否超出当月最大日。如果错误,提示"日期错误,请重新输入!"  ,且变量清零,清除缓冲区;如果正确统计输入天数为当年的第几天。

if (indata[1].date>arrmonthR[indata[1].month])

{

cout << "日期错误,请重新输入!"  << endl;



indata[1] = { 0, 0, 0 };                 //变量清零。

yday = 0;                                //变量清零。

_flushall();                             //清除缓冲区。

goto reinput;                            //重新输入。

}

yday += arrmonthR;                        //统计输入天数为当年的第几天:输入月份前整月天数之和。

}

}

else

{

//平年,统计输入天数为当年的第几天。

//cout << indata[1].year << "年是平年" << endl;

for (unsigned int i = 0; i < indata[1].month; i++)  //i为月份。

{



//判断输入日期是否正确,即日期是否超出当月最大日。如果错误,提示"日期错误,请重新输入!"  ,且变量清零,清除缓冲区;如果正确统计输入天数为当年的第几天。

if (indata[1].date>arrmonthP[indata[1].month])

{

cout <<  "日期错误,请重新输入!"  << endl;



indata[1] = { 0, 0, 0 };                 //变量清零。

yday = 0;                                //变量清零。

_flushall();                             //清除缓冲区。

goto reinput;                            //重新输入。

}

yday += arrmonthP;                         //统计输入天数为当年的第几天:输入月份前整月天数之和。

}

}

yday = yday + indata[1].date;                        //统计输入天数为当年的第几天:整月天数与输入日之和。

cout << indata[1].year << "-" << indata[1].month << "-" << indata[1].date << "是" << indata[1].year << "年的第" << yday << "天" << endl;    //显示结果。


indata[1] = { 0, 0, 0 };                 //变量清零。

yday = 0;                                //变量清零。

_flushall();                             //清除缓冲区。



}

system("pause");

return 0;

}

"水仙花数"判断

输入一个三位数判断是否为"水仙花数",水仙花数指该三位数每个位上的数字立方和等于它本身,即A³+B³+C³=ABC。

输入:153

输出:True

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

int main()
/*
水仙花数作为自幂数的一种特例,本程序很容易就能改为一般自幂数的判断。
程序从键盘读入一个数,判断其是否是水仙花数。
变量命名采用下划线命名法。
*/
{
	int number = 0;//要判断的数
	double number_double = 0;//定义一个double存最原始的数字输入
	scanf_s("%lf", &number_double);//从键盘读入数据
	number = (int)(number_double);
	/*下面一步的操作是为了程序的鲁棒性,防止输入小数等情况的发生,支持字母转成的数字。*/
	if (number_double < 100.0 || number_double >999.0 ||//要介于100到999之间的数
		((number_double - (double)(number))) != 0)//判断为整数才可
	{
		printf("请输入100到999之间的整数!!!\n");
		system("pause");
		return 0;
	}

	int number_tmp = number;
	int rem;
	int digits[10] = { 0 };//int型数据最多能存10位数,这里写10也是为了程序的泛化型,容易改为自幂数判断
	int i = 0;

	/*提取输入的各个位置上的数字,放入数组digits中。*/
	while (1)
	{
		if (number_tmp < 10)
		{
			digits[i] = number_tmp;
			break;
		}
		rem = number_tmp % 10;
		number_tmp = number_tmp / 10;
		digits[i] = rem;
		i = i + 1;
	}

	/*求各个位置上的立方之和。*/
	int sum = 0;
	int n;
	for (n = 0; n <= i; n++)
	{
		int tmp = digits[n];
		sum = sum + (int)(pow(tmp, i + 1));//tmp *tmp * tmp;
	}

	/*判断是否是水仙花数。*/
	if (sum == number)
		printf("True\n");
	else
		printf("False\n");

	system("pause");


	return 0;
}


在这里插入图片描述

别人的代码:

'''

·编程语言python3

·题目介绍:

    输入一个三位数判断是否为"水仙花数",水仙花数指该三位数每个位上的数字立方和等于它本身,即A³+B³+C³=ABC

    输入:153

    输出:Ture

·解题概述:

    水仙花数只是自幂数的一种,严格来说3位数的3次幂数才称为水仙花数。

    为了增加程序的可扩展性,本解法可以计算任意位数的自幂数。

    计算的关键在于获取输入数的每个位上的数字并乘方累加,为了获取每个位上的数字,下面一共采用两种方法。

    一、judge1通过字符串转换的方式获取每个位上的数字。

    二、judge2通过迭代的方式获取每个位上的数字。

    最后对比两种方式的运行时间。

·结论:

    才用方法一通过字符串转换的方式获取每个位上的数字,可以直接运用python的特性进行大数计算,不受int的限制。

    并且运行效率高于方法二,输入可以是任意位数的数字,有较好扩展性。

'''

import time

from functools import wraps



#计算函数运行时间的修饰器

def timefn(fn):

    @wraps(fn)

    def measure_time(*args, **kwargs):

        t1 = time.time()

        result = fn(*args, **kwargs)

        t2 = time.time()

        print(fn.__name__ + " 耗时 " + str(t2 - t1) + " second")

        return result

    return measure_time



#judge1通过字符串转换的方式获取每个位上的数字。

def judge1(num:int):

    s = str(num)    #先将数字转化为字符串

    cal = 0         #累计的每个位上数字的乘方和

    lenght = len(s) #输入数字的位数

    for ch in s:    #通过字符来遍历每个数字

        cal += pow(int(ch), lenght) #把每个位上数字的乘方和累加

    return cal == num   #将结果与原数进行比较



#judge2通过迭代的方式获取每个位上的数字。

def judge2(num:int):

    s = str(num)    # 先将数字转化为字符串

    cal = 0         # 累计的每个位上数字的乘方和

    lenght = len(s)  # 输入数字的位数

    remainder=num   #获取每个位上数字后剩余的数

    for _ in range(lenght): #从个位数开始依次获取每个位上的数字

        pos=remainder%10    #当前位置上的数字

        remainder=int(remainder/10) #获取完当前位置上的数字后剩余数字

        cal += pow(pos, lenght) #把每个位上数字的乘方和累加

    return cal == num #将结果与原数进行比较



#将judge1计算100000次的运行时间

@timefn

def judge1RunningTime(num:int):

    for _ in range(100000):

        judge1(num)

    return judge1(num)



#将judge2计算100000次的运行时间

@timefn

def judge2RunningTime(num:int):

    for _ in range(100000):

        judge2(num)

    return judge2(num)



if __name__=="__main__":

    # print("153是自幂数吗?", judge1(153))

    # print("370是自幂数吗?", judge1(370))

    # print("54748是自幂数吗?", judge1(54748))

    # print("1741725是自幂数吗?", judge1(1741725))

    # print("24678050是自幂数吗?", judge1(24678050))

    # print("1517841543307505039是自幂数吗?", judge1(1517841543307505039))

    # print("27907865009977052567814是自幂数吗?", judge1(27907865009977052567814))

    # print("174088005938065293023722是自幂数吗?", judge1(174088005938065293023722))

    # print("188451485447897896036875是自幂数吗?", judge1(188451485447897896036875))

    # print("*************运行时间比较****************")

    # judge1RunningTime(49388550606)

    # judge2RunningTime(49388550606)

    num=int(input())

    print(judge1(num))


概率计算

一辆客车行驶路线为从A站-B站-C站,小明每天要在B站乘坐客车去C站上学。
客车从A站到达B站的时间服从均值20分钟、标准差2分钟的正态随机分布。请计算小明每天准时赶上客车的概率。

客车早上从A站发车的时刻和概率为:
出发时刻 8:00 8:03 8:05
概率 0.5 0.3 0.2

小明早上到达B站的时刻和概率为:
到站时刻 8:18 8:20 8:22 8:24
概率 0.4 0.3 0.1 0.2

  • MATLAB 程序
p1 = [0.5 0.3 0.2]';
p2 = [0.4 0.3 0.1 0.2]';
P = p1*p2';
t1 = [0 3 5];
t2 = [18 20 22 24];
T = [t2-t1(1);
    t2-t1(2);
    t2-t1(3);
    ];
P_mat = (1-cdf('normal',T,20,2)).*P;
%P_mat2 = qfunc((T-20)./2).*P

output = sum(sum(P_mat));
vpa(output,53)

MATLAB转C可以用MATLAB内置的coder工具箱。流程是:m文件改成函数(可以改成一个不带参的函数)->coder打开工具箱->新建工程、添加m文件->输出类型:C可执行文件,只生成代码->编译。编译之后,codegen的exe文件夹下面的文件就是c文件。

需要注意的是:转C代码的路径,不能有中文路径!!!不能有中文路径!!!不能有中文路径!!!

一般来说,用MATLAB转出来的C文件,可读性不是特别好,变量命名也很奇怪,有一些内置的非开源的MATLAB函数转不成C。什么时候用MATLAB转C呢?当你不在意代码的内容,只care C程序的输入输出接口的时候,你可以去转,并且去调用它。

下面是用C写的一个这道题的答案。不是MATLAB转的。因为我很在意转出来的效果,并且MATLAB的一些内置函数转不出来,这个时候,与其转出来之后再慢慢修改,还不如直接用C写来得便捷。

  • C程序
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//#define N 10000

double norm_cdf(double x, double mu, double sigma)
/*正态分布分布函数的计算函数
x表示密度函数从-inf积到x(即分布函数值),mu是均值,sigma是方差
返回分布函数值
*/
{
	x = (x - mu) / sigma;
	return (1 + erf(x / sqrt(2))) *0.5;
}

/*下面是我原来写的正态分布密度函数和用蒙特卡洛方法求分布函数
(密度函数积分)的程序,但是要达到较高精度,速度很慢,注释掉*/
//double norm(double mu, double sigma)
//{
//	double x, stdnorm, sum = 0.0; int j;
//
//
//	for (j = 1; j <= 12; j++)
//	{
//		sum = sum + rand() / (double)(RAND_MAX);
//	}
//	stdnorm = sum - 6;
//	x = sigma*stdnorm + mu;
//	return x;
//}
//
//double qfunc(double mu, double sigma,double x)
//{
//	int sum = 0; double Q;
//	for (int i = 0; i < N; i++)
//	{
//		if (gauss(mu, sigma) >= x)
//		{
//			sum = sum + 1;
//		}
//	}
//	Q = (double)((double)(sum) / N);
//	return Q;
//}


double main(void)
{
	/*使用动态开辟内存的方式存数组,增加了程序的可扩展性*/
	double pA[] = { 0.5, 0.3, 0.2 };
	double pB[] = { 0.4, 0.3, 0.1, 0.2 };//给定的概率值
	int size_pA = sizeof(pA) / sizeof(double);
	int size_pB = sizeof(pB) / sizeof(double);
	int size_pAB = size_pA*size_pB;
	double* p_AB = (double*)malloc(size_pAB*sizeof(double));
	double p_AB_tmp;

	double tA[] = { 0, 3, 5 };
	double tB[] = { 18, 20, 22, 24 };//给定的时间值
	int size_tA = size_pA;
	int size_tB = size_pB;
	int size_tAB = size_tA*size_tB;
	double* t_AB = (double*)malloc(size_tAB*sizeof(double));
	double t_AB_tmp;

	double std_dev = 2;//标准差
	double mean = 20;//方差

	double* ps_take = (double*)malloc(size_tAB*sizeof(double));//用一维数组,存12种情况,每种情况的联合概率
	double ps_take_tmp;
	double output = 0;

	int ij;
	for (int i = 0; i < size_pA; i++)
	{
		for (int j = 0; j < size_pB; j++)
		{
			ij = i*size_pA + j;
			p_AB_tmp = pA[i] * pB[j];//计算发车时间和小明到达车站时间的联合概率
			p_AB[ij] = p_AB_tmp;

			t_AB_tmp = (tB[j] - tA[i]);//计算每种情况下对应的时间差
			t_AB[ij] = t_AB_tmp;

			// time_t t;
			// srand((unsigned)time(&t));
			// ps_take_tmp = qfunc(mean, std_dev, t_AB_tmp);
			ps_take_tmp = 1 - norm_cdf(t_AB_tmp, mean, std_dev);//计算1-分布函数值,当前情况下能赶上车的概率
			ps_take[ij] = ps_take_tmp;

			output = output + p_AB_tmp*ps_take_tmp;//对12种情况下,每种情况的概率做累积


		}
	}

	printf("%0.17f", output);//打印结果,保留小数点后17位
	getchar();
	return output;
}

在这里插入图片描述

  • 额外赠送:正态分布的分布函数计算程序
#include <math.h>

#define ERF_PI 3.141592653589793
#define ERF_N 100


double erf(double x)erf(x) = the cumulation of { 2/sqrt(pi)*exp(-z*z) } from 0 to x; //error function
{	// 2/sqrt(pi) * { ∑[(-1)^n / n! * x^(2n+1)/(2n+1)] + x }
	double res = x;
	double factorial = 1;	//n!
	double x_pow = x;
	int one = 1, n;
	for( n=1; n<100; n++ ){
		factorial *= n;
		one *= -1;
		x_pow *= x*x;
		res += one / factorial * x_pow / ( 2*n+1 );
	}
	res *= 2 / sqrt(ERF_PI);
	return res;
}

double norm_cdf(double x)//cumulation distribution function of standard normal distribution
{
	return ( 1 + erf( x / sqrt(2) ) ) / 2;
}

该代码采用C语言实现了误差函数erf(),其精度可根据参数ERF_N来调节(默认100),并且由于使用单次循环同时累加和累乘,因而避免了调用pow()函数,使得算法速度更快。该实现采用的是麦克劳林展开方法再逐项求积分。
另外,还包含了标准正态分布函数的计算函数norm_cdf(),该函数调用了erf()函数。

别人的代码:

#!/usr/bin/python3.5

# -*- coding: utf-8 -*-



'''

@author:孙*宇

@time:2019-11-28

@file:178****1790-概率计算-Python语言.py

@算法思想:大数定律

'''



import numpy as np

import random



def pick_rand(time,prob):

    '''

    该函数用于以指定概率抽取到站样本值

    :param time:客车或者小明各个时刻到站的时间(分钟)列表

    :param prob:客车或者小明各个时刻到站的概率列表

    :return:返回指定概率抽取的样本值

    '''

    x = round(random.uniform(0,1),1)

    init_prob = 0

    for item,item_prob in zip(time,prob):

        init_prob += item_prob

        if x < init_prob:

            break

    return item



def prob_get(n,mean,std,bus_time,bus_prob,person_time,person_prob):

    '''

    算法思想:大数定律

    一辆客车行驶路线为从A站-B站-C站,小明每天要在B站乘坐客车去C站上学。

    客车从A站到达B站的时间服从均值20分钟、标准差2分钟的正态随机分布。

    计算小明每天准时赶上客车的概率。

    :param n: 抽取样本的次数

    :param mean: 假设样本服从正态分布下的均值

    :param std: 假设样本服从正态分布下的标准差

    :param bus_time: list 客车到达时间点(分钟)

    :param bus_prob: list 客车到达概率

    :param person_time: list 小明到达时间点(分钟)

    :param person_prob: list 小明到达概率

    :return: 小明准时赶上客车的概率

    '''

    m = 0

    for i in range(1,n):

        x = np.random.normal(loc=20, scale=2, size=1)  # 均值mean,标准差std,数量

        #随机抽取客车和小明达到时间点

        bus_sample = pick_rand(bus_time,bus_prob)

        person_sample = pick_rand(person_time,person_prob)

        #判断小明是否满足准时达到条件

        if x + bus_sample >= person_sample:

            m += 1

    return m/n



if __name__ == '__main__':

    #考虑在大量样本下,服从正态分布,抽取样本30000次(可以更高)

    n = 30000

    mean = 20  #样本在正态分布下的均值

    std = 2    #样本在正态分布下的标准差

    bus_time = [0, 3, 5] #客车到达时间点(分钟)

    bus_prob = [0.5, 0.3, 0.2] #客车到达概率

    person_time = [18, 20, 22, 24] #小明到达时间点(分钟)

    person_prob = [0.4, 0.3, 0.1, 0.2] #小明到达概率

    # 调用函数

    arrive_prob = round(prob_get(n,mean,std,bus_time,bus_prob,person_time,person_prob)+0.009,2)

    #输出小明准时赶上火车的概率

    print(arrive_prob)


©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页