精华内容
下载资源
问答
  • 字符的三种存储方式

    万次阅读 多人点赞 2020-05-25 22:50:08
    工科生一枚,热衷于底层技术开发,强烈的好奇...  在数据结构中,字符要单独用一种存储结构来存储,称为存储结构。这里的指的就是字符。无论学习哪种编程语言,操作最多的总是字符。我们平常使用最多的.

    工科生一枚,热衷于底层技术开发,有强烈的好奇心,感兴趣内容包括单片机,嵌入式Linux,Uboot等,欢迎学习交流!
    爱好跑步,打篮球,睡觉。 欢迎加我QQ1500836631(备注CSDN),一起学习交流问题,分享各种学习资料,电子书籍,学习视频等。

      在数据结构中,字符串要单独用一种存储结构来存储,称为串存储结构。这里的串指的就是字符串。无论学习哪种编程语言,操作最多的总是字符串。我们平常使用最多的存储结构无疑是利用定长数组存储。但是这种存储结构需要提前分配空间,当我们不知道字符串长度的时候,过大的分配内存无疑是一种浪费。因此,合理的选择字符串的存储方式显得格外重要。下面将依次介绍三种存储方式。

    定长顺序存储

      字符串的定长顺序存储结构,可以理解为采用 “固定长度的顺序存储结构” 来存储字符串,因此限定了其底层实现只能使用静态数组。
      使用定长顺序存储结构存储字符串时,需结合目标字符串的长度,预先申请足够大的内存空间。
      例如,采用定长顺序存储结构存储 “feizhufeifei”,通过目测得知此字符串长度为12(不包含结束符 ‘\0’),因此我们申请的数组空间长度至少为 12,用 C 语言表示为:

    char str[18] = "feizhufeifei";
    

      下面是具体的C语言实现

    #include<stdio.h>
    int main()
    {
        char str[15]="feizhufeifei";
        printf("%s\r\n",str);
        return 0;
    }
    

      这种存储方式基本是初学者都应该掌握的。下面介绍第二种存储方式。

    动态数组存储

      首先我们应该明确两个概念:堆和栈。
      堆是由我们程序员自己管理的,当进程调用malloc等函数分配内存时,新分配的内存就被动态分配到堆上,当利用free等函数释放内存时,被释放的内存从堆中被剔除。 
      栈又称堆栈,是用户存放程序临时创建的变量,也就是我们函数{}中定义的变量,但不包括static声明的变量,static意味着在数据段中存放变量。除此之外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中,由于栈的先进后出特点,所以栈特别方便用来保存、恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存,交换临时数据的内存区。
      当我们调用malloc时,就会在堆上划分一块空间给我们使用,具体代码如下:

    //创建了一个动态数组str,通过使用 malloc 申请了 10个 char 类型大小的堆存储空间。
    char * str = (char*)malloc(10*sizeof(char));
    

      动态数组的优势是长度可变,根据需要动态进行分配。当我不想申请新的变量,但是又想要扩大str的空间怎么办呢?这个时候realloc函数就起作用了。

    //通过使用这行代码,之前具有10 个 char 型存储空间的动态数组,其容量扩大为可存储 20 个 char 型数据。
    str = (char*)realloc(str, 20*sizeof(char));
    

      下面通过一个合并两个字符串的例子来更好地理解下动态分配过程。

    /*
     * @Description: 字符串的堆动态堆分配内存
     * @Version:   V1.0
     * @Autor: Carlos
     * @Date: 2020-05-25 
     * @LastEditors: Carlos
     * @LastEditTime: 2020-05-25 
     */ 
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //打印测试语句
    #define DEBUG 0
    #if DEBUG
    #define DBG_PRINTF(fmt, args...)  \
    do\
    {\
        printf("<<File:%s  Line:%d  Function:%s>> ", __FILE__, __LINE__, __FUNCTION__);\
        printf(fmt, ##args);\
    }while(0)
    # else
    
    # define DBG_PRINTF(fmt, args...)
    #endif
    int main()
    {
        char *s1 = NULL;
        char *s2 = NULL;
        s1 = (char *)malloc(5*sizeof(char *));
        strcpy(s1,"test"); 
        DBG_PRINTF("s1:%s\r\n",s1);
        s2 = (char *)malloc(7*sizeof(char *));
        strcpy(s2,"string"); 
        DBG_PRINTF("s2:%s\r\n",s2);
        int length1 = strlen(s1);
        int length2 = strlen(s2);
        //尝试将合并的串存储在 s1 中,如果 s1 空间不够,则用realloc动态申请
        if(length1<length1+length2)
            s1 =(char*) realloc(s1,(length1 + length2+1) * sizeof(char));
         //合并两个串到 s1 中
        for(int i = length1; i < length1 + length2;i++)
             s1[i] = s2[i - length1];
         //串的末尾要添加 \0,避免出错
        s1[length1 + length2] = '\0';
        printf("s1+s2:%s", s1);
        //用完动态数组要立即释放
        free(s1);
        free(s2);
        return 0;
    }
    

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/qq_16933601/article/details/106342678

    块链存储

      块链存储就是利用链表来存储字符串。本文使用的是无头结点的链表结构(即链表的第一个头结点也存储数据)。
    我们知道,单链表中的 “单” 强调的仅仅是链表各个节点只能有一个指针,并没有限制数据域中存储数据的具体个数。因此在设计链表节点的结构时,可以令各节点存储多个数据。
      例如,我们要用链表存储feizhu字符串,链表结构如下所示:
    在这里插入图片描述
      我们也可以每个链表存储四个字符,那么最后一个节点肯定不会占满。这时,我们可以使用#或者其他符号将其填满。
    在这里插入图片描述
      怎样确定链表中每个节点存储数据的个数呢?
      链表各节点存储数据个数的多少可参考以下几个因素:
      串的长度和存储空间的大小:若串包含数据量很大,且链表申请的存储空间有限,此时应尽可能的让各节点存储更多的数据,提高空间的利用率(每多一个节点,就要多申请一个指针域的空间);反之,如果串不是特别长,或者存储空间足够,就需要再结合其他因素综合考虑;
      程序实现的功能:如果实际场景中需要对存储的串做大量的插入或删除操作,则应尽可能减少各节点存储数据的数量;反之,就需要再结合其他因素。
      下面是具体的代码实现。

    /*
     * @Description: 字符串的块链表存储(无头结点的链表)
     * @Version: V1.0
     * @Autor: Carlos
     * @Date: 2020-05-25 
     * @LastEditors: Carlos
     * @LastEditTime: 2020-05-25 
     */ 
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    //全局设置链表中节点存储数据的个数
    #define linkNum 3
    typedef struct link {
        //数据域可存放 linkNum 个数据
        char a[linkNum]; 
        //代表指针域,指向直接后继元素
        struct link * next; 
    }Link; 
    /**
     * @Description: 遍历链表,打印
     * @Param: Link * head 结构体头结点指针
     * @Return: 无
     * @Author: Carlos
     */
    void PrintLink(Link * head)
    {
         Link * p = head;
        while (p)
        {
        for (int i = 0; (i < linkNum) &&(p->a[i]!='#'); i++) 
        {
            printf("%c", p->a[i]);
        }
         p = p->next;
        }
    }
    /**
     * @Description: 初始化链表
     * @Param: Link * head 结构体头结点指针。char * str 要操作的字符串
     * @Return: Link *结构体指针
     * @Author: Carlos
     */
    Link * InitLink(Link * head, char * str)
    {
        int length = strlen(str);
        //需要的节点个数 向上取整
        int nodenum = length/linkNum;
        Link *p = head;
        int j;
         //将数据存放到每个节点的数组中
        for(int i = 0;i<=nodenum;i++)
        {
           
            for( j = 0;j < linkNum;j++)  
            {
                if (i*linkNum + j < length)
                {
                     p->a[j] = str[i*linkNum+j];
                } 
                //使用#填充未满的节点数组空间
                else
                {
                    p->a[j] = '#';
                }
                          
            }
            //链接新旧两个节点
            if (i*linkNum + j < length)
            {
                Link* q = (Link*)malloc(sizeof(Link));
                q->next = NULL;
                p->next = q;
                p = q;
            }
        }
       
        return head;
    }
    
    int main()
    {
        Link* head = (Link*)malloc(sizeof(Link));
        head->next=NULL;
        InitLink(head,"blockchain");
        PrintLink(head);
        return 0;
    }
    

      关于链表不明白的可以参考这篇博客史上最全单链表的增删改查反转等操作汇总以及5种排序算法(C语言)
      文中代码均已测试,有任何意见或者建议均可联系我。欢迎学习交流!
      如果觉得写的不错,请点个赞再走,谢谢!

    展开全文
  • 的概念及存储方式

    千次阅读 2020-04-06 16:20:09
    一、的基本概念 1.定义 是由零个或多个字符组成的有限序列。一 般记为 s= “a1a2a3…an” 其中,s是的名, 用双引号括起来的字符序列是的值;an可以是字母、 数字或其他字符;中字符的数目n称为的长度。...

    一、串的基本概念

    1.定义
    串是由零个或多个字符组成的有限序列。一 般记为
    s= “a1a2a3…an”
    其中,s是串的名, 用双引号括起来的字符序列是串的值;an可以是字母、 数字或其他字符;串中字符的数目n称为串的长度。零个字符的串称为空串, 其长度为零。
    2.基本概念
    空格串:由一个或多个空格组成的字符串称为空格串;
    (空串与空格串的区别:空串长度为0,而空格串长度不为零。)
    子串:串中任意连续字符组成的子序列称为该串的子串;
    主串:包含子串的串称为主串;
    子串在主串中的位置:首次出现在主串中的位置
    例如:
    主串S=“abcdefbcdh”
    子串s=“bcd”
    则s在S中的位置(或序号)为:2

    二、串的比较

    (1)两串相等的条件:当且仅当串长度相等,并且各个位置上的字符都相等
    (2)两个串A,B的比较,从前往后逐个比较对应位置上的ASCII码:
    ① “=” 两个字符串同时结束,表示A=B;
    例如:“abc"=“abc”
    ② “>" A中ASCII码大于B中对应位置上的ASCII码,或者B结束,表示A>B
    例如:”abxy">“ab” “132”>“123”
    ③ "<“B中ASCII码大于A中对应位置上的ASCII码,或者A结束,表示A<B
    例如:”abc”<“abcd” “bef”<“c”

    三、串的存储表示

    顺序存储:用一组连续的存储单元来存放串中的字符序列
    1、定长顺序存储表示
    类型定义

    # define maxlen 255
    typedef struct {
        char ch[maxlen]; //存储串的一维数组
        int length;  //串长度
    }sstring;
    

    2、堆分配存储表示(动态)
    类型定义

    typedef char *string
    typedef struct{
            char *ch;
            int length;
    }hstring;
    hstring S;
    

    链式存储:用单链表方式来存储串值
    类型定义

    # define nodesize 80
    typedef struct node{
        char data[nodesize];
        struct node *next;
    }lsring;
    
    展开全文
  • 字符str1、str2连接,三种存储方式一、定长存储 一、定长存储 #include<iostream> using namespace std; #define MAXLEN 255 typedef struct { char ch[MAXLEN + 1]; int length; }String; void StrAssign...

    串(字符串)是一种特殊的线性表,它的数据元素仅有一个字符组成。一般情况下处理的非数值型数据对象经常是字符串数据,例如在事务处理中,顾客的姓名、地址、货物产地等,一般都作为字符串处理。通常以“串的整体”作为处理对象。

    一 、串的存储结构

    串的顺序存储结构是用一组地址连续的存储单元来存储字符序列的。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。一般用定长数组来定义。
    在这里插入图片描述
    串的实际长度可以在预定义长度的范围内随意,超出预定义长度的串值则会被舍弃,称之为“截断”。

    在这里插入图片描述
    1.定长顺序存储
    2.堆分配存储(也是顺序存储结构)
    3.块链存储

    1 定长存储

    1.串的顺序存储结构
    串的顺序存储结构是用一组地址连续的存储单元来存储字符序列的。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。一般用定长数组来定义。
    在这里插入图片描述
    #define MAXLEN 255
    typedef struct {
    char ch[MAXLEN + 1];
    //存储串的一维数组,ch[0]~ch[255],共256个;
    //通常情况下ch[0]存放串的长度,或者闲置不用,真正串的类容从ch[1]开始
    int length;//串的当前长度
    }String;

    2 块链存储

    串要进行频繁插入删除操作时,顺序存储不方便,就要用到链式存储

    串的块链存储,指的是使用链表结构存储字符串。
    在这里插入图片描述
    从图 2 可以看到,使用链表存储字符串,其最后一个节点的数据域不一定会被字符串全部占满,对于这种情况,通常会用 ‘#’ 或其他特殊字符(能与字符串区分开就行)将最后一个节点填满。

    链表各节点存储数据个数的多少可参考以下几个因素:
    串的长度和存储空间的大小:若串包含数据量很大,且链表申请的存储空间有限,此时应尽可能的让各节点存储更多的数据,提高空间的利用率(每多一个节点,就要多申请一个指针域的空间);反之,如果串不是特别长,或者存储空间足够,就需要再结合其他因素综合考虑;
    程序实现的功能:如果实际场景中需要对存储的串做大量的插入或删除操作,则应尽可能减少各节点存储数据的数量;反之,就需要再结合其他因素。

    1 串的链式存储

    串的块链存储,指的是使用链表结构存储字符串。
    在这里插入图片描述
    缺点存储密度低
    如图第一个结点存储了字符A,占用一个字节,假如地址占用4个字节,那么存储密度1/(1+4)=0.2
    在这里插入图片描述

    2 块链存储

    为了解决存储密度引入,链式存储的块链
    将多个字符存储在一个结点,那么这一个节点叫做一个存储块,即块链
    在这里插入图片描述
    如图第一个结点存储了字符A、B、C、D,4个字符占用4个字节,假如地址占用4个字节,那么共占用8个字节,则存储密度 4/(4+4)=0.5

    在这里插入图片描述

    如果每个块存放50个字符,那么存储密度50/(50+4)=0.92
    在这里插入图片描述

    3 块链存储的定义

    在这里插入图片描述

    二、串连接三种方式实现(定长、堆、块链)

    字符串str1、str2连接,分别用定长存储、堆存储、块链存储实现,不能直接调用函数库中自带的连接函数。

    1 定长存储

    #include<iostream>
    using namespace std;
    #define MAXLEN 255//定义串的最大长度为255,<=255以内的任何串可用
    typedef struct {
    	char ch[MAXLEN + 1];//存储串的一维数组,ch[0]~ch[255],共256个
    	int length;//串的当前长度
    }String;
    void StrAssign(String* Str, char str[])//生成一个其值等于字符串常量 str 的串 Str
    {
    	int i = 0;
    	while (str[i] != '\0') i++;//计算str的长度
    	Str->length = i;
    	for (i = 0; i < Str->length; i++) {
    		Str->ch[i] = str[i];//从第一个字符开始,着个赋
    	}
    }
    void StrConcat(String str1, String str2, String* str3)//连接字符串1和2,并存在字符串3中
    {
    	str3->length = str1.length + str2.length;
    	int i;
    	for (i = 0; i < str1.length; i++) {//当串1的字符全部赋值给串3,退出当前for循环
    		str3->ch[i] = str1.ch[i];
    	}  //将str1赋值到str
    	for (; i < str3->length; i++) {//此for循环的i从串1长度str1.length开始到str3->length结束
    		str3->ch[i] = str2.ch[i - str1.length];
    	}  //将str2赋值到str
    }
    void print(String* str)
    {
    	int i;
    	for (i = 0; i < str->length; i++) {
    		cout << str->ch[i];
    	}
    	cout << endl;
    }
    int main()
    {
    	char st1[255], st2[255];
    	String str1, str2, str3;
    	cout << "请输入第一个串" << endl;
    	cin >> st1;
    	StrAssign(&str1, st1);
    	cout << "请输入第二个串" << endl;
    	cin >> st2;
    	StrAssign(&str2, st2);
    	StrConcat(str1, str2, &str3);
    	print(&str3);
    	return 0;
    }
    

    在这里插入图片描述

    2 堆分配存储

    #include<iostream>    //堆存储
    using namespace std;
    #define MAXSIZE 100
    typedef struct st {
    	char* ch;  //串存放的起始地址
    	int length;  //串的长度
    	int strsize; //分配的存储空间的大小
    }String;
    String CreateNullString() {    //初始化
    	String str;
    	str.length = 0;
    	str.ch = (char*)malloc(MAXSIZE * sizeof(char));
    	str.strsize = MAXSIZE;
    	return str;
    }
    void StrAssign(String* str1, char str[]) {//生成一个其值等于字符串常量 str 的串 str1
    	int i = 0;
    	while (str[i] != '\0') i++;//计算str的长度
    	if (str1->length < i) {
    		//增加存储空间,将较长的空间赋值为新的值
    		str1->ch = (char*)malloc(sizeof(char));
    		str1->strsize = i;
    	}
    	str1->length = i;
    	for (i = 0; i < str1->length; i++) {
    		str1->ch[i] = str[i];//从第一个字符开始,着个赋
    	}
    }
    void StrConcat(String* str, String str1, String str2) {
    	if (str->strsize < str1.strsize + str2.strsize) {
    		str->ch = (char*)realloc(str->ch, (str->length + str1.length) * sizeof(char));
    		str->strsize = str1.length + str2.length;
    	}
    	str->length = str1.length + str2.length;
    	int i;
    	for (i = 0; i < str1.length; i++) {
    		str->ch[i] = str1.ch[i];
    	}  //将str1赋值到str
    	for (; i < str->length; i++) {
    		str->ch[i] = str2.ch[i - str1.length];
    	}  //将str2赋值到str
    }
    void print(String* str) {
    	int i;
    	for (i = 0; i < str->length; i++) {
    		cout << str->ch[i];
    	}
    	cout << endl;
    }
    int main()
    {
    	char st1[255], st2[255];
    	String str1, str2, str3;
    	str1 = CreateNullString();
    	str2 = CreateNullString();
    	str3 = CreateNullString();
    	cout << "请输入第一个串" << endl;
    	cin >> st1;
    	StrAssign(&str1, st1);
    	cout << "请输入第二个串" << endl;
    	cin >> st2;
    	StrAssign(&str2, st2);
    	StrConcat(&str3, str1, str2);
    	print(&str3);
    	return 0;
    }
    

    在这里插入图片描述

    3 块链存储

    在这里插入图片描述

    思路(1):两个子串先分成块,再连接

    //将两个串先分别转换成块存储
    //将已经分好的块进行连接

    但这样有个问题,第一个串的最后一块可能不满,显然有些不合理,造成了空间浪费

    #include <stdio.h>
    #include <iostream>
    #include <cstring>
    #define CHUNKSIZE 4//用户自定义块的大小
    using namespace std;
    typedef struct Chunk {  //块链存储结构体
    	char ch[CHUNKSIZE];
    	struct Chunk* next;
    }Chunk;
    Chunk* initChunk(char[]);//初始化一个串 
    void print_Chunk(Chunk* h);//打印Chunk串 
    void contract(Chunk* t, Chunk* s);//将串s插入到串t某个字符后 
    int main()
    {
    	Chunk* s, * t;
    	char s_str[100];
    	char t_str[100];
    	cout << "请输入t串:";
    	cin >> t_str;
    	cout << "请输入s串:";
    	cin >> s_str;
    	t = initChunk(t_str);//将两个串先分别,转换成块存储
    	s = initChunk(s_str);//将两个串先分别,转换成块存储
    	cout << "链接后为:" << endl;
    	contract(t, s); //将已经存储好的块进行连接
    	print_Chunk(t);//打印连接后的块链
    	return 0;
    }
    Chunk* initChunk(char str[])
    {
    	Chunk* h, * temChunk, * lastChunk;
    	h = new Chunk;//为头结点分配内存, 头结点不储存信息 
    	lastChunk = h;
    	int num = strlen(str) / CHUNKSIZE;//计算出所需块链的个数
    	int mod = strlen(str) % CHUNKSIZE;
    	if (mod != 0)num++;//如果不是这整数个块,则块数num+1
    	int i, j;
    	//对每一个块赋值 
    	for (i = 0; i < num; i++)
    	{
    		temChunk = new Chunk;//为块链分配内存 
    		j = 0;
    		//当字符串还没有结束以及j<CHUNKSIZE的时候,进行赋值 
    		while (j < CHUNKSIZE && str[i])
    		{
    			temChunk->ch[j] = str[i * CHUNKSIZE + j];//将对应字符赋值
    			j++;
    		}
    		// 尾插法
    		//将当前已经完成的这个块,连接在上一个块的后面
    		lastChunk->next = temChunk;
    		lastChunk = temChunk;
    	}
    	//如果最后一个块没填满,通常用'#'补上
    	if (mod != 0)
    	{
    		int temp = CHUNKSIZE - mod;
    		for (size_t q = 0; q < temp; q++)
    		{
    			lastChunk->ch[mod + q] = '#';//最后一个块没填满,用'#'补上
    		}
    	}
    	lastChunk->next = NULL;
    	return h;
    }
    void print_Chunk(Chunk* h)
    {
    	Chunk* temChunk;
    	temChunk = h->next;
    	int i;
    	while (temChunk)//打印输出时,按块输出
    	{
    		for (i = 0; i < CHUNKSIZE; i++)
    		{
    
    			if (temChunk->ch[i] == NULL)
    			{
    				break;
    			}
    			else
    			{
    				cout << temChunk->ch[i] ;
    			}
    
    		}
    		temChunk = temChunk->next;//一个块输出完毕,继续输出下一个块
    		cout << " ";//为了使直观的反映内部存储结构,输出时块与块之间,以空格间隔
    	}
    	cout << endl;
    }
    void contract(Chunk* t, Chunk* s)
    {
    	while (t->next)
    	{
    		t = t->next;
    	}
    	t->next = s->next;//直接把s连在t之后	 
    }
    

    如图,第一个串的最后一块可能不满,显然有些不合理,造成了空间浪费。
    为了便于观察,他是4个一块,第一个串最后一块不满的用#补上

    //为了使直观的反映内部存储结构,输出时块与块之间,以空格间隔
    在这里插入图片描述
    第二个串最后一块不满的用#补上
    在这里插入图片描述

    思路(2)先连接,再分块存储

    //先把两个串连接
    //然后再按照块链的方式存储

    #include <iostream>
    #include<string>
    #include<cstring>
    #define CHUNKSIZE 5 //用户自定义块的大小
    using namespace std;
    
    typedef struct Chunk {//块链存储结构体
    	char ch[CHUNKSIZE];
    	struct Chunk* next;
    }Chunk;
    
    char s_s[200];
    Chunk* initChunk(char[]);//初始化一个块链 
    void print_Chunk(Chunk* h);//打印Chunk块 
    void StrConcat(char s1[], char s2[]);
    int main()
    {
    	Chunk* s, * t;
    	char s_str[100];
    	char t_str[100];
    	cout << "请输入t串:";
    	cin >> t_str;
    	cout << "请输入s串:";
    	cin >> s_str;
    	StrConcat(t_str, s_str);//先把两个串连接
    	t = initChunk(s_s);//然后再按照块链的方式存储
    	print_Chunk(t);//打印连接后的块链
    	return 0;
    }
    
    Chunk* initChunk(char str[])
    {
    	Chunk* h, * temChunk, * lastChunk;
    	h = new Chunk;//为头结点分配内存, 头结点不储存信息 
    	lastChunk = h;
    	int len = strlen(str);//串的总长度
    
    	int num = strlen(str) / CHUNKSIZE;//计算出所需块链的个数
    	int mod = strlen(str) % CHUNKSIZE;
    	if (mod != 0) num++;//如果不是这整数个块,则块数num+1
    
    	int i, j;
    	//对每一个块链赋值 
    	for (i = 0; i < num; i++)//创建num个块,组成一个块链
    	{
    		temChunk = new Chunk;//为块链分配内存 
    		j = 0;
    
    		//创建单个块,当这个块填满或者字符串结束时,退出本次while循环
    		//当字符串还没有结束以及j<CHUNKSIZE的时候,进行赋值 
    		while (str[i * CHUNKSIZE + j] != '\0' && j < CHUNKSIZE)
    		{
    			temChunk->ch[j] = str[i * CHUNKSIZE + j];//将对应字符赋值
    			j++;
    		}
    		// 尾插法
    		//将当前已经完成的这个块,连接在上一个块的后面
    		lastChunk->next = temChunk;
    		lastChunk = temChunk;
    
    		//如果最后一个块没填满,通常用'#'补上
    		//当字符串已经结束,并且最后一个块没满,则执行if语句
    		if ((i * CHUNKSIZE + j) == (len) && (CHUNKSIZE - mod!=0))
    		{
    			int temp = CHUNKSIZE - mod;
    			for (size_t q = 0; q < temp; q++)
    			{
    				temChunk->ch[j + q] = '#';//最后一个块没填满,用'#'补上
    			}
    		}
    	}
    	lastChunk->next = NULL;//块链完成,最后加上NULL结束
    
    
    	cout << endl << "当前块的大小为:" << CHUNKSIZE << endl;
    	cout << "该块链共有" << num << "个块组成" << endl << endl;
    	return h;
    }
    
    
    void print_Chunk(Chunk* h)
    {
    	Chunk* temChunk;
    	temChunk = h->next;
    	int i;
    
    	//输出连接后的串
    	cout << "连接后的串为:";
    	for (i = 0; i < strlen(s_s); i++) {
    		cout << s_s[i];
    	}
    	cout << endl;
    
    	//便于观察块链的内部真实存储结构,输出块链的每一个块的内容
    	cout << "块链的存储结构为:";
    	while (temChunk)
    	{
    		for (i = 0; i < CHUNKSIZE; i++)
    		{
    			if (temChunk->ch[i] == NULL)
    			{
    				break;
    			}
    			else
    			{
    				cout << temChunk->ch[i];
    			}
    		}
    		temChunk = temChunk->next;
    		cout << " ";//当一个块输出完毕,输出空格,即每个块之间用空格间隔,还是便于观察
    	}
    	cout << endl;
    }
    
    void StrConcat(char s1[], char s2[])
    {
    	int i = 0;
    	for (; i < strlen(s1); i++)
    	{
    		s_s[i] = s1[i];
    	}
    
    	for (; i < strlen(s1) + strlen(s2); i++)
    	{
    		s_s[i] = s2[i - strlen(s1)];
    	}
    }
    

    #define CHUNKSIZE 5 //用户自定义块的大小

    当CHUNKSIZE= 5时,
    第二个块只有3个字符,后面两个空缺部分用#填补

    //为了使直观的反映内部存储结构,输出时块与块之间,以空格间隔
    在这里插入图片描述
    当CHUNKSIZE= 4时,
    存储满两个完整的块
    在这里插入图片描述

    思路(3)在思路(1)上改进,第一个串的最后一块不满,用第二个串前移补上。但程序是实现上较为复杂,感兴趣的自己研究。

    展开全文
  • redis存储几种方式

    千次阅读 2019-11-15 10:09:28
    首先要明白redis是一个数据库 redis是一个内存数据库, 所有数据基本上都存在于内存当中, 会定时以追加或者快照的方式刷新到硬盘中. 由于redis是一个内存数据库, 所以读取写入的速度是非常快的, 所以经常被用来做...

    一、redis的数据是存在内存里吗?

       首先要明白redis是一个数据库 redis是一个内存数据库, 所有数据基本上都存在于内存当中, 会定时以追加或者快照的方式刷新到硬盘中. 由于redis是一个内存数据库, 所以读取写入的速度是非常快的, 所以经常被用来做数据, 页面等的缓存。
    

    二、redis各种数据类型的使用场景?

    1. Redis常用数据类型

    Redis最为常用的数据类型主要有以下:

    String
    Hash
    List
    Set
    Sorted set
    pub/sub
    Transactions
    在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部内存管理中是如何描述这些不同数据类型的:

         首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:
    
         type代表一个value对象具体是何种数据类型,
    
         encoding是不同数据类型在redis内部的存储方式,
    
         比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。
    
       这里需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的,该功能会在后面具体描述。通过上图我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用,我们随后会具体讨论。
    
    1. 各种数据类型应用和实现方式

    下面我们先来逐一的分析下这7种数据类型的使用和内部实现方式:

    String:

    Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字.
    
    常用命令:  set,get,decr,incr,mget 等。
    
    应用场景:String是最常用的一种数据类型,普通的key/ value 存储都可以归为此类.即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。除了提供与 Memcached 一样的get、set、incr、decr 等操作外,Redis还提供了下面一些操作:
    

    获取字符串长度
    往字符串append内容
    设置和获取字符串的某一段内容
    设置及获取字符串的某一位(bit)
    批量设置一系列字符串的内容

    实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
    

    Hash

    常用命令:hget,hset,hgetall 等。
    
    应用场景:在Memcached中,我们经常将一些结构化的信息打包成HashMap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。
    
            我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:
    
    用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:
    

    在这里插入图片描述
    第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。
    在这里插入图片描述
    第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。

    那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口,如下图:
    在这里插入图片描述
    也就是说,Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。

    这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。

    实现方式:

    上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

    List

    常用命令:lpush,rpush,lpop,rpop,lrange等。
    
    应用场景:
    
    Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。
    
    Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。Lists的另一个应用就是消息队列,
    可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。
    
    实现方式:
    
    Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
    

    Set

    常用命令:
    
    sadd,spop,smembers,sunion 等。
    
    应用场景:
    
    Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
    
    Sets 集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构,可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
    
    实现方式:
    
    set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因
    

    Sorted Set

    常用命令:
    
    zadd,zrange,zrem,zcard等
    
    使用场景:
    
    Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
    
    另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
    
    实现方式:
    
    Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
    

    Pub/Sub

    Pub/Sub 从字面上理解就是发布(Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊等功能
    

    Transactions
    谁说NoSQL都不支持事务,虽然Redis的Transactions提供的并不是严格的ACID的事务(比如一串用EXEC提交执行的命令,在执行中服务器宕机,那么会有一部分命令执行了,剩下的没执行),但是这个Transactions还是提供了基本的命令打包执行的功能(在服务器不出问题的情况下,可以保证一连串的命令是顺序在一起执行的,中间有会有其它客户端命令插进来执行)。Redis还提供了一个Watch功能,你可以对一个key进行Watch,然后再执行Transactions,在这过程中,如果这个Watched的值进行了修改,那么这个Transactions会发现并拒绝执行。

    1. Redis实际应用场景

      Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;它的数据模型非常独特,用的是单线程。另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不需要转到Redis。
      

    转向Redis当然也是可取的,许多开发者从一开始就把Redis作为首选数据库;但设想如果你的开发环境已经搭建好,应用已经在上面运行了,那么更换数据库框架显然不那么容易。另外在一些需要大容量数据集的应用,Redis也并不适合,因为它的数据集不会超过系统可用的内存。所以如果你有大数据应用,而且主要是读取访问模式,那么Redis并不是正确的选择。

        然而我喜欢Redis的一点就是你可以把它融入到你的系统中来,这就能够解决很多问题,比如那些你现有的数据库处理起来感到缓慢的任务。这些你就可以通过Redis来进行优化,或者为应用创建些新的功能。在本文中,我就想探讨一些怎样将Redis加入到现有的环境中,并利用它的原语命令等功能来解决 传统环境中碰到的一些常见问题。在这些例子中,Redis都不是作为首选数据库。
    

    1、显示最新的项目列表
    下面这个语句常用来显示最新项目,随着数据多了,查询毫无疑问会越来越慢。

    SELECT * FROM foo WHERE … ORDER BY time DESC LIMIT 10
    在Web应用中,“列出最新的回复”之类的查询非常普遍,这通常会带来可扩展性问题。这令人沮丧,因为项目本来就是按这个顺序被创建的,但要输出这个顺序却不得不进行排序操作。

        类似的问题就可以用Redis来解决。比如说,我们的一个Web应用想要列出用户贴出的最新20条评论。在最新的评论边上我们有一个“显示全部”的链接,点击后就可以获得更多的评论。
    
        我们假设数据库中的每条评论都有一个唯一的递增的ID字段。
    
        我们可以使用分页来制作主页和评论页,使用Redis的模板,每次新评论发表时,我们会将它的ID添加到一个Redis列表:
    

    LPUSH latest.comments
    我们将列表裁剪为指定长度,因此Redis只需要保存最新的5000条评论:

       LTRIM latest.comments 0 5000 
    
      每次我们需要获取最新评论的项目范围时,我们调用一个函数来完成(使用伪代码):
    

    FUNCTION get_latest_comments(start, num_items):
    id_list = redis.lrange(“latest.comments”,start,start+num_items - 1)
    IF id_list.length < num_items
    id_list = SQL_DB(“SELECT … ORDER BY time LIMIT …”)
    END
    RETURN id_list
    END
    这里我们做的很简单。在Redis中我们的最新ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。

        我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。
    

    2、删除与过滤
    我们可以使用LREM来删除评论。如果删除操作非常少,另一个选择是直接跳过评论条目的入口,报告说该评论已经不存在。

       有些时候你想要给不同的列表附加上不同的过滤器。如果过滤器的数量受到限制,你可以简单的为每个不同的过滤器使用不同的Redis列表。毕竟每个列表只有5000条项目,但Redis却能够使用非常少的内存来处理几百万条项目。
    

    3、排行榜相关
    另一个很普遍的需求是各种数据库的数据并非存储在内存中,因此在按得分排序以及实时更新这些几乎每秒钟都需要更新的功能上数据库的性能不够理想。

      典型的比如那些在线游戏的排行榜,比如一个Facebook的游戏,根据得分你通常想要:
    
         - 列出前100名高分选手
    
         - 列出某用户当前的全球排名
    
      这些操作对于Redis来说小菜一碟,即使你有几百万个用户,每分钟都会有几百万个新的得分。
    
      模式是这样的,每次获得新得分时,我们用这样的代码:
    
      ZADD leaderboard  <score>  <username> 
    
     你可能用userID来取代username,这取决于你是怎么设计的。
    
      得到前100名高分用户很简单:ZREVRANGE leaderboard 0 99。
    
      用户的全球排名也相似,只需要:ZRANK leaderboard <username>。
    

    4、按照用户投票和时间排序
    排行榜的一种常见变体模式就像Reddit或Hacker News用的那样,新闻按照类似下面的公式根据得分来排序:

       score = points / time^alpha 
    
      因此用户的投票会相应的把新闻挖出来,但时间会按照一定的指数将新闻埋下去。下面是我们的模式,当然算法由你决定。
    
      模式是这样的,开始时先观察那些可能是最新的项目,例如首页上的1000条新闻都是候选者,因此我们先忽视掉其他的,这实现起来很简单。
    
      每次新的新闻贴上来后,我们将ID添加到列表中,使用LPUSH + LTRIM,确保只取出最新的1000条项目。
    
      有一项后台任务获取这个列表,并且持续的计算这1000条新闻中每条新闻的最终得分。计算结果由ZADD命令按照新的顺序填充生成列表,老新闻则被清除。这里的关键思路是排序工作是由后台任务来完成的。
    

    5、处理过期项目
    另一种常用的项目排序是按照时间排序。我们使用unix时间作为得分即可。

      模式如下:
    
       - 每次有新项目添加到我们的非Redis数据库时,我们把它加入到排序集合中。这时我们用的是时间属性,current_time和time_to_live。
    
       - 另一项后台任务使用ZRANGE…SCORES查询排序集合,取出最新的10个项目。如果发现unix时间已经过期,则在数据库中删除条目。
    

    6、计数
    Redis是一个很好的计数器,这要感谢INCRBY和其他相似命令。

       我相信你曾许多次想要给数据库加上新的计数器,用来获取统计或显示新信息,但是最后却由于写入敏感而不得不放弃它们。
    
       好了,现在使用Redis就不需要再担心了。有了原子递增(atomic increment),你可以放心的加上各种计数,用GETSET重置,或者是让它们过期。
    
       例如这样操作:
    
         INCR user:<id> EXPIRE 
    
         user:<id> 60 
    
       你可以计算出最近用户在页面间停顿不超过60秒的页面浏览量,当计数达到比如20时,就可以显示出某些条幅提示,或是其它你想显示的东西。
    

    7、特定时间内的特定项目
    另一项对于其他数据库很难,但Redis做起来却轻而易举的事就是统计在某段特点时间里有多少特定用户访问了某个特定资源。比如我想要知道某些特定的注册用户或IP地址,他们到底有多少访问了某篇文章。

      每次我获得一次新的页面浏览时我只需要这样做:
    
       SADD page:day1:<page_id> <user_id> 
    
      当然你可能想用unix时间替换day1,比如time()-(time()%3600*24)等等。
    
      想知道特定用户的数量吗?只需要使用SCARD page:day1:<page_id>。
    
       需要测试某个特定用户是否访问了这个页面?SISMEMBER page:day1:<page_id>。
    

    8、实时分析正在发生的情况,用于数据统计与防止垃圾邮件等
    我们只做了几个例子,但如果你研究Redis的命令集,并且组合一下,就能获得大量的实时分析方法,有效而且非常省力。使用Redis原语命令,更容易实施垃圾邮件过滤系统或其他实时跟踪系统。

    9、Pub/Sub
    Redis的Pub/Sub非常非常简单,运行稳定并且快速。支持模式匹配,能够实时订阅与取消频道。

    10、队列
    你应该已经注意到像list push和list pop这样的Redis命令能够很方便的执行队列操作了,但能做的可不止这些:比如Redis还有list pop的变体命令,能够在列表为空时阻塞队列。

       现代的互联网应用大量地使用了消息队列(Messaging)。消息队列不仅被用于系统内部组件之间的通信,同时也被用于系统跟其它服务之间的交互。消息队列的使用可以增加系统的可扩展性、灵活性和用户体验。非基于消息队列的系统,其运行速度取决于系统中最慢的组件的速度(注:短板效应)。而基于消息队列可以将系统中各组件解除耦合,这样系统就不再受最慢组件的束缚,各组件可以异步运行从而得以更快的速度完成各自的工作。
    
    此外,当服务器处在高并发操作的时候,比如频繁地写入日志文件。可以利用消息队列实现异步处理。从而实现高性能的并发操作。
    

    11、缓存
    Redis的缓存部分值得写一篇新文章,我这里只是简单的说一下。Redis能够替代memcached,让你的缓存从只能存储数据变得能够更新数据,因此你不再需要每次都重新生成数据了。

    展开全文
  • 存储结构

    2019-06-02 22:03:26
    存储结构与线性表相同,分为两。 1.的顺序存储结构 的顺序存储结构是用一组地址连续的存储单元来存储串中的字符序列的。按照预定义的大小,为每个定义的变量分配一个固定长度的存储区。一般是用定长...
  • 字符输入的几种方式

    千次阅读 2021-01-22 17:05:50
    一.对于string类 方法一:... 第一个参数str是用来存储输入行的数组名称,第二个参数len是要读取的字符数。 #include using namespace std; int main() { char str[30]; cin.getline(str, 30); cout ; return 0; }
  • 前端游览器的几种存储方式 1.cookies 2.localstorage 3.sessionstorage 4.Web SQL 5.IndexedDB 1.cookies:在HTML5标准前本地存储的主要方式 优点:是兼容性好,请求头自带cookie方便; 缺点:是只有4K,自动请求头...
  • 几种本地存储方式

    2019-11-29 10:50:07
    浏览器本地存储的容器: 1-cookie 2-sessionStorage 3-localStorage cookie cookie 浏览器早期存储数据容器, 主要用于 存放用户名和密码 特点: 容量小 4kb 操作繁琐 ‘name=zs; pass=123; age=20’ h5中新增两...
  • C语言中定义字符几种方式

    千次阅读 2020-03-11 08:45:27
     由于字符本质上其实就是以'\0作为'结尾的特殊字符数组,所以定义字符时,必须保证字符串存储的最后一个元素为'\0'。  当我们没有给定字符具体长度时,我们通过这种方式:char 字符名称[] = {字符所含...
  • 是一特殊的线性表,所以先得搞清楚线性表的顺序、链式存储,在其基础上便可以清楚分析特殊线性表的存储结构:栈、队列、 顺序:结构体里面定义一个数组+长度等辅助信息 链式:结构体里面定义一个元素数据类型+...
  • 详细对比Java字符存储方式

    千次阅读 2019-11-28 18:47:27
    详细对比Java字符存储方式 字符: String name = "hello"; 变量名name存储在jvm栈,值"hello"存储在堆中的常量池中 字符对象: String name2 = new String("hello"); 变量名name2存储在jvm栈,值"hello...
  • 【1】在H5之前,cookie是主要的存储方式。cookie可以兼容到包括ie6以上的所有浏览器。 【2】localStorage的存储周期为永久,只要开发者不手动删除,会一直存在 sessionStorage的存储周期为当前会话,数据会在...
  • 的3种存储结构

    千次阅读 2015-05-28 13:05:13
    第一种存储结构:顺序存储 这种存储结构里没有包含指针,比如说: String S[101];//其中S[0]存储S的长度 第二种存储结构:堆存储结构 这种存储结构一般包含一个头结点,比如说: typedef struct{ Node *head; ...
  • 前端HTML5几种存储方式的总结

    千次阅读 2018-03-18 21:23:09
    总体情况h5之前,存储主要是用cookies。... 目标解决4k的大小问题解决请求头常带存储信息的问题解决关系型存储的问题跨浏览器 1、本地存储localstorage存储方式:以键值对(Key-Value)的方式存储,永久存储,永不...
  • C语言:定义字符几种方式

    万次阅读 多人点赞 2019-05-30 14:14:26
    #include <stdio.h> ... //定义字符几种方式 //字符和字符数组的区别:最后一位是否是空字符 char names1[] = {'j', 'a', 'c', 'k', '\0'}; char names2[50] = "jack"; char * ...
  • 第一,通过jedis 储存对象大概三 one: 本课程的序列化成byte字节 ,最终存byte字节, two: 对象转hashmap,也就是你想表达的hash的形式,最终存map, three: 对象转json,最终存json,其实也就是...
  • HTML5的几种存储方式

    万次阅读 2017-07-01 20:27:34
    HTML5的几种存储方式html5在引入webStorage之前,主要用cookies.web storagehtml5的webstorage 分两种:LocalStorage 和SessionStorage,两者的差别主要在生命周期不同。 LocalStorage LocalStorage用于持久化的...
  • Java中字符存储方式 ...以下几种情形。 情形一 String s = "123"; 虚拟机在处理字面量"123"时,首先在本地栈中创建字符"123",随后对其调用本地方法intern()。intern方法的作用是检查StringTabl
  • 字符常见的几种编码方式

    千次阅读 2016-10-28 15:31:56
    .ASCII码 这是美国在19世纪60年代的时候为了建立英文字符和二进制的关系时制定的编码规范,它能表示128个字符,其中包括...原本的ASCII码对于英文语言的国家是够用了,但是欧洲国家的一些语言会拼音,这时7个字节就
  • JSON字符几种格式

    千次阅读 2021-02-24 14:07:06
    2.JSON字符({ “key” : “value”}) { "key" : "我爱你", "key1" : "一生一世" } 3.JSON数组({ “key” : [value]}) { "key" : [520, 1314], "key1" : [520, 3344] } 4.JSON对象({ “key” : {value}}
  • 字符的输入与赋值是非常容易搞混淆的一块,这里总结一下顺序存储的字符输入方式: 一、栈内静态存储 1.定义时用字符赋值 char s[15] = "helloworld"; 不能先定义,然后赋值,如: char s[10]; s = “hello...
  • 常见的储存方式 - plist 格式文件存储 - NSUserDefaults 沙盒存储(个人偏好设置) - 文件读写存储 - 解归档存储 - 数据库存储 了解缓存,先要了解iOS中沙盒机制这个概念 沙盒其实质就是在iOS系统...
  • 掌握的基本处理操作和几种不同的存储结构(定长顺序存储表示、堆分配存储表示和块链存储表示)。 二、 实验要求 1、 实现赋值、比较、求长、串联接以及求子这5种基本操作。 2、 能利用上述实现的基本操作...
  • Java字符存储方式

    千次阅读 2018-12-28 05:24:51
      Java中的字符只能位于内存中的两个区域:常量池和Java堆。常量池维护了一个StringTable,它... 以下几种情形。 情形一 String s="123"; 复制代码  虚拟机在处理字面量"123"时,首先在本地栈中创建字符"1...
  • 串存储结构及其实现

    千次阅读 2019-03-15 09:39:10
    数据结构中,字符要单独用一种存储结构来存储,称为存储结构。这里的指的就是字符。 严格意义上讲,存储结构也是一种线性存储结构,因为字符中的字符之间也具有"一对一"的逻辑关系。只不过,...
  • 在richtextbox中对字符进行常见的几种操作,并最后批量存储到access中 适合新手学习对字符的操作问题
  • 变量的存储以及变量的几种类型

    千次阅读 2019-09-16 14:45:12
    起初我们在内存中开辟一块空间用来存储数据,每一块空间都一个地址值。但是如果很多个地址值的时候,非常难以辨别和记忆,所以我们给每一个地址值定义一个变量。(如上面的name和number) 二、举例 我们在...
  • 1、 实现赋值、比较、求长、串联接以及求子这5基本操作。 2、 能利用上述实现的基本操作完成置换Replace (&S, T, V)以及从中删除一段子StrDelete(&S,pos,len)的操作。 3、 以上要求实现的操作不能直接...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 581,065
精华内容 232,426
关键字:

串有几种存储方式