DC - 13 :顺序表

顺序表操作:

(代码就不一次分析了)

以下为seqlist.h头文件

#ifndef __SEQLIST_H__
#define __SEQLIST_H__

#define FALSE -1
#define TRUE 0


#define INIT_SIZE 100
#define RISE 20


typedef int seqdata;

typedef struct _seqlist
{
    seqdata *list;
    seqdata len;
    seqdata max_len;	
}seqlist;


seqlist *Create_list();//创建表

int Againmalloc(seqlist *s);//大小不够的扩大

int Insert_pos(seqlist *s, int pos, seqdata data);//在pos位置插入数据
 
int Finddata(seqlist *s, seqdata data, seqdata *x);//找指定的值,返回下标

int Getdata(seqlist *s, int pos2, seqdata *x);//找下标的值

int Delete_pos (seqlist *s, int pos);//根据下标删除数据

int Delete_data(seqlist *s, seqdata data);//根据数据删除

int Reverse_list(seqlist *s);//逆序

seqlist *Merge_list(seqlist *s1, seqlist *s2);//合并表格

void Display (seqlist *s);//打印

void Destroy(seqlist *s);//释放

#endif
以下为seqlist.c函数

#include <stdio.h>
#include "seqlist.h"
#include <stdlib.h>


seqlist *Create_list()
{
	seqlist *s = (seqlist *)malloc(sizeof (seqlist) / sizeof (char));
	if (s == NULL)
	{
		return NULL;
	}
	s ->list = (seqdata *)malloc(sizeof (seqdata)/sizeof(char) * INIT_SIZE);
	if (s ->list == NULL)
	{
		free(s);
		return NULL;
	}
	s ->len     = 0;
	s ->max_len = INIT_SIZE;
	
	return s;
}

int Againmalloc(seqlist *s)
{
	if (s == NULL)
		return FALSE;
	  int size     = sizeof (seqdata) /sizeof (char) * (INIT_SIZE + RISE);
	  seqdata* tmp = (seqdata *)realloc(s ->list,size);
    if (tmp == NULL)
        return FALSE;
    s ->list      = tmp;
     s ->max_len += RISE;
	
	
	
    return TRUE; 	
}


int Insert_pos(seqlist *s, int pos, seqdata data)
{
	if (s == NULL || pos < 0 || pos > s ->len)
		return FALSE;
	if (s ->len == s ->max_len)
	{
		if (Againmalloc (s) != TRUE)
            return FALSE;			
	}
	
	int i;
	for (i = s ->len - 1; i >= pos; i--)
	{
        s ->list[i+1] = s ->list[i];
	}
        s ->list[pos] = data;
        s ->len++;

    return TRUE;		
	
	
}




int Finddata(seqlist *s, seqdata data, seqdata *x)
{

	if (s == NULL || x == NULL)
		return FALSE;
	
	int i;
	int flag = 0;
	for (i = 0; i < s ->len; i++)
	{
		if (s ->list[i] == data)
		{
            printf ("找到的下标为:");
        	flag = 1;
			*x   = i - 1;
			break;
		}
	}
	if (flag == 0) 
		printf ("未找到\n");
	
	
	
}



int Getdata(seqlist *s, int pos2, seqdata *x)
{
	if (s == NULL  || x ==NULL )
	{	
         return FALSE;
	}
	if (pos2 < 0 || pos2 > s ->len)
	{
		printf ("输入错误\n");
	}
	printf ("数字为 :");
	*x = s ->list[pos2];
	
	return TRUE;
	
}




int Delete_pos (seqlist *s, int pos)
{
	if (s == NULL || pos < 0 || pos > s ->len)
		return FALSE;
	int i;
	for (i = pos + 1; i < s ->len - 1; i++)
		s ->list[i] = s ->list[i+1];
	return TRUE;
	
}



int Delete_data(seqlist *s, seqdata data)
{
	if (s == NULL)
	    return FALSE;
	
	int i;
	int j;
	int flag = 1;
	for (i = 0; i < s ->len;i++)
	{
		if (s ->list[i] == data)
		{
			for (j = i; j < s ->len -1; j++)
			{
		        s ->list[j] = s ->list[j+1];
			    flag = 0;
			}				
		}
			
	}			
	if (flag == 1)
		printf ("没有这个数据\n");
	
	return TRUE;
}



int Reverse_list(seqlist *s)
{
	if (s == NULL)
		return FALSE;
	
	int i = 0;
	int j = s ->len - 1;
	while (i < j)
	{
		int tmp = s ->list[i];
		s ->list[i++] = s ->list[j];
		s ->list[j--] = tmp;
	}
	
	return TRUE;
		
}



seqlist *Merge_list(seqlist *s1, seqlist *s2)
{
	if (s1 == NULL || s2 == NULL)
		return NULL;
	seqlist* s3= (seqlist *)malloc(sizeof (seqlist) / sizeof (char));
	    if (s3 == NULL)
			return NULL;
		
	int sizes3 = sizeof (seqdata) / sizeof (char) * (s1 ->len + s2 ->len);
	s3 ->list = (seqdata *)malloc(sizes3);
	s3 ->len  = s1 ->len + s2 ->len;
	s3 ->max_len = s1 ->len + s2 ->len;
	
	
	int i = 0;
	int j = 0;
	int k = 0;
	while (i < s1 ->len  && j < s2 ->len)
	{
		if (s1 ->list[i] < s2 ->list[j])
			s3 ->list[k++] = s1 ->list[i++];
		else 
			s3 ->list[k++] = s2 ->list[j++];
	}
	
	while (i < s1 ->len )
	{
	    s3 ->list[k++] = s1 ->list[i++];
	}
	while (j < s2 ->len )
	{
		s3 ->list[k++] = s2 ->list[j++];
	}
	
	return s3;
	
}







void Display (seqlist *s)
{
	if (s == NULL)
		return ;
	
	int i;
	for (i = 0; i < 21; i++)
	{
		if (i % 4 == 0 && i != 0)
		    printf ("\n");
			printf ("%-8d",s ->list[i]);
	}
	printf ("\n");
	 
	
}

void Destroy(seqlist *s)
{
	if (s == NULL)
		return;
	
	// 先释放存储空间
	free (s->list);
	
	// 释放顺序表
	free (s);
}

下面为main.c

#include <stdio.h>
#include "seqlist.h"



int main()
{
	
	seqlist *s = Create_list();
	if (s == NULL)
	{
		printf ("创建失败\n");
		return FALSE;
	}
	    printf ("创建成功\n");
	


	
	int i1;
	for (i1 = 1; i1 < 21; i1++)
	{
		Insert_pos(s, 0, i1);
	}
	Display (s);
	
	
	
	int k1;
	Finddata (s, 5, &k1);
	printf ("%d\n",k1);
	Display (s);
	
	
        int k2;
	Getdata (s, 5, &k2);
	printf ("%d\n",k2);
	Display (s);
	
	
	
	Delete_data(s,75);
	Display (s);



	Delete_pos(s,5);
	printf("删除后的数据为:\n");
	Display (s);
	
	
	Reverse_list(s);
	printf ("逆序后的数据为:\n");
	Display (s);
	

	seqlist *s1 = Create_list();
	if (s1 == NULL)
	{
		printf ("创建失败\n");
		return FALSE;
	}
	seqlist *s2 = Create_list();
	int i;
	if (s2 == NULL)
	{
		printf ("创建失败\n");
		return FALSE;
	}
	for (i = 20; i >= 0; i -= 2)
	{
		Insert_pos(s1,0, i);
	}
	for (i = 19; i >= 1; i -= 2)
	{
		Insert_pos(s2,0, i);
	}
	seqlist *s3 = Merge_list(s1, s2);
	printf("合并数据过程如下:\n");
	printf ("s1: \n");
	Display(s1);
	printf ("s2: \n");
	Display(s2);
	printf ("s3: \n");
	Display(s3);
	Destroy(s);
	s = NULL;
	printf ("销毁成功\n");	
	return TRUE;
	

		
		
		
		
		
		
		
	
}
通过以上代码,总结出以下几点注意:

(1)头文件,程序代码=与==的区别,逗号分好的使用,这些虽然都是一些很细节的地方,但是对于精密的计算机来说,程序是按照我们所写的儿执行的,有时候一个符号,可能导致整个程序的崩溃。所以加强代码 编写是必不可少的,对于写程序的过程中,也应时刻注意符号等等的书写。

(2)在堆上用malloc开辟空间的时候,必不可少的操作是检查空间是否开辟成功,医用要用if语句进行检查,对于使用完的空间应该用free函数进行释放,使用完的指针指向NULL,
(3)顺序表可以类比成一个数组,下标从0开始,对于数组的大部分操作对于顺序表也适用。

(4)程序错误


合并两个有序的表,这个错误错在当时Display函数的初始值为1.。。。。找了很长时间才找到。所以写代码一定要细心。

(5)对于程序中的bug,现阶段要自己找,自己看,这些都是自己写代码宝贵的财富,只有错过,才知道哪儿是对的。只要改了这些习惯,才能写出高质量的代码。

(6)模型,很多不懂得过程用笔画成模型,用模型参照解答,会很快。


<think>我们正在分析TCPC-DPM的SrcCap日志,以理解充电协商过程。TCPC(Type-C Port Controller)是USB Type-C端口控制器,DPM(Dynamic Power Management)是动态电源管理。在USB PD(Power Delivery)协议中,SrcCap(Source Capabilities)是源端(如充电器)发出的能力声明,告知设备(如手机或笔记本)它能够提供的电源配置(电压、电流等)。 根据引用[3],VIN-DPM(输入电压动态电源管理)在充电器管理IC中扮演重要角色,它管理输入电源(如适配器)并为电池充电。在PD协商中,源端会发送多个SrcCap报文,设备端根据这些信息请求合适的电源配置。 在PD 3.0协议中,源端可能发送多个SrcCap报文(如SrcCap1, SrcCap2等),以提供不同的电源配置选项。设备端通过Request报文请求其中一个配置。整个协商过程涉及多个步骤,包括能力的声明、请求和确认。 分析日志时,我们需要关注: 1. SrcCap报文的内容:包括电压、电流、功率以及是否支持PPS(Programmable Power Supply)等。 2. 报文发送的顺序:源端可能先发送一个基础的能力集(SrcCap1),再发送扩展的能力集(SrcCap2),例如包含PPS档位。 3. 设备端的响应:设备端会发送Request报文,选择其中一个配置。 下面我们通过一个具体的日志分析示例来解读: 假设日志片段如下: ``` [TCPC] SrcCap1: 5V/3A, 9V/3A, 15V/3A [TCPC] SrcCap2: PPS: 3.3-11V/5A [TCPC] Device Request: 9V/3A [TCPC] Accept ``` 步骤解读: 1. 源端首先发送SrcCap1,声明三个固定档位:5V/3A, 9V/3A, 15V/3A。 2. 源端再发送SrcCap2,声明一个PPS档位:电压范围3.3V-11V,最大电流5A。 3. 设备端选择9V/3A的固定档位,并发送Request。 4. 源端接受请求(Accept),协商完成。 如果设备端支持PPS,它可能会选择PPS档位,例如: ``` [TCPC] Device Request: PPS 5V/3A ``` 在分析日志时,还需要注意: - 每个SrcCap报文可能包含多个电源对象(Power Data Objects, PDO)。每个PDO代表一种电源配置。 - 固定档位PDO(Fixed Supply PDO)和PPS PDO(Augmented PDO with PPS)有不同的结构。 - 设备端在Request中会指定所选PDO的索引(从1开始)或PPS的参数(电压、电流)。 为了更深入地理解,我们可以用数学表达式描述PPS的电压和电流范围。设PPS档位的电压范围为$[V_{\min}, V_{\max}]$,最大电流为$I_{\max}$,则设备可以请求任意电压$V \in [V_{\min}, V_{\max}]$,电流$I \in [0, I_{\max}]$,但受限于功率$P = V \times I \leq P_{\max}$($P_{\max}$由源端设定)。 在日志中,SrcCap2的PPS档位通常表示为: ``` PPS: <min_voltage>V-<max_voltage>V/<max_current>A ``` 引用[1]中提到的DPM_Report枚举类型,在充电协商过程中,DPM模块可能会生成报告,例如: - DPM_Report_DPC_STARTED:处理链(可能是协商过程)开始。 - DPM_Report_DPC_STOPPED:处理链结束。 - DPM_Report_DPC_ASSERT:检测到异常。 - DPM_Report_NOTIFY_DPC_RESULT:处理链有结果(如协商成功)。 这些报告可以帮助我们了解协商过程中的状态变化。 因此,在分析日志时,我们可以结合这些报告来理解协商过程。例如,如果看到DPM_Report_DPC_ASSERT,则说明协商过程中出现了异常。 总结分析步骤: 1. 识别日志中的SrcCap报文,解析每个PDO(包括固定档位和PPS档位)。 2. 观察设备端Request报文,看选择了哪个PDO(固定档位索引或PPS参数)。 3. 关注DPM报告,了解协商过程中的状态(开始、结束、异常等)。 4. 如果协商失败,检查是否有异常报告(如DPM_Report_DPC_ASSERT)或错误码。 通过以上步骤,我们可以解析TCPC-DPM日志并理解充电协商过程。 §§相关问题§§ 1. 如何从日志中识别PPS协商失败的具体原因? 2. 在USB PD协议中,SrcCap报文的结构是怎样的? 3. 如何通过DPM报告诊断充电协商中的异常? 4. 设备端在什么条件下会选择PPS档位而非固定档位?</think>### TCPC-DPM SrcCap日志解析与充电协商过程解读 #### 一、SrcCap日志结构解析 在USB PD协议中,SrcCap(Source Capabilities)是电源(Source)向设备(Sink)宣告供电能力的报文。日志中的`SrcCap1`、`SrcCap2`表示多组能力声明,其数学表达为: $$ \text{SrcCap}_n = \left\{ \text{PDO}_1, \text{PDO}_2, \cdots, \text{PDO}_k \right\} $$ 其中每个**电源数据对象(PDO)** 包含: 1. **电压/电流档位**:固定电压(如5V/3A)或PPS可调电压(如3.3-20V) 2. **协议标志位**:标识是否支持PPS、PD3.0等特性 3. **最大功率限制**:$P_{\max} = V_{\text{nom}} \times I_{\max}$ 引用[1]中的`DPM_Report_DPC_INFO`报告会记录这些能力宣告事件[^1]。 #### 二、典型协商流程分析 ```mermaid sequenceDiagram participant Source as 电源(TCPC) participant Sink as 设备(DPM) Source->>Sink: SrcCap1 (基础PDO) Sink->>Source: Request (选择PDO) alt 支持PPS Source->>Sink: SrcCap2 (PPS PDO) Sink->>Source: PPS_Request (动态电压请求) Source->>Sink: Accept (确认) else 不支持PPS Source->>Sink: Reject (拒绝) end Note right of Sink: DPM_Report_NOTIFY_DPC_RESULT[^1] ``` ##### 关键阶段解读: 1. **初次能力宣告(SrcCap1)** - 电源发送固定电压档位(如5V/3A, 9V/2A) - 日志示例:`SrcCap1: FIXED[5V/3A, 9V/2A]` 2. **PPS能力宣告(SrcCap2)** - 当设备发送包含`GET_PPS_STATUS`的Request后触发[^4] - 日志特征:`SrcCap2: PPS[3.3-11V/5A]` - 电压范围精度需满足$ \Delta V \leq \pm1\% $[^3] 3. **动态电压协商** - 设备发送`PPS_Request`指定目标电压$V_{\text{target}}$ - 数学关系:$V_{\text{target}} \in [V_{\min}, V_{\max}]$ - 电源响应`Accept`或`Reject`(受温度/线缆影响)[^3] #### 三、PPS协商失败诊断 当SrcCap2未正常公布PPS档位时,检查日志中以下关键点: 1. **设备请求类型** ```log [DPM] Request: RDO[PDO2] // 选择固定档位 [DPM] Request: PPS[5.2V/3A] // 正确触发PPS协商 ``` 2. **环境监测异常** - 若伴随`DPM_Report_DPC_ASSERT`[^1],通常表示: $$ \left| \frac{dT}{dt} \right| > 3℃/min \quad \text{或} \quad \Delta V_{\text{out}} > 0.1V $$ - 触发保护机制屏蔽PPS[^3] 3. **协议超时事件** - PPS响应需在$ t_{\text{resp}} < 20\text{ms} $ - 超时日志:`PD_ERR: PPS_TIMEOUT` #### 四、日志分析实例 **成功PPS协商:** ```log [TCPC] SrcCap1: FIXED[5V/3A, 9V/2A, 15V/1.5A] [DPM] Request: RDO[PDO2] // 选择9V档位 [TCPC] SrcCap2: PPS[3.3-11V/5A] // 公布PPS能力 [DPM] PPS_Request: 5.2V/3.2A [TCPC] Accept // 协商成功 [DPM] Report: NOTIFY_DPC_RESULT // 结果上报[^1] ``` **PPS协商失败:** ```log [TCPC] SrcCap1: FIXED[5V/3A] [DPM] Request: RDO[PDO1] // 缺失SrcCap2表明未触发PPS流程 [DPM] Report: DPC_ASSERT(ERR_PPS_UNSUPPORTED) // 异常报告[^1] ``` ### 根本问题定位 $$ \text{PPS失败率} \propto \frac{ \text{温度波动} \times \text{线缆阻抗} }{ \text{协议兼容性} } $$ 主要瓶颈在于**早期PD控制器固件**与**PPS精密电压调节**的匹配冲突[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值