AVFoundation – AVAssetTrack 获取视频 音频信息

目录

  • 一.前言
    • 1.AVAsset
    • 2.AVAssetTrack
    • 3.AVComposition / AVMutableComposition
    • 4.AVMutableVideoComposition
    • 5.AVMutableCompositionTrack
    • 6.AVMutableVideoCompositionLayerInstruction
    • 7.AVMutableVideoCompositionInstruction
    • 8.AVAssetExportSession
  • 二.AVAssetTrack 简介
  • 三.AVAssetTrack 获取
  • 四.AVAssetTrack 介绍
    • 1、检索跟踪信息
    • 2、检索时间属性
    • 3、检索语言属性
    • 4、检索视觉特征
    • 5、检索声音特征
    • 6、检索基于帧的特征
    • 7、寻找轨道段
    • 8、管理元数据
    • 9、使用关联轨道
    • 10、创建示例游标
  • 五.AVAssetTrack 使用
  • 六.猜你喜欢

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 基础

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 线程

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> OpenGL ES

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> GPUImage

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> AVFoundation

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> CocoaPods

一.前言

1.AVAsset

Assets  可以来自一个文件或用户的相册,可以理解为多媒体资源,通过 URL 作为一个 asset 对象的标识. 这个 URL 可以是本地文件路径或网络流;

2.AVAssetTrack

AVAsset 包含很多轨道  **AVAssetTrack **的结合,如 audio, video, text, closed captions, subtitles…

3.AVComposition / AVMutableComposition

**使用  AVMutableComposition  类可以增删 AVAsset 来将单个或者多个 AVAsset 集合到一起,用来合成新视频。**除此之外,若想将集合到一起的视听资源以自定义的方式进行播放,需要使用 AVMutableAudioMix 和 AVMutableVideoComposition 类对其中的资源进行协调管理;

4.AVMutableVideoComposition

AVFoundation 类 API 中最核心的类是 AVVideoComposition / AVMutableVideoComposition 。

AVVideoComposition / AVMutableVideoComposition 对两个或多个视频轨道组合在一起的方法给出了一个总体描述。它由一组时间范围和描述组合行为的介绍内容组成。这些信息出现在组合资源内的任意时间点。

AVVideoComposition / AVMutableVideoComposition 管理所有视频轨道,可以决定最终视频的尺寸,裁剪需要在这里进行;

5.AVMutableCompositionTrack

多个 AVAsset 集合到一起合成新视频中轨道信息,有音频轨、视频轨等,里面可以插入各种对应的素材(画中画,水印等);

6.AVMutableVideoCompositionLayerInstruction

AVMutableVideoCompositionLayerInstruction 主要用于对视频轨道中的一个视频处理缩放、模糊、裁剪、旋转等;

7.AVMutableVideoCompositionInstruction

表示一个指令,决定一个 timeRange 内每个轨道的状态,每一个指令包含多个 AVMutableVideoCompositionLayerInstruction ;而 AVVideoComposition 由多个 AVVideoCompositionInstruction 构成;

AVVideoCompositionInstruction 所提供的最关键的一段数据是组合对象时间轴内的时间范围信息。这一时间范围是在某一组合形式出现时的时间范围。要执行的组全特质是通过其 AVMutableVideoCompositionLayerInstruction 集合定义的。

8.AVAssetExportSession

AVAssetExportSession 主要用于导出视频;

二.AVAssetTrack 简介

AVAsset 是 AVFoundation 框架中的核心的类,它提供了基于时间的音视频数据.(如电影文件,视频流),一个 AVAsset 包含很多轨道 AVAssetTrack 的结合,如 audio, video, text, closed captions, subtitles…

AVF_EXPORT AVMediaType const AVMediaTypeVideo                 NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT AVMediaType const AVMediaTypeAudio                 NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT AVMediaType const AVMediaTypeText                  NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT AVMediaType const AVMediaTypeClosedCaption         NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT AVMediaType const AVMediaTypeSubtitle              NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT AVMediaType const AVMediaTypeTimecode              NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT AVMediaType const AVMediaTypeMetadata              NS_AVAILABLE(10_8, 6_0);
AVF_EXPORT AVMediaType const AVMediaTypeMuxed                 NS_AVAILABLE(10_7, 4_0);

三.AVAssetTrack 获取

AVAssetTrack 可以 通过 AVAsset 获取,如下

- (nullable AVAssetTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;
- (NSArray<AVAssetTrack *> *)tracksWithMediaType:(AVMediaType)mediaType;
- (NSArray<AVAssetTrack *> *)tracksWithMediaCharacteristic:(AVMediaCharacteristic)mediaCharacteristic;@property (nonatomic, readonly) NSArray<AVAssetTrack *> *tracks;

其中 track id 是视频文件中的唯一标识码。

四.AVAssetTrack 介绍

1、检索跟踪信息

/* 轨道所属的 AVAsset  */
@property (nonatomic, readonly, weak) AVAsset *asset;/* 该轨道的唯一标识符  */
@property (nonatomic, readonly) CMPersistentTrackID trackID;/* 轨道的媒体类型;例如 AVMediaTypeVideo,AVMediaTypeAudio或AVMediaTypeSubtitle */
@property (nonatomic, readonly) AVMediaType mediaType;/* 轨道引用的媒体样本的格式描述 */
@property (nonatomic, readonly) NSArray *formatDescriptions;/* 指示轨道是否可在当前环境中播放;如果为YES,则可以启用使用轨道资源初始化的 AVPlayerItem的 AVPlayerItemTrack进行回放 */
@property (nonatomic, readonly, getter=isPlayable) BOOL playable API_AVAILABLE(macos(10.8), ios(5.0), tvos(9.0), watchos(1.0));/* Indicates whether the receiver is decodable in the current environment; if YES, the track can be decoded even though decoding may be too slow for real time playback.  */
@property (nonatomic, readonly, getter=isDecodable) BOOL decodable API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));/* 指示是否根据存储在其容器中的状态启用轨道。对于基于文件的媒体,可以使用 AVPlayerItemTrack更改其启用的演示文稿状态 */
@property (nonatomic, readonly, getter=isEnabled) BOOL enabled;/* 指示轨道是否引用仅包含在其存储容器中的样本数据;如果轨道仅在其存储容器内引用样本数据,则值为YES,否则为NO。 */
@property (nonatomic, readonly, getter=isSelfContained) BOOL selfContained;/* 轨道所需的样本数据的总字节数;如果无法确定总样本数据长度,则该值可以是0。 */
@property (nonatomic, readonly) long long totalSampleDataLength;/*指示轨道是否引用具有指定媒体特征的媒体
*/
- (BOOL)hasMediaCharacteristic:(AVMediaCharacteristic)mediaCharacteristic;

2、检索时间属性

/* AVAsset总时间轴内的跟踪时间范围。 */
@property (nonatomic, readonly) CMTimeRange timeRange;/*	时间刻度,其中轨道的时间值可以在没有无关数字转换的情况下操作。*/
@property (nonatomic, readonly) CMTimeScale naturalTimeScale;/* 由轨道引用的媒体数据的预估数据速率比特每秒。如果未指示数据速率,则该值可以是0.0,并且不能使用存储在媒体资源中的其他信息来计算该值。 */
@property (nonatomic, readonly) float estimatedDataRate;

3、检索语言属性

/* 与轨道相关的语言,作为  ISO 639-2/T 语言代码。如果没有指明语言,则该值可以是nil。 */
@property (nonatomic, readonly, nullable) NSString *languageCode;/* 与轨道关联的语言标记,作为 BCP 47 语言标记。如果未指示语言标记,则该值可以是nil。 */
@property (nonatomic, readonly, nullable) NSString *extendedLanguageTag;

4、检索视觉特征

/* 轨道引用的媒体数据的原生尺寸。对于视频轨道,例如视频或字幕轨道,这将返回媒体的 naturalSize。对于非视频轨道,例如音频或章节轨道,这将返回 CGSizeZero的值。*/
@property (nonatomic, readonly) CGSize naturalSize;/* 在轨道的存储容器中指定的转换作为可视媒体数据的首选转换以用于显示目的。此属性的值通常(但不总是) CGAffineTransformIdentity。 */
@property (nonatomic, readonly) CGAffineTransform preferredTransform;

5、检索声音特征

/*轨道存储容器中指定的音量作为可听媒体数据的首选音量;通常(但不总是)为1.0;对于不可听的音轨,该值将为0.0。
*/
@property (nonatomic, readonly) float preferredVolume;

6、检索基于帧的特征

/*轨道的帧速率,以每秒帧数为单位。标称帧速率表示每个媒体样本携带全帧的轨道的每秒帧数。对于基于场的(隔行扫描)视频轨道,此属性的值指示场速率,而不是帧速率。
*/
@property (nonatomic, readonly) float nominalFrameRate;/*轨道帧的最小持续时间。轨道的最小帧持续时间是其最大帧速率的倒数。例如,具有每秒30帧的最大帧速率的视频轨道将具有1/30(或0.033)的最小帧持续时间。如果轨道的最小帧持续时间未知或无法计算,则此属性的值为 kCMTimeInvalid。 */
@property (nonatomic, readonly) CMTime minFrameDuration API_AVAILABLE(macos(10.10), ios(7.0), tvos(9.0), watchos(1.0));/*指示轨道中的样本是否可能具有不同的显示值和解码时间戳。
*/
@property (nonatomic, readonly) BOOL requiresFrameReordering API_AVAILABLE(macos(10.10), ios(8.0), tvos(9.0), watchos(1.0));

7、寻找轨道段

//从轨道的媒体样本到其时间线的时间映射
@property (nonatomic, copy, readonly) NSArray<AVAssetTrackSegment *> *segments;//来自segments数组的轨道段对应或最接近trackTime。
- (nullable AVAssetTrackSegment *)segmentForTrackTime:(CMTime)trackTime;//通过适当的时间映射映射指定的跟踪时间,并返回生成的样本显示时间。与trackTime对应的样本呈现时间; 如果trackTime超出范围,则该值将无效。
- (CMTime)samplePresentationTimeForTrackTime:(CMTime)trackTime;

8、管理元数据

/* 所有元数据标识符的元数据项数组,其中有一个值可用。* 可以使用-metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:方法根据语言过滤AVMetadataItem实例数组。* 可以使用- metadataItemsFromArray:filteredByIdentifier:方法通过标识符过滤它们。*/
@property (nonatomic, readonly) NSArray<AVMetadataItem *> *metadata;//每个公共元数据键的AVMetadataItem对象数组,其值可用。
@property (nonatomic, readonly) NSArray<AVMetadataItem *> *commonMetadata;//该数组包含NSString对象,每个对象用于轨道可用的每种元数据格式
@property (nonatomic, readonly) NSArray<AVMetadataFormat> *availableMetadataFormats;//创建一个元数据对象数组,每个元数据对象对应于指定格式的容器中的每个元数据项。
- (NSArray<AVMetadataItem *> *)metadataForFormat:(AVMetadataFormat)format;

9、使用关联轨道

//该数组包含NSString对象,每个类型的关联对应一个对象。
@property (nonatomic, readonly) NSArray<AVTrackAssociationType> *availableTrackAssociationTypes;//创建一个数组,其中包含与使用指定关联类型的轨道关联的其他轨道。
- (NSArray<AVAssetTrack *> *)associatedTracksOfType:(AVTrackAssociationType)trackAssociationType;

10、创建示例游标

//指示AVAssetTrack是否可以提供AVSampleCursor的实例来遍历其媒体样本并发现信息。
@property (nonatomic, readonly) BOOL canProvideSampleCursors;/* 创建AVSampleCursor的实例,并将其放置在指定的时间戳附近。
* 如果AVAssetTrack的asset的属性receiverPreciseDurationAndTiming的值为YES,则示例光标准确定位在接收者的最后一个媒体示例上,其显示时间戳小于或等于所需的时间戳,如果没有这样的示例,则为表示顺序中的第一个示例。
* 如果providePreciseDurationAndTiming为NO,并且将精确样本定位在期望的时间戳上非常昂贵,则可以近似定位样本光标。
*/
- (nullable AVSampleCursor *)makeSampleCursorWithPresentationTimeStamp:(CMTime)presentationTimeStamp;//创建AVSampleCursor的实例,并将其按解码顺序放置在接收器的第一个媒体样本上。
- (nullable AVSampleCursor *)makeSampleCursorAtFirstSampleInDecodeOrder;//创建AVSampleCursor的实例,并将其按解码顺序放置在接收器的最后一个媒体样本上。
- (nullable AVSampleCursor *)makeSampleCursorAtLastSampleInDecodeOrder;

五.AVAssetTrack 使用

根据 AVAsset 获取 AVAssetTrack 检查视频是否自带旋转角度(比如相机拍摄的视频有可能带有旋转角度)

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:C语言教程 - AVAssetTrack 获取视频 音频信息
//@Time:2021/07/26 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/- (void)viewDidLoad
{[super viewDidLoad];self.view.backgroundColor = [UIColor redColor];//加载视频文件,检查是否有旋转角度NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];NSLog(@"time:%f",CMTimeGetSeconds(asset.duration));NSLog(@"angle : %d",[self degressFromVideoFileWithURL:url]);//加载音频文件,检查是否有视频NSURL* url2 = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"456.mp3" ofType:nil]];AVURLAsset* asset2 = [[AVURLAsset alloc] initWithURL:url options:nil];NSArray *videoTracks = [asset2 tracksWithMediaType:AVMediaTypeVideo]; // 检查是否有视频轨道NSArray *audioTracks = [asset2 tracksWithMediaType:AVMediaTypeAudio]; // 检查是否有音频轨道if([videoTracks count] > 0)NSLog(@"存在视频");if([audioTracks count] > 0)NSLog(@"存在音频");
}-(NSUInteger)degressFromVideoFileWithURL:(NSURL *)url
{NSUInteger degress = 0;AVAsset *asset = [AVAsset assetWithURL:url];NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; // 检查是否有视频轨道if([tracks count] > 0) {AVAssetTrack *videoTrack = [tracks objectAtIndex:0];//获取视频轨道相关信息CGAffineTransform t = videoTrack.preferredTransform;if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){// Portraitdegress = 90;}else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){// PortraitUpsideDowndegress = 270;}else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){// LandscapeRightdegress = 0;}else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){// LandscapeLeftdegress = 180;}}return degress;
}
/*
time:4249.883000
angle : 90
存在音频
*/

六.猜你喜欢

  • AVAsset 加载媒体
  • AVAssetTrack 获取视频 音频信息
  • AVMetadataItem 获取媒体属性元数据
  • AVAssetImageGenerator 截图
  • AVAssetImageGenerator 获取多帧图片
  • AVAssetExportSession 裁剪/转码
  • AVPlayer 播放视频
  • AVPlayerItem 管理资源对象
  • AVPlayerLayer 显示视频
  • AVQueuePlayer 播放多个媒体文件
  • AVComposition AVMutableComposition 将多个媒体合并
  • AVVideoComposition AVMutableVideoComposition 管理所有视频轨道

未经允许不得转载:猿说编程 » AVFoundation – AVAssetTrack 获取视频 音频信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/524646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云漫圈 | 什么是DNS?什么是DNS污染?什么又是DNS劫持?

戳蓝字“CSDN云计算”关注我们哦&#xff01;文章转载自公众号&#xff1a;漫画编程2019年1月23日下午&#xff0c;我正在公司疯狂的撸着代码&#xff0c;沉浸在我的代码世界中&#xff0c;正在欣赏着自己刚刚写下的一行lambda表达式&#xff0c;突然微信上传来女朋友的消息。在…

React之state总结

1.理解 1&#xff09;可包含多个key-value 2&#xff09;更新state来更新页面显示 2.注意 1&#xff09;render中this为组件实例对象 2&#xff09;组件方法中this为underfined&#xff0c;解决&#xff1f; a.bind&#xff08;&#xff09; b.箭头函数 3&#xff09;更…

AVFoundation – AVMetadataItem 获取媒体属性元数据

目录 一.前言 1.AVAsset2.AVAssetTrack3.AVComposition / AVMutableComposition4.AVMutableVideoComposition5.AVMutableCompositionTrack6.AVMutableVideoCompositionLayerInstruction7.AVMutableVideoCompositionInstruction8.AVAssetExportSession 二.AVMetadataItem 简介三…

全面剖析企业私有云

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 |孙杰本文转载自公众号&#xff1a;华章计算机在以AWS、Google、阿里等为代表的公有云发展的同时&#xff0c;很多大型企业出于数据安全性、系统稳定性、软硬件自主权、对自主可控以及TCO低的考虑&#xff0c;更加倾向于建设企…

AVFoundation – AVAssetImageGenerator 截图

目录 一.前言 1.AVAsset2.AVAssetTrack3.AVComposition / AVMutableComposition4.AVMutableVideoComposition5.AVMutableCompositionTrack6.AVMutableVideoCompositionLayerInstruction7.AVMutableVideoCompositionInstruction8.AVAssetExportSession 二.AVAssetImageGenerato…

React之props批量传递

<!DOCTYPE html> <html> <head> <meat charset"UTF-8"> <title>2_props批量传递</title> </head> <body> <!-- 准备好一个容器 --> <div id"test1"></div> <div id"test2&qu…

趣挨踢 | 如何修改个人简历?一些过来人的经验

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 汕大小吴出处&#xff1a;https://www.nowcoder.com/discuss/154151一、前言又到了招聘的季节&#xff0c;看到很多师弟师妹们不太懂得如何写简历来展现自己&#xff0c;这里我想给出我个人的一些建议。因为我的简历修改了很…

C/C++ _wcsupr_s 函数 – unicode 字符串小写转大写 - C语言零基础入门教程

目录 一._wcsupr_s 函数简介二._wcsupr_s 函数实战三.注意问题三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 面向对象 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 设计模式 零基…

React之props限制

<!DOCTYPE html> <html> <head> <meat charset"UTF-8"> <title>2_props限制</title> </head> <body> <!-- 准备好一个容器 --> <div id"test1"></div> <div id"test2"&…

msyql之事务

--事务 --转账 create database shop character set utf8 collate utf8_general_ci use shop create table account( id int(3) not null auto_increment, NAMEvarchar(30) not null, moneydecimal(9,2) not null, primary key(id) )engineinnodb default cha…

云评测 | OpenStack智能运维解决方案 @文末有福利!

戳蓝字“CSDN云计算”关注我们哦&#xff01;文章摘自 | 《OpenStack架构分析与实践》谈到OpenStack&#xff0c;一个难以避免的话题就是运维&#xff0c;对于OpenStack的运维而言&#xff0c;随着其项目的不断增多&#xff0c;传统的“人肉运维”方式显然不能满足当下及以后的…

C/C++ ceil 函数 - C语言零基础入门教程

目录 一.ceil 函数简介二.ceil 函数使用三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 面向对象 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 设计模式 零基础 C/C 学习路线推荐 :…

通信协议讲解

协议&#xff1a;约定&#xff0c;好比说的普通话 网络通信协议:速率&#xff0c;传输码率&#xff0c;代码结构&#xff0c;传输控制...... 问题&#xff1a;非常的复杂&#xff1f; 大事化小&#xff1a;分层&#xff01; TCP/IP协议簇&#xff1a;实际上是一组协议 重要…

要闻君说: 百度云喜提信息安全首证;紫光展锐携5G芯片进击2019MWC;OPPO首发5G手机惊艳亮相……...

关注并标星星CSDN云计算每周三次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go 大家好&#xff01;偶是要闻君。活动多多、新闻不少&#xff0c;精神饱满的周一&#xff0c;学起来&#xff01;&#xff01;&#xff01;文/要闻君一年一度&#xff0c;十分重磅&a…

C/C++ floor 函数 - C语言零基础入门教程

目录 一.floor 函数简介二.floor 函数使用三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 面向对象 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 设计模式 零基础 C/C 学习路线推荐…

Tcp实现聊天讲解

客户端&#xff1a; 1.连接服务器Socket 2.发送消息 服务端&#xff1a; 1.建立服务端口ServerSocket 2.等待用户的连接accept 3.接收用的消息 package com.wuming.lesson02;import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStr…

Spring精华问答 | Spring Boot有哪些优点?

戳蓝字“CSDN云计算”关注我们哦&#xff01;Spring是于2003 年兴起的一个轻量级的Java 开发框架&#xff0c;为了解决企业应用开发的复杂性而创建的。今天&#xff0c;我们一起来看看关于Spring更加有深度的问答吧。。1Q&#xff1a;Spring Boot有哪些优点&#xff1f;A&#…

C/C++ round 函数 - C语言零基础入门教程

目录 一.round 函数简介二.round 函数使用三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 面向对象 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 设计模式 零基础 C/C 学习路线推荐…

基于Kubernetes的持续部署方案

戳蓝字“CSDN云计算”关注我们哦&#xff01;文章转载自Docker方案概述本技术方案为基于Kubernetes为核心的持续部署&#xff08;下文简称CD&#xff09;方案&#xff0c;可以满足开发方的程序级日志查看分析&#xff0c;运维方的快速扩容与日常运维分析&#xff0c;并且可以保…

C/C++ abs 函数 - C语言零基础入门教程

目录 一.abs 函数简介二.abs 函数使用三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 面向对象 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 设计模式 零基础 C/C 学习路线推荐 : C…