把字符串存入数组c鱼鱼_AUTOSAR+C

7faf988957b49d9a1c059da11d1cdc1b.gif dfd898145b83d35fd9917f399fa29645.gif bff3a7682448e26173351f456c82a1f9.gif

1

AUTOSAR(存储抽象)

1

NvBlockSwComponents

注:以下AUTOSAR相关内容转载至CSDN博主「雪云飞星」 。大家AUTOSAR感兴趣可以访问原文。链接如下:

https://blog.csdn.net/xyfx_fhw/article/details/97122915

1、AutoSAR 4.x的优化

NvBlockSwComponents是S/R接口来做NVRAM的管理的,具有以下特点:

①可以将多个RAM变量聚合到一个NVRAM Block中

②对于NVRAM Blocks,支持扇入(Fan-in,可以理解为将多个SWC的数据导入到一个RAM Block中)和扇出(Fan-out,可以理解为将一个RAM Block中的数据导出到多个SWC的数据中)

③可以通过RTE对S/R的管理来防止并发访问的发生

④NvBlockSwComponents是可选的,没有需求可以不使用

2、架构

31b615159e3c3467bc51fa14aea6bcb7.png

NvBlockDescriptor:主要作用是规定RAM Block的区域划分,也可以做NvBlock的Service Needs功能等,下一节课会讲解它的详细用法

NvBlockSwComponents:该SWC的代码一般来说是自动生成的,它会根据配置自动负责和NvM进行对接,来完成读写操作。还可以定义一些Service函数供NvM使用,比如当写入数据完成后,可以调用Rte_NvMNotifyJobFinished来处理写入完成的一些事

Fan-in:图中将两个Application的SWC的数据存入了一个RAM Block中

Fan-out:图中将一个RAM Block中的某个数据给到了多个SWC里

Fan-in/out:即Fan-in和Fan-out的功能都有

3、控制流

eb6cc7e82cae9a1b6b9e849a7fcf5b4a.png

控制流是和NvBlockSwComponents的Runnable有关,因为Runnable才是控制的根本,NvBlockSwComponents中Runnable的触发只有三种条件:

• 定时周期触发

• Nv数据接收触发

• C/S接口调用触发

举例说明有:

①从Application SWC写一个数进入NV里,通过Nv数据接收触发的方式:

首先Application SWC通过Nv Port将要写入的数据传入NvBlockDescriptor设计好的RAM Block中(“3、架构” 那张图做的工作);然后由于这个Nv Port的写入操作,触发了WriteRunnable,该Runnable里会调用和NvM的C/S接口;最后由NvM_WriteBlock这个C/S接口去调用NvM中的写入函数,由NvM管理并写入数据

②从Application SWC写一个数进入NV里,通过C/S接口调用触发的方式:

首先也是Application SWC通过Nv Port将要写入的数据传入NvBlockDescriptor设计好的RAM Block中;然后Application SWC利用C/S接口调用NvBlockSwComponents的Service Runnable;再由该Runnable调用NvM里的NvM_WriteBlock这个C/S接口去调用NvM中的写入函数,由NvM管理并写入数据

③从Application SWC写一个数进入NV里,通过定时触发的方式:

也和上面类似,唯一的区别在于调用Runnable的方式变成了定时触发

二、 Nv Port

之前我们讲过了Port分为S/R和C/S Port,但其实还有几种特殊的Port,包括我们在模式管理中讲到的Mode Port,然后就是标定中用到的Calibration Port,还有就是我们在Nv中要使用到的Nv Port。它们的图标如下,从图标中来看,它们都是属于S/R接口的一种

e361c0306c4510b1877e458a0813501a.png

三、NV Block SWC

我们建立NvBlockSwComponent的时候需要选择我们的Type为Non-Volatile Memory Block的类型,这样,我们就得到了一个用于专门处理NV数据的SWC类型。但是该类型的SWC是不支持普通SWC的很多操作的,仅仅用于处理NV Data,代码可以由配置自动生成

  • Properties

这里可以配置NVRAM中的RAM Block 和ROM Block的一些选项

Data Type:该RAM Block的类型,这里需要注意的是,如果是使用的Fan-in的话,这里的类型一定要使用结构体类型,因为当多个SWC的数据存入一个RAM Block的时候,是需要多个数据进行暂存的。上图中的TestStruct是我新建的一个IDT数据类型

Periodic Trigger:如果我们配置了一个周期性的Runnable,那么这里是可以选择该Runnable的,作用就是当周期触发该Runnable时,该Runnable会执行将这个RAM Block写入NV的操作(通过NvM)

Data Reception Triggers:如果我们配置了一个Runnable,该Runnable的触发条件是On Data Reception,那么通过一个Data Mapping的操作,可以在这里显示所有的与本RAM Block关联的Data Reception Triggers Runnable

  • NV Block Data Mapping

这个Mapping的操作就是将SWC的Port与我们的RAM Block关联上,告诉DaVinci我们的Port传过来的数据要存放在哪个RAM Block的哪个数据中,或者我们的RAM Block里的数据要给哪些Port。

  • Service Needs(NvBlockNeeds)

之前讲过自下而上的Service Mapping操作,这里的Service Needs是自上而下的Service Mapping操作。作用是申明该SWC可能需要用到哪些Service函数,然后再进入BSW层去配置需要用到这些Service函数的功能。这里的NvBlockNeeds是一类特殊的Service Needs,因为它单独放在了NvBlockDescriptors里进行配置(但内容是一样的,只是位置不同罢了)。仅仅是NvBlockSwComponents有这个特性,如果不使用NvBlockSwComponents直接将Application SWC和NvM相连也是可以的,那么Application SWC的Service Needs就需要从其他地方来配置了。

9489b06295f16d96fac70d18b9e6372c.gif

2

C语言

11.2.3-11.3.3

a. gets_s函数

gets_s(words, STLEN);

gets_s()与fgets()的区别如下。

1、gets_s()只从标准输入中读取数据,所以不需要第3个参数。

2、如果gets_s()读到换行符,会丢弃它而不是储存它。

3、如果gets_s()读到最大字符数都没有读到换行符,会执行以下几步。首

先把目标数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换

行符或文件结尾,然后返回空指针。接着,调用依赖实现的“处理函数”(或

你选择的其他函数),可能会中止或退出程序。

第2个特性说明,只要输入行未超过最大字符数,gets_s()和gets()几乎一样,完全可以gets_s()替换gets()。

第3个特性说明,要使用这个函数还需要进一步学习。

比较一下 gets()、fgets()和 gets_s()的适用性。如果目标存储区装得下输入行,3 个函数都没问题。但是fgets()会保留输入末尾的换行符作为

字符串的一部分,要编写额外的代码将其替换成空字符。

如果输入行太长会怎样?使用gets()不安全,它会擦写现有数据,存在

安全隐患。gets_s()函数很安全,但是,如果并不希望程序中止或退出,就

要知道如何编写特殊的“处理函数”。另外,如果打算让程序继续运行,gets_s()会丢弃该输入行的其余字符,无论你是否需要。由此可见,当输入太长,超过数组可容纳的字符数时,fgets()函数最容易使用,而且可以选择不同的处理方式。

9861a1b930ca538ebbd921858b116870.png

b.scanf()函数

scanf()和gets()或fgets()的区别在于它们如何确定字符串的末尾:

scanf()更像是“获取单词”函数,而不是“获取字符串”函数;如果预留的存储区装得下输入行,gets()和fgets()会读取第1个换行符之前所有的字符。

scanf()函数有两种方法确定输入结束。无论哪种方法,都从第1个非空白字符作为字符串的开始。如果使用%s转换说明,以下一个空白字符(空行、空格、制表符或换行符)作为字符串的结束(字符串不包括空白字符)。如果指定了字段宽度,如%10s,那么scanf()将读取10 个字符或读到第1个空白字符停止(先满足的条件即是结束输入的条件)

如下图为字段宽度和scanf()

看下面的程序:

18aef701ffddcb4d26d3373c492327a9.png

下面是该程序的3个输出示例:

Please enter 2 names.

Jesse Jukes

I read the 2 names Jesse and Jukes.

Please enter 2 names.

Liza Applebottham

I read the 2 names Liza and Applebotth.

Please enter 2 names.

Portensia Callowit

I read the 2 names Porte and nsia.

第1个输出示例,两个名字的字符个数都未超过字段宽度。第2个输出示

例,只读入了Applebottham的前10个字符Applebotth(因为使用了%10s转换

说明)。第3个输出示例,Portensia的后4个字符nsia被写入name2中,因为第

2次调用scanf()时,从上一次调用结束的地方继续读取数据。在该例中,读

取的仍是Portensia中的字母。

scanf()和gets()类似,也存在一些潜在的缺点。如果输入行的内容过长,scanf()也会导致数据溢出。不过,在%s转换说明中使用字段宽度可防止溢出。

字符串输出

讨论完字符串输入,接下来我们讨论字符串输出。C有3个标准库函数,用于打印字符串:put()、fputs()和printf()。

c.puts()函数

puts()函数很容易使用,只需把字符串的地址作为参数传递给它即可。

如下图为puts()函数程序:

c747472521a7150f6917f4e8f744874c.png

该程序示例再次说明,用双引号括起来的内容是字符串常量,且被视为该字符串的地址。另外,储存字符串的数组名也被看作是地址。在第5个puts()调用中,表达式&str1[5]是str1数组的第6个元素(r),puts()从该元素

开始输出。与此类似,第6个puts()调用中,str2+4指向储存"pointer"中i的存储单元,puts()从这里开始输出。

puts()函数在遇到空字符时就会停止输出,所以必须确保有空字符

如下图程序操作是有问题的:

597d3ec36cc28258862921fc18de2c84.png

由于dont缺少一个表示结束的空字符,所以它不是一个字符串,因此puts()不知道在何处停止。它会一直打印dont后面内存中的内容,直到发现一个空字符为止。为了让puts()能尽快读到空字符,我们把dont放在side_a和side_b之间。

我们使用的编译器把side_a数组储存在dont数组之后,所以puts()一直输出至遇到side_a中的空字符。你所使用的编译器输出的内容可能不同,这取决于编译器如何在内存中储存数据。如果删除程序中的side_a和side_b数组会怎样?通常内存中有许多空字符,如果幸运的话,puts()很快就会发现一个。但是,这样做很不靠谱。

d.fputs()函数

fputs()函数是puts()针对文件定制的版本。它们的区别如下。

fputs()函数的第 2 个参数指明要写入数据的文件。如果要打印在显示器上,可以用定义在stdio.h中的stdout(标准输出)作为该参数。与puts()不同,fputs()不会在输出的末尾添加换行符。

e.printf()函数

和puts()一样,printf()也把字符串的地址作为参数。printf()函数用起来没有puts()函数那么方便,但是它更加多才多艺,因为它可以格式化不同的数据类型。

printf()不会自动在每个字符串末尾加上一个换行

符。因此,必须在参数中指明应该在哪里使用换行符。例如:

printf("%s\n", string);

和下面的语句效果相同:

puts(string);

如上所示,printf()的形式更复杂些,需要输入更多代码,而且计算机执行的时间也更长(但是你觉察不到)。然而,使用 printf()打印多个字符串更加简单。例如,下面的语句把 Well、用户名和一个#define定义的字符串

打印在一行:

printf("Well, %s, %s\n", name, MSG);

f6048d0d9ecb1583c232e4d2275c8d5f.gif 27816a394db8e26b036ab9873e6d88d3.png 2c571916d1422c37aa680d6aa70b635c.png公众号ID: gh_dc943d9de6b5扫码关注最新动态
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值