C enhance Day(二)

本文深入探讨C语言中的指针概念,包括指针变量与内存管理,防止头文件重复包含技巧,以及指针在函数参数中的应用。同时,详细解析字符串初始化、拷贝、搜索和处理技巧,提供实用代码示例。

一. 回顾

1.1 变量

在这里插入图片描述

1.2 内存四区

  • 变量三要素里的作用域指的是,它是全局变量还是局部变量。
  • 变量的生命周期结合内存四区来看。

在这里插入图片描述

1.3 函数调用模型

  • 理清程序各个函数运行流程(压栈弹栈,入栈出栈,先进后出)

1.4 指针也是一种数据类型

在这里插入图片描述

1.5 void *在使用的时候要转化成它实质的类型

在这里插入图片描述

1.6 防止头文件重复包含

  • #pragma once
    这个是防止头文件重复包含,或者交叉重复包含,比如a.h里面展开了b.h,然后b.h里面又展开了a.h,这样就交叉重复包含了,为了防止报错加入#pragma once,这个时候如果a.h里面展开过b.h,下一次就不会再继续展开了。

1.7 兼容C++编译器

  • 这种情况应用于我在.c的文件里封装好的接口函数,想要在.cpp文件里使用,而不用逐个把.c结尾的文件换成.cpp结尾的文件。如下,在主函数里调用socketclient.c里的某个函数,不做兼容C++编译器的处理的时候编译就会报错,所以兼容C++编译器的处理就是为了兼容C代码在C++编译器里运行的时候不用再做修改:

在这里插入图片描述

1.8 上一节作业的结构图

在这里插入图片描述

二. 指针强化

2.1 指针变量和它指向的内存块的区别

如定义:char *p = "abcde"

  • 如果以%s打印表示,把p所指向的内存空间的内容打印出来,操作的是它指向的内存,只是刚好它是字符串
  • 如果以%d打印表示,打印的是这个指针变量的值

代码测试:
在这里插入图片描述
代码分析,这里p是一个指针变量,我们将它加一之后指向的是字符数组的第二个字符,它本身所指向的内存的内容是没有改变的。

运行结果如下:
在这里插入图片描述
结构图如下:
在这里插入图片描述

2.2 写内存时,先确保内存可写

<1> 运行以下代码会报错,因为buf存在文字常量区,内存不可修改

char * buf = "asafadfadsgadsga";
buf[2] = '1';

< 2 > 对比之下,如下代码是可以运行,可修改的,因为这里的buf1在栈区开辟了一片连续空间,是把文字常量区里的字符串内容拷贝了一份放在buf1里

char buf1[] = "ssdfsdgsdg";
buf1[1] = 'a';

2.3 小概念

  • 指针步长(p++):根据所指内存空间的数据类型来确定
  • 不允许向NULL和非法地址拷贝内存

2.4 改变指针指向(对2.1的补充)

这里的流程是现在栈区定义了指针变量q,赋值为NULL,然后在堆区分配了100个字节大小的空间,此时这个空间里面是没有内容的,然后将这个空间的首地址返回给指针变量q保存,运行到strcpy(q,"abcdefg")时,才将文字常量区里的字符串拷贝到q所指向的堆区空间里。
在这里插入图片描述
结构图如下:
在这里插入图片描述
自己写的验证代码如下所示:

int main(int argc, char **argv)
{
	char* q = NULL;
	q = (char*)malloc(100 * sizeof(char));
	
	//判断一下是否动态分配能存成功
	if (q == NULL)
	{
		return -1;
	}

	strcpy(q, "asdfsadf");
	printf("%s\n", q);
}

但是初次写这个代码时犯了如下的错误,这种赋值方式是不对的,错误代码如下:

	char* p = (char *)malloc(100 * sizeof(char));
	*p = "adsadfa"; //字符串这样赋值可不行,必须得用strcpy的形式
	printf("%s\n", p);

但是以下代码又是正确的,画一个内存四区图就能理解,这里虽然开辟了一段堆区内存,但是没有用它,本来p是指向堆区内存的,但是我下面的给指针变量赋值又把存在于文字常量区的字符串的首地址给了p,现在的p是指向文字常量区的这段字符串的,代码如下:

	char* p = (char *)malloc(100 * sizeof(char));
	p = "adsadfa"; 
	printf("%s\n", p);

2.5 指针做参数的输入输出特性

< 1 > 输入
主调函数分配内存,此处的buf作为函数的参数,主调函数已经给buf分配过内存了
在这里插入图片描述
< 2 > 输出
被调函数分配内存,需要传递地址

void fun3(char **p,int *len)
{
	if(p == NULL)
	{
		return; //这里return什么都不加表示退出函数,如果满足p == NULL就退出函数
	}

	char * tmp = (char *)malloc(100);
	if(tmp == NULL) //验证有没有成功在堆区分配到内存,如果没有分配到返回的是NULL,也退出函数
	{
		return;
	}
	strcpy(tmp, "agdsgdsg");
	
	//间接赋值
	*p = tmp;
	*len = strlen(tmp);
}

int main(void)
{
	char *p = NULL;
	int len = 0;
	fun3(&p, &len);
	if(p != NULL)
	{
		printf("p = %s, len = %d\n",p,len);
	}
}

结构图如下:
在这里插入图片描述

三. 字符串

3.1 字符串初始化

  • C语言没有字符串类型,通过字符数组模拟
  • C语言字符串,以字符’\0’,数字0

在这里插入图片描述

  • 字符0是一个字符,有对应的ASCII码,它和数字0以及’\0’不同
    在这里插入图片描述
  • sizeof()strlen()
    在这里插入图片描述
  • 为了确保定义的数组最后内存会被释放,所以数组名是一个常量,因为它是一个常量,且定义了数组之后大小是确定的,根据这个常量以及数组的大小,系统知道结束后释放多大的内存。

3.2 字符串拷贝

< 1 > 未封装成函数

以下为课上较标准的方式写的:

在这里插入图片描述
以下是我自己写的实现字符串拷贝函数,贼特么笨,在这里我刚开始初始化目的字符串的这种方式char dst[] = { 0 };是不可取的,因为这样赋值的话,这个数组的大小是只能容纳一个元素,在后面就会出现数组越界的情况,不要这么干。同时这里的目的字符串初始化char dst[100];没有初始化值是因为如果初始化为0,最后面就不想要我们自己在目的字符串里补结束符0,我们这里是为了学习,提醒自己后面要补上一个结束符:

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

int main(int argc, char** argv)
{
	char src[] = { "asdfasdfa" };
	//char dst[] = { 0 };  //目的字符串这样初始化可不行
	char dst[100];
	char* p = NULL;
	p = src;
	int i = 0;
	int n = 0;

	while (*p != '\0')
	{
		dst[i] = *p;
		i++;
		p++;
	}
	n = strlen(src);
	dst[n] = '\0';
	printf("%s", dst);
	printf("\n");
	return 0;
}

< 2 > 封装成函数

  • 形式1,操作下标
    在这里插入图片描述
  • 形式2,操作指针
    在这里插入图片描述
  • 形式3,比形式2更高级,别这么写,有点难看懂的
    在这里插入图片描述
  • 形式4,更骚的版本,别这么写,有点难看懂的
    在这里插入图片描述
  • 形式5,行业标杆的写法
  1. 加入了判断位,防止形参指针输入为NULL而直接造成程序报错
  2. 最好不要直接使用形参,对其修改等操作,找个变量存取它,此处定义了char *to = dstchar *from = src保证了传进来的形参不会被改变
// 成功为0,失败非0
int my_strcpy4(char *dst, char *src)
{
	if(dst == NULL || src == NULL)
	{
		return -1;
	}
	//辅助变量把形参接过来
	char *to = dst;
	char *from = src;

	// *dst = *src
	// dst++, src++
	//判断 *dst是否为0,为0跳出循环
	while(*to++ = *from++)
	{
		NULL;
	}

	//此时若打印dst,因为地址已经指向'\0'了,打印不出来任何东西,所以传参的时候不要直接使用形参
	//printf("my_strcpy4: dst = %s\n",dst)
	return 0;
}

int main(void)
{
	char src[] = "asadsfafsad";
	char dst[100] = { 0 };
	int ret = 0;
	
	ret = my_strcpy4(dst, src);

	//此时传给函数NULL,程序不会崩
	if(ret != 0)
	{
		printf("my_strcpy4 err:%d\n", ret);
		return ret; // 能够进入这里表示,此时程序已经报错了,这里return让程序结束掉,不会再运行下面的打印字符串的程序了
	}
	printf("%s\n",dst);

	return 0;
}

3.3 strstr中的while和do while模型

< 1 > do-while

int main(void)
{
	char *p = "11abcd111122abcd3333322abcd3333322qqq";
	int n = 0;

	do
	{
		p = strstr(p,"abcd");
		if(p != NULL)
		{
			n++; //累计个数

			//重新设置查找的起点
			p = p + strlen("abcd");
		}
		else //如果没有匹配的字符串,跳出循环
		{
			break;
		}
	}while(*p != 0); //如果没有到结尾

	printf("n = %d\n", n);
	return 0;
}

< 2 > while

int main(void)
{
	char *p = "11abcd111122abcd3333322abcd3333322qqq";
	int n = 0;

	while((p = strstr(p, "abcd")) != NULL)
	{
		//能进来,肯定有匹配的子串

		//重新设置起点位置
		p = p + strlen("abcd");
		n++;

		if(*p == 0) //如果到结束符
		{
			break;
		}
	}

	printf("n = %d\n", n);
	return 0;
}

< 3 > 封装函数

int my_strstr(char *p,int *n)
{
	//辅助变量
	int i = 0;
	char *tmp = p;
	
	while((tmp = strstr(tmp, "abcd")) != NULL)
	{
		//能进来,肯定有匹配的子串

		//重新设置起点位置
		tmp = tmp + strlen("abcd");
		i++;

		if(*tmp == 0) //如果到结束符
		{
			break;
		}
	}
	
	//间接复制
	*n = i;

	return 0;
}
int main(void)
{
	char *p = "11abcd111122abcd3333322abcd3333322qqq";
	int n = 0;
	int ret = 0;

	//通过形参修改实参,需要传地址
	ret = my_strstr(p, &n);
	if(ret != 0)
	{
		return ret;
	}
	printf("n = %d",n);

	return 0;
}

3.4 两头堵模型

< 1 > 未封装函数型

在这里插入图片描述

< 2 > 封装函数型

因为这里没有改变首地址,所以写进函数的时候可以不用找个变量存取字符串的首地址,记得与上面的区分开。

int fun(char *p, int *n)
{
	if(p = NULL || n == NULL)
	{
		return -1;
	}
	int begin = 0;
	int end = strlen(p) - 1;

	//从左边开始
	//如果当前字符为空,而且没有结束
	while(p[begin] == ' ' && p[begin] != 0)
	{
		begin++; //位置从右移动一位
	}

	//如果当前字符为空,而且没有结束
	while(p[end] == ' ' && p[end] != 0)
	{
		edn--; //往左移动一位
	}	

	*n = end - begin + 1;
	
	return 0;
}

int main(void)
{
	char *p = "       abcdefg        ";
	int ret = 0;
	int n = 0;

	ret = fun(p, &n);
	if(ret != 0)
	{
		return ret;
	}

	printf("n = %d\n", n);
	
	return 0;
}

3.5 两头堵模型强化

int fun(char *p, int *n)
{
	if(p = NULL || n == NULL)
	{
		return -1;
	}
	int begin = 0;
	int end = strlen(p) - 1;
	int n = 0;

	//从左边开始
	//如果当前字符为空,而且没有结束
	while(p[begin] == ' ' && p[begin] != 0)
	{
		begin++; //位置从右移动一位
	}

	//如果当前字符为空,而且没有结束
	while(p[end] == ' ' && p[end] != 0)
	{
		edn--; //往左移动一位
	}	
	n = end - begin + 1;

	strncpy(buf, p + begin, n);
	buf[n] = 0;

	return 0;
}

int main(void)
{
	char *p = "       abcdefg        ";
	int ret = 0;
	char buf[100] = {0};

	ret = fun2(p, buf);
	if(ret != 0)
	{
		return ret;
	}
	printf("buf = %s",buf);

	return 0;
}

四. 思考题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Group Assignment - Case Study BACKGROUND BeachBoys BikeShare is a bike share service provider where users can take and return bikes at any of the 70 sta�ons on their network. The company wants to leverage their data to beter understand and, hopefully, op�mize their opera�ons. BikeShare has decided to start by harnessing analy�cs to enhance opera�ons in the logis�cs department, by improving the redistribu�on of bikes between sta�ons to meet demand, and ensuring that there are bikes and return docks available when and where users need them. As a key step towards tackling this challenge, management has tasked you to develop a model capable of predic�ng the net rate of bike ren�ng for a given sta�on, which is defined as the number of bikes returned to, minus the number of bikes taken from, the given sta�on in a given hour. In other words, your model should enable BikeShare's logis�cs team to make the statement - "In the next hour, the quan�ty of bikes at sta�on A will change by X”. In addi�on, management would also like you to: • Help them understand the factors that affect bike rental, which could inform future decisions on where to locate BikeShare's sta�ons. • Help them conceptualize how your predic�on may be used to improve the redistribu�on of bikes within the network. • Highlight any assump�ons or drawbacks of the analysis, if any, and suggest how they may be verified or addressed in the future. ASSIGNMENT Explore, transform, and visualize the given data as appropriate, before using it to train and evaluate an appropriate ML model for the problem. Address the issues highlighted by management as described above, albeit in a less in-depth manner. Finally, ar�culate your findings and recommenda�ons in a concise, coherent, and professional manner, making reference to any earlier results or diagrams as appropriate to support your conclusions. Please use Python to complete this task, using any libraries you might deem necessary for your analysis, e.g., pandas, sklearn, etc. Detail your code, analysis findings, and recommenda�ons clearly in a reproducible Jupyter notebook with appropriate comments and documenta�on, so that an individual viewing the notebook will be able to follow through your steps and understand the reasoning involved and inferences made. DELIVERABLES You should upload the following deliverables in a .zip file: • A Jupyter notebook detailing your analysis and findings for this project, • A PDF-ed copy of the Jupyter notebook above, which should not exceed 30 pages, • The datasets used in your analysis, which should be loaded into your notebook, • Addi�onal files relevant to your analysis, which should be described in your notebook. Finally, please prepare presenta�on slides for the group presenta�on (10-15 mins). All team members need to present in English. THE DATA The company has collected informa�on on the sta�ons, trips taken, and on weather condi�ons in each of the ci�es from September 2014 to August 2015. You can find the data here - bikes_data.zip (3.1 MB). Below, you will also find detailed informa�on on all the fields available in the dataset. The way you include this informa�on in your model is up to you and should be clearly jus�fied and documented in your report. You are free to use any other data sources provided you specify a link to this informa�on in your report. Sta�on Data • ld: sta�on ID number • Name: name of sta�on • Lat: la�tude • Long: longitude • Dock Count: number of total docks at sta�on • City: one of San Francisco, Redwood City, Palo Alto, Mountain View, or San Jose Please note that during the period covered by the dataset, several sta�ons were moved. Sta�ons 23, 25, 49, 69, and 72 became respec�vely sta�ons 85, 86, 87, 88, 89 (which in turn became 90 a�er a second move). Trip Data • Trip ld: numeric ID of bike trip • Dura�on: �me of trip in seconds • Start Date: start date of trip with date and �me, in Pacific Standard Time • Start Sta�on: sta�on id of start sta�on • Start Terminal: numeric reference for start sta�on • End Date: end date of trip with date and �me, in Pacific Standard Time • End Sta�on: sta�on id for end sta�on • Subscrip�on Type: Subscriber (annual or 30-day member) or Customer (24hour or 3-day member) Weather Data • Date: day for which the weather is being reported • Temperature (day min, mean and max): in F • Dew point (day min, mean and max): Temperature in F below which dew can form • Humidity (day min, mean and max): in % • Pressure (day min, mean and max): Atmospheric pressure at sea level in inches of mercury • Visibility (day min, mean and max): distance in miles • Wind Speed (day max and mean): in mph • Max Gust Speed: in mph • Precipita�on: total amount of precipita�ons in inches • Cloud Cover: scale of 0 (clear) tons (totally covered) • Events: Special meteorological events • Wind Direc�on: in degrees • Zip: area code for San Francisco (94107), Redwood City (94063), Palo Alto (94301), Mountain View (94041), and San Jose (95113)
08-07
这是一个非常典型的机器学习项目,目标是预测自行车租赁的净变化,并分析影响因素。以下是该项目的步骤概述和一个基本的代码框架。 ### 步骤概述 1. **数据加载**:加载并合并三个数据集(站点、骑行、天气)。 2. **数据预处理**:清理缺失值、转换时间字段、特征工程等。 3. **可视化**:探索数据分布和关系。 4. **模型训练**:选择适当的回归模型(如线性回归、随机森林等)进行训练。 5. **结果分析**:解释模型结果,识别影响因素。 6. **报告撰写**:总结发现和建议。 ### 代码框架 ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score # 加载数据 stations = pd.read_csv('stations.csv') trips = pd.read_csv('trips.csv') weather = pd.read_csv('weather.csv') # 数据预处理 # 转换时间字段为datetime格式 trips['Start Date'] = pd.to_datetime(trips['Start Date']) trips['End Date'] = pd.to_datetime(trips['End Date']) # 提取小时信息 trips['Start Hour'] = trips['Start Date'].dt.hour trips['End Hour'] = trips['End Date'].dt.hour # 计算每个站点每小时的净变化 hourly_changes = trips.groupby(['Start Station', 'Start Hour']).size().reset_index(name='Outflows') hourly_returns = trips.groupby(['End Station', 'End Hour']).size().reset_index(name='Inflows') # 合并出库和入库数据 net_changes = hourly_changes.merge(hourly_returns, how='outer', left_on=['Start Station', 'Start Hour'], right_on=['End Station', 'End Hour']) net_changes['Net Change'] = net_changes['Inflows'] - net_changes['Outflows'] net_changes.dropna(subset=['Net Change'], inplace=True) # 特征工程 # 将站点ID与站点数据合并 net_changes = net_changes.merge(stations[['id', 'Lat', 'Long', 'Dock Count', 'City']], how='left', left_on='Start Station', right_on='id') # 将天气数据按日期和城市合并 weather['Date'] = pd.to_datetime(weather['Date']) weather.set_index('Date', inplace=True) net_changes['Start Date'] = net_changes['Start Hour'].apply(lambda x: pd.Timestamp(f'2014-09-01 {x}:00')) # 假设日期固定 net_changes.set_index('Start Date', inplace=True) net_changes = net_changes.join(weather, on='Date') # 模型训练 X = net_changes[['Lat', 'Long', 'Dock Count', 'Temperature (mean)', 'Humidity (mean)', 'Wind Speed (mean)']] y = net_changes['Net Change'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) model = LinearRegression() model.fit(X_train, y_train) # 模型评估 y_pred = model.predict(X_test) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f'MSE: {mse}') print(f'R^2: {r2}') # 可视化 plt.figure(figsize=(10, 6)) sns.scatterplot(x=y_test, y=y_pred) plt.xlabel('Actual Net Change') plt.ylabel('Predicted Net Change') plt.title('Actual vs Predicted Net Change') plt.show() # 结果分析 coefficients = pd.DataFrame({'Feature': X.columns, 'Coefficient': model.coef_}) print(coefficients) ``` ### 分析和建议 1. **特征重要性**:通过模型系数可以确定哪些特征对净变化影响最大。 2. **运营优化**:根据预测结果,可以在需求高峰期前调整自行车分配。 3. **局限性和改进**:考虑更多外部因素(如节假日、特殊事件),并验证模型在不同时间段的表现。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值