精华内容
下载资源
问答
  • dlib库学习-------矩形区域表示

    千次阅读 2019-03-25 21:11:00
    bbox通常有两种表示方式: 左上角和右下角坐标 中心点坐标和长宽 在dlib库中提供了两个类来表示一个矩形区域dlib.rectangle和dlib.drectangle,下面我们分别来介绍一下这两个类 dlib.rectangle 1.构造函数 ...

    做过目标检测工作的人都知道我们经常用一个矩形框(bbox)表示一个目标区域。bbox通常有两种表示方式:

    • 左上角和右下角坐标
    • 中心点坐标和长宽

    在dlib库中提供了两个类来表示一个矩形区域dlib.rectangle和dlib.drectangle,下面我们分别来介绍一下这两个类

    • dlib.rectangle

              1.构造函数

     __init__(left,top,right,bottom)  
    '''
    left----->矩形区域左上角的横坐标
    
    top------>矩形区域左上角的纵坐标
    
    right---->矩形区域右下角的横坐标
    
    down----->矩形区域右上角的纵坐标
    ''''

               rectangle类的构造函数接受四个参数,全部为int型。

         2.rectangle包含的常用方法

    area()-------------------->返回矩形框的面积(int型)
    center()------------------>返回矩形框的中心点(point型)
    height()------------------>高(int)
    width()------------------->宽(int)
    left(),top(),right(),bottom()------>左上点,右下点的坐标
    contains()--------------->判断矩形区域是否包围某个点或者某个矩形,该函数有多个原型,返回值为bool类型
       1.contains(point)------->接受参数为point型的一个点
       2.contains(X,Y)--------->接受一个坐标,全部为整型
       3.contains(rectangle)---->接受一个dlib.rectangle类型表示的矩形面积
    intersect(rectangle)-------->该函数求当前矩形与输入矩形的交集,返回一个dlib.rectangle类型
    is_empty()----------------->判断矩形是否为空
    • dlib.drectangle

         该类和dlib.rectangle几乎完全相同。唯一的区别就是内部坐标用浮点数实现(吐槽一下,这么久了在数字图像领域从来没见过浮点数的坐标,不知道作者基于什么目的搞出了这个类)

      构造函数接受四个float型,意义和rectangle的参数完全相同

    area(),height(),width(),left(),top(),right(),bottom()返回值全部为float型

     

    展开全文
  • 字符串数组的两种存储方式

    千次阅读 2016-11-24 23:13:21
    当我们把这两种都声明到变量区的时候,字符串数组在栈区(变量呆的地方).字符串也会在栈区. 而指针字符串在栈区.指针字符串指向的字符串却到了常量区.这说明,此时字符串指针指向的那个字符串不可修改,因为是在

    在C语言中,我们用"随便写一些内容".来表示一个字符串.编译器会自动的在宿便写的一些内容后面加上一个'\0'来存储表示字符串结束了

    第一种存储方式是数组存储.第二种存储是字符串指针的形式存储

    当我们把这两种都声明到变量区的时候,字符串数组在栈区(变量呆的地方).字符串也会在栈区.

    而指针字符串在栈区.指针字符串指向的字符串却到了常量区.这说明,此时字符串指针指向的那个字符串不可修改,因为是在常量区.此时,我们只能通过修改字符串指针指向的地址来"改变"字符串指针中存储的内容,其实内容并没有改变.而是字符串指针指向的地址改变了.

    展开全文
  • Android中监听语言变化的两种方式

    千次阅读 2017-07-19 22:40:28
    Android中监听语言变化的方式有两种,通过在Activity里配置configChanges,然后重写onConfigurationChanged方法,另一种方式通过注册广播监听LOCALE_CHANGED,下面就来看下,这两种方式以及遇到的一些问题。...

    Android中监听语言变化的方式有两种,通过在Activity里配置configChanges,然后重写onConfigurationChanged方法,另一种方式通过注册广播监听LOCALE_CHANGED,下面就来看下,这两种方式以及遇到的一些问题。

    1.在Activity里配置configChanges

    1.1 在对应Activity里添加configChanges配置

            <activity
                android:name=".MainActivity"
                android:configChanges="locale|layoutDirection"
                android:exported="true"
                >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    在配置android:configChanges时,开始只配置了locale,发现改变语言时当app处于后台,并没有finish时,并不会在resume时调用Activity重写的onConfigurationChanged函数。原来是因为Android 4.2增加了layoutDirection属性,当改变语言设置后,该属性也会成newConfig中的一个mask位,所以ActivityManagerService(实际在ActivityStack)在决定是否重启Activity的时候总是判断为重启,所以在android:configChanges 中同时添加locale和layoutDirection时,才会在resume时调用Activity重写的onConfigurationChanged函数

    1.2 Activity里重写onConfigurationChanged函数

        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            Toast.makeText(this,"onConfigurationChanged language change "+newConfig.locale.toString(),Toast.LENGTH_SHORT).show();
            Log.d("jason","onConfigurationChanged newConfig:"+newConfig.toString());
        }
    上面的步骤就可以了吗,其实不然,还有件重要事情没干,在清单文件中添加下面权限:
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
    ps:这种方式监听语言切换,只有当当前activity没有被finish时才有效
    另外附上android:configChanges 可选值

    任何或所有下列字符串均是该属性的有效值。多个值使用“|”分隔 — 例如,“locale|navigation|orientation”。

    说明
    mcc IMSI 移动国家/地区代码 (MCC) 发生了变化 - 检测到了 SIM 并更新了 MCC。
    mnc IMSI 移动网络代码 (MNC) 发生了变化 - 检测到了 SIM 并更新了 MNC。
    locale 语言区域发生了变化 — 用户为文本选择了新的显示语言。
    touchscreen 触摸屏发生了变化。(这种情况通常永远不会发生。)
    keyboard 键盘类型发生了变化 — 例如,用户插入了一个外置键盘。
    keyboardHidden 键盘无障碍功能发生了变化 — 例如,用户显示了硬件键盘。
    navigation 导航类型(轨迹球/方向键)发生了变化。(这种情况通常永远不会发生。)
    screenLayout 屏幕布局发生了变化 — 这可能是由激活了其他显示方式所致。
    fontScale 字体缩放系数发生了变化 — 用户选择了新的全局字号。
    uiMode 用户界面模式发生了变化 — 这可能是因用户将设备放入桌面/车载基座或夜间模式发生变化所致。 请参阅 UiModeManager。 此项为 API 级别 8 中新增配置
    orientation 屏幕方向发生了变化 — 用户旋转了设备。

    :如果您的应用面向 API 级别 13 或更高级别(按照 minSdkVersion 和 targetSdkVersion 属性所声明的级别),则还应声明 "screenSize" 配置,因为当设备在横向与纵向之间切换时,该配置也会发生变化。

    screenSize 当前可用屏幕尺寸发生了变化。它表示当前可用尺寸相对于当前纵横比的变化,因此会在用户在横向与纵向之间切换时发生变化。 不过,如果您的应用面向 API 级别 12 或更低级别,则 Activity 始终会自行处理此配置变更(即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动 Activity)。

    此项为 API 级别 13 中新增配置。

    smallestScreenSize 物理屏幕尺寸发生了变化。它表示与方向无关的尺寸变化,因此只有在实际物理屏幕尺寸发生变化(如切换到外部显示器)时才会变化。 对此配置的变更对应于smallestWidth 配置的变化。 不过,如果您的应用面向 API 级别 12 或更低级别,则 Activity 始终会自行处理此配置变更(即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动 Activity)。

    此项为 API 级别 13 中新增配置。

    layoutDirection 布局方向发生了变化。例如,从从左至右 (LTR) 更改为从右至左 (RTL)。 此项为 API 级别 17 中新增配置。

    2.利用BroadcastReceiver注册监听语言切换的广播

    自定义LanguageReceiver,在AndroidManifest注册如下:
         <receiver
                android:name=".LanguageReceiver"
                android:enabled="true"
                android:exported="true">
                <intent-filter android:priority="1000">
                    <action android:name="android.intent.action.LOCALE_CHANGED"/>
                </intent-filter>
         </receiver>
    上面在receiver节点里有android:enabled和android:exported,下面分别看看这两个啥意思
    android:enabled 系统是否可将其实例化 — "true" 表示可以,“false”表示不可以。 默认值为“true”。
    android:exported 是否可由其他应用的组件启动 —“true”表示可以,“false”表示不可以。若为“false”,则只能由同一应用的组件或使用同一用户 ID 的不同应用启动。
    默认值取决于 Receiver 是否包含 Intent 过滤器,没有任何过滤器,默认值为“false”,反之默认值为“true”。
    当语言切换后,LanguageReceiver@onReceive方法会被调用
    public class LanguageReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO: This method is called when the BroadcastReceiver is receiving
            // an Intent broadcast.
            Log.d("jason", " LanguageReceiver onReceive");
            Toast.makeText(context,"LanguageReceiveronReceive ",Toast.LENGTH_SHORT).show();
        }
    }
    上面的广播的是哪发出的呢,忍不住跟踪了一把,最后发现是在ActivityManagerService.java发出来
    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
     private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
                boolean initLocale, boolean persistent, int userId, boolean deferResume) {
                    ...
                    if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
                        intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
                        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
    	            if (initLocale || !mProcessesReady) {
                            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                        }
                        broadcastIntentLocked(null, null, intent,
                                null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                                null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                    }
                    ...
    }
    展开全文
  • 串的类型定义以及三种表示形式

    千次阅读 2018-08-11 23:45:05
    引言  计算机处理的信息中,很大一部分包括字符串变量的处理。字符串变量时候也...所以,在学习串时,必要掌握它的三种表示方式:定长顺序存储表示、堆分配存储表示以及块链顺序存储表示。在表示方式后,需...

     引言   

    计算机处理的信息中,很大一部分包括字符串变量的处理。字符串变量有时候也简称为串。与链表、栈、队列结构的学习过程类似,在学习串的过程中,需要先了解其基本结构,然后是基本操作函数(例如插入删除修改等)。不同的是,由于串这个名词含义的复杂性,导致其本身就有着多种的表示方式。所以,在学习串时,有必要掌握它的三种表示方式:定长顺序存储表示、堆分配存储表示以及块链顺序存储表示。在表示方式后,需要掌握的是不同表示方式下的操作。

    正文

    一、串的定长顺序存储表示

      与顺序表的定义类似,使用定长存储串只需要分配一片连续的内存,即定义一个字符串类型的数组来存储字符即可完成在连续内存区域中存储的目的。在设置长度的时候,需要多留一位(字符串首位)以存储字符串的长度。该类表示方式的代码如下:

    #include <iostream>
    #define max 100
    using namespace std;
    typedef char S[max+1];

    在定长存储表示下,可以直接通过访问数组中的下标来访问字符串数组中的任意字符。这种访问方式有两种最直观的应用:串连接以及求子串。

    (1)串连接操作

    串连接操作的整体思路是,将两个定长为L1,L2的字符串数组S1,S2通过串值复制操作复制到新建的定长为L3的字符串数组S3中,当L1+L2>L3时,需要将串S2的一部分截断,若L1>L3时,需要将串S1的一部分截断。示意图如下所示:

    字符串连接示意图

     

    字符串连接代码如下所示:

    void Contact(char s1[101],char s2[101],char s3[101],int l1,int l2)
    {
        if(l1+l2<=max)
        {
            for(int i=1;i<=l1;i++)
            {
                s3[i]=s1[i];
            }
            for(int j=1;j<=l2;j++)
            {
                s3[l1+j]=s2[j];
            }
            s3[0]=(char)(l1+l2);
        }
        else if(l1<max)
        {
            for(int i=1;i<=l1;i++)
            {
                s3[i]=s1[i];
            }
            for(int k=l1+1;k<=max;k++)
            {
                s3[k]=s2[k-l1];
            }
            s3[0]=(char)max;
        }
        else{
            for(int j=0;j<max;j++)
            {
                s3[j]=s1[j];
            }
            s3[0]=(char)max;
        }
    }

     

     补充两个函数:1)初始化函数Init,初始化函数主要有两个步骤,包括输入字符串的字符数目以及输入字符,先定义新字符数组s,输入字符数目l。再通过for循环将字符打入字符数组内,字符数组的首位赋值为字符数目l。代码如下:

    void Init(char s[101],int l)
    {
        s[0]=(char)l;
        for(int i=1;i<=l;i++)
        {
            cin>>s[i];
        }
        s[l+1]='\0';
    }

    2)显示函数show,显示函数意为先通过strlen()函数求出字符串数组的长度,再由下标为1开始的for循环将字符挨个输出,代码如下:

    void show(char s[101])
    {
        int l=strlen(s);
        for(int i=1;i<=l;i++)
        {
            cout<<s[i];
        }
        cout<<endl;
        cout<<l<<endl;
    }

    这两个函数的主要目的是初始化字符数组以及检验字符的算法成果,在之后字符串的应用中也会多次使用到。

    (2)求子串操作

    对比串连接操作而言,求子串操作其实相对简单,主要的过程就是从母串下标为pos开始,复制长度为len的字符数组进入新的字串sub中,完成的仅仅只是一个字符串的复制过程。具体代码如下:

    void Sub(char s0[101],char s1[101],int pos,int len)
    {
        if(pos<1||pos>s1[0]||len<0||len>s1[0]-pos+1)
        {
            cout<<"Wrong"<<endl;
        }
        else
        {
            for(int i=1;i<=len;i++)
            {
                s0[i]=s1[pos+i-1];
            }
            s0[0]=len;
            s0[pos+len]='\0';
        }
    }

    二、堆分配存储表示

         由串定长分配存储的结构可以看出,在定长分配计算的过程中,如果出现字符串长度超过设定的母串最大长度时,必须要进行截取超出长度的处理。这就意味着,操作的复杂度会不断增加。为了改进这种情况,于是就出现了堆分配存储这一种串的存储方式。堆分配存储的直接概念是:以一段连续分配的地址作为存储字符串的地址,与定长不同的是,要求使用malloc()与free()函数进行内存的动态添加与删除。如果分配地址成功,要求返回一个指向起始地址的指针ch,方便进行后续内存的访问。

         串的堆分配存储代码如下:主要新建一个名为Hstring的结构体,结构体内部定义一个返回类型为char型的指针以及int型变量length。  

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    using namespace std;
    typedef struct
    {
        char *ch;
        int length;
    }Hstring;

        同之前的学习经验类似,在了解了串的堆分配结构后,开始了解其基本操作。首先是串的初始化函数。特别注意的是,串的初始化函数其实等同于生成一个值等于某个串常量的新串。这个操作本质上分为两步,首先是内存的分配,其次便是字符的复制。内存的分配首先要求出串的长度l,接着利用for循环通过控制下标赋值将单个字符按顺序复制,此处不同于串的定长存储,首位不需要放置长度。串的初始化代码如下:

    void Init(Hstring *h,char *chars)
    {
        int i=0;
        int len=0;
        if(h->ch)
        {
            free(h->ch);
        }
        for(i=0;chars[i]!='\0';i++);
        len=i;
        if(!i)
        {
            h->ch='\0';
            h->length=0;
        }
        else
        {
            h->ch=(char*)malloc(len*sizeof(char));
            for(i=0;i<len;i++)
          {
              h->ch[i]=chars[i];
          }
              h->length=len;
        }
        h->ch[i]=chars[i];
        h->length=i;
    }

         类似地,在定义了串的初始化操作后,需要完成的是串的显示操作,首先明确定义的显示操作对象为一个Hstring类型的变量记作h,可以访问其内部的指针ch(ch的返回类型为字符型),由指针的知识易得,通过for循环语句控制下标可以访问指针所指内存的下一段内存。通过赋值语句(将指针所指的内存的返回量赋值给字符)使得字符被输出。

    void show(Hstring *h)
    {
        for(int i=0;i<h->length;i++)
        {
            cout<<h->ch[i];
        }
        cout<<endl;
    }

          在完成了初始化操作以及显示操作后,开始定义串的字典序比较,求子串,连接函数。首先是串的字典序比较,字典序比较的主要特点是:首先定义两个Hstring类型的串,记作s与h。通过for循环控制两个串的下标i,通过i的增减来访问每一个字符。返回值用两者第一个不同的字符的字典序之差来表示。代码如下:

    int compare(Hstring*s,Hstring *h)
    {
        for(int i=0;i<s->length&&i<h->length;i++)
        {
            if(s->ch[i]!=h->ch[i])
            {
                return s->ch[i]-h->ch[i];
                break;
            }
        }
        return s->length-h->length;
    }

         接下来是串的求子串操作,与定长存储分配时的算法相同,先进行条件的判断,判断完成后进行一个字符串的求子串操作过程,本质上就是通过for循环控制下标,将特定顺序的字符复制到新串中去。并用一个新的返回类型为字符的指针去返回。代码如下:

    void Substring(Hstring *sub,Hstring *s,int pos,int len)
    {
        if(sub->ch)
            {
                free(sub->ch);
            }
        if(pos<0||pos>s->length||len<=0||len>s->length-pos+1)
        {
            cout<<"Wrong"<<endl;
        }
        if(!len)
        {
            sub->ch=NULL;
            sub->length=0;
        }
        else
        {
            sub->ch=(char*)malloc(len*sizeof(char));
            for(int i=0;i<=len-1;i++)
            {
                sub->ch[i]=s->ch[pos+i-1];
            }
                sub->length=len;
                sub->ch[len]='\0';
            }
    }

          串连接操作与定长存储时基本相同,只是不需要考虑固定长度时对字符串截取的影响,只需要给其分配正确长度的空间即可。主要操作就是通过for循环控制下标对字符串进行复制。具体代码如下:

    void contact(Hstring *h,Hstring *s1,Hstring *s2)
    {
        if(h->ch)
        {
            free(h->ch);
        }
        h->ch=(char*)malloc((s1->length+s2->length)*sizeof(char));
        for(int i=0;i<s1->length;i++)
        {
            h->ch[i]=s1->ch[i];
        }
        for(int j=0;j<s2->length;j++)
        {
            h->ch[s1->length+j]=s2->ch[j];
        }
        h->length=s1->length+s2->length;
    }

    三、串的块链存储表示

          串的块链存储表示,直白地说,就是用链表来表示串,存储串的信息。在串的定长存储与堆分配存储中,串的一个个字符都是作为单个的单元或者整体连续的内存开始存储的。在串的第三种存储方式,即块链存储表示中由于链表的结构因素,使得每一个节点会由不同的字符所组成,显而易见地,节点中的字符数目也不一定相同。由于串的长度不一定是节点大小的整倍数,则链表的最后一个节点不一定全部都是字符,相对地,可以由‘#’符号进行补齐。 需要注意的是,以链表存储串值时,需要同时设置一个尾指针来指示链表中的最后一个节点。基本结构代码以及示意图如下,(定义的CHUNKSIZE变量为单个节点中的字符数目,同时用变量blank代替字符‘#’):

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    using namespace std;
    #define CHUNKSIZE 5
    char blank ='#';
    typedef struct Chunk
    {
        char ch[CHUNKSIZE];
        struct Chunk *next;
    }chunk;
    typedef struct
    {
        Chunk *head,*tail;
        int curlen;
    }LString;
    串的块链存储示意图

         串的块链存储的基本操作如下:首先是初始化操作Init(LString *t),将指针t返回的对象的head指针与tail指针均初始化为NULL,同时将t所指结点的长度设为0,代码如下:

    void Init(LString *t)
    {
       (*t).head=(*t).tail=NULL;
       (*t).curlen=0;
    }

          与串的堆分配存储学习过程类似,在了解了串的初始化操作后,需要了解的是串的生成相同子串操作。整体操作的过程为新建一个返回LString为类型的指针t,并将字符串赋值给该指针所指的内存(相当于生成一个值等于串常量chars的串t)。在串的块链存储过程中,基本思路如下:1)进行条件的判断,如果字符串chars的长度l等于0或者字符串中出现了‘#’符号,则输出错误指示 2)求出节点的数量j,如果字符串长度(字符数目)是单个节点的大小的整数倍时,则节点的数量j等于l/size,若不是整数倍,则j的数量需要加1  3)在求出节点的数目j后,定义块链类型的指针p,q,通过for循环为指针p分配空间,初始化的p与q指针均指向头结点,每新建一个指针所指向的节点p,便将q结点的后继记作p节点,再将q节点后移一位。 4)通过for循环填补每个节点中的字符  5)如果此时chars指针的返回值为空(即已经没有字符可以输入节点了),则将结点中剩余的位置填补上‘#’字符  6)以上的步骤均是在j次for循环中每一步所实现的,等同于j个节点每一次都需要实现一次“新分配结点,后继结点的设立,填补字符”的步骤。  代码如下:

    void StrAssign(LString *t,char *chars)
    {
        Chunk*p,*q;
        int j,k,m;
        int l=strlen(chars);
        if(!l||strchr(chars,blank))
        {
            cout<<"Wrong"<<endl;
        }
        (*t).curlen=l;
        j=l/CHUNKSIZE;
        if(l%CHUNKSIZE)
        {
             j++;
        }
      for(k=0;k<j;k++)
        {
            p=(Chunk*)malloc(sizeof(Chunk));
            if(!p)
            {
                cout<<"Wrong"<<endl;
            }
            if(k==0)
            {
                q=p;
                (*t).head=q;
            }
            else
            {
                q->next=p;
                q=p;
            }
    
            for(m=0;m<CHUNKSIZE&&*chars;m++)
            {
                 *(q->ch+m)=*chars++;
            }
                 if(!*chars)
              {
                 (*t).tail=q;
                 q->next=NULL;
                 for(;m<CHUNKSIZE;m++)
                 {
                     *(q->ch+m)=blank;
                 }
    
              }
        }
    }

    串的截取子串操作是极其重要的一项操作,截取子串的基本过程就是在定义了初始的字符位序以及字符串长度后,将原串s中的字符复制到新串t中。基本思路如下:  1)先进行条件的判断,如果输入的pos值或Len值不符合要求,则输出为错误  2)确定结点的数目为n   3)新建头结点p以及n-1个剩余的结点q,将q按顺序连接,p不停赋值等于q,最后使结点p指向NULL,并使串t的尾指针指向p  4)最后一个结点剩余空位均用字符‘#’来填补  5)定义变量m与i,m用来表示在串t中的字符的位序,与字符处在的结点的位序i需要分开考虑。i的意义在于,表示了一个字符在每一个结点内的位序,而这个位序是不能大于CHUNKSIZE的  6)定义一个flag变量,当flag为1时,可以直接进行字符的复制,而不需要通过for循环来控制数目为n的结点访问.访问下一个结点的要求为i=CHUNKSIZE,字符串赋值的语句为*(q->ch+i)=*(p->ch+k);     代码如下:

    void Substring(LString*t,LString s,int pos,int len)
    {
        Chunk *p,*q;
        int n,i,flag=1;
        if(pos<1||pos>s.curlen||len<0||len>s.curlen-pos+1)
        {
            cout<<"Wrong"<<endl;
        }
        n=len/CHUNKSIZE;
        if(len%CHUNKSIZE)
        {
            n++;
        }
        p=(Chunk*)malloc(sizeof(Chunk));
        (*t).head=p;
        for(i=1;i<n;i++)
        {
            q=(Chunk*)malloc(sizeof(Chunk));
            p->next=q;
            p=q;
        }
        p->next=NULL;
        (*t).tail=p;
        (*t).curlen=len;
        for(i=len%CHUNKSIZE;i<len;i++)
        {
            *(p->ch+i)=blank;
        }
        q=(*t).head;
        i=0;
        int m=0;
        p=s.head;
        while(flag)
        {
            for(int k=0;k<CHUNKSIZE;k++)
            {
                if(*(p->ch+k)!=blank)
                {
                    m++;
                    if(n>=pos&&n<=pos+len-1)
                    {
                        if(i==CHUNKSIZE)
                        {
                            q=q->next;
                            i=0;
                        }
                        *(q->ch+i)=*(p->ch+k);
                        i++;
                        if(m==pos+len-1)
                        {
                            flag=0;
                            break;
                        }
                    }
                }
            }
            p=p->next;
        }
    }
    

          在掌握了求子串以及子串复制生成操作后,需要掌握其最后一个操作,即子串的连接。其主要的思路就是将LString s 与LString t两个子串进行串的复制,完成后进行串的连接。在字符串连接操作之前,首先需要完善字符串的复制函数Strcopy()。基本操作思路如下:1)要实现的过程为将串s的内容复制到串t之中,先定义串指针h,将其初始化为s的头指针,定义返回类型为Chunk的指针p,q,同时赋值上对应的长度(将s的长度赋给t) 2)将p作为每一个新建过程中新建的结点,每次循环与q指针交互赋值(将新的p指针所指结点连接至q指针后,再将q指针后继指为p)  3)通过while循环,当指示串s的指针h不为空时,将h指针的返回字符复制给p指针所指的内存   4)在循环完成后,将p指针所指结点的后继结点赋值为NULL,同时将p指针的结点定义为串t的尾指针指向的结点。   基本代码如下:

    void Strcopy(LString *t,LString s)
    {
        Chunk *h=s.head;
        Chunk *p,*q;
        (*t).curlen=s.curlen;
        if(h!=NULL)
        {
            (*t).head=(Chunk*)malloc(sizeof(Chunk));
            p=(*t).head;
            *p=*h;
            h=h->next;
            while(h)
            {
                q=p;
                p=(Chunk*)malloc(sizeof(Chunk));
                q->next=p;
                *p=*h;
                h=h->next;
            }
            p->next=NULL;
            (*t).tail=p;
        }
        else
        {
            cout<<"Wrong"<<endl;
        }
    }
    

          定义完成串的复制操作后最终串的连接操作也相对可以完成,基本思路如下:1)明确条件下基本操作为将串s1,s2复制并且连接为新串t  2)定义串a1,a2,并将s1,s2复制给串a1,a2   3)新串t的长度为a1a2的长度之和  4)新串t的头指针与a1的头指针相同,尾指针与a2的尾指针相同    5)定义a1的尾指针的后继为a2的头指针  6)借此可以直接通过访问指针t来达到访问s1,s2连接的结果。

    void StrContact(LString *t,LString s1,LString s2)
    {
        LString a1,a2;
        Init(&a1);
        Init(&a2);
        Strcopy(&a1,s1);
        Strcopy(&a2,s2);
        (*t).curlen=a1.curlen+a2.curlen;
        (*t).head=a1.head;
        a1.tail->next=a2.head;
        (*t).tail=a2.tail;
    }

     

    展开全文
  • 多维数组存储的两种方式

    万次阅读 2013-11-08 12:47:30
    1 数组存储的要求 数组存储的要求:连续存储。   连续:数组的n个元素对应n(或n+1)个内存地址,相邻元素的地址相邻。 ...相邻元素:对于一维数组来说,相邻...同一区域的内存都是连续的,不存在形象的矩阵等型
  • 动画的实现方式主要有两种:IAnimationTrack和ICamera。 一、Animation (1)、基于关键帧 (2)、设置每个关键帧的ImeStamp来确定播放时间(该帧占总播放时间的百分比) (3)、便于使用,集成了视频输出接口。可...
  • Nginx 中的两种限流方式

    万次阅读 2018-10-29 20:27:37
    限流即控制流量,本文将记录 Nginx 的二限流设置。 生活中的 “限流”? 限流并非新鲜事,在生活中亦无处不在,下面例举一二: 博物馆:限制每天参观总人数以保护文物 高铁安检:若干安检口,旅客依次排队,...
  • 一、防火墙简介 介绍: 防火墙是整个数据包进入主机前的第一道关卡。是一种位于内部网络与...管理防火墙的两种方式 : (1)firewalld 管理火墙的工具,相对简单 (2)iptables 复杂,功能强大 二、firewa...
  • 本文针对两种相似的数据增强方式——Random Erasing&Cutout进行解读。他们的相似点在于都是随机对输入图像遮挡一部分。 Random Erasing 论文下载链接:https://arxiv.xilesou.top/pdf/1708.04896.pdf 论文代码...
  • 粉色区域表示这块网卡ipv4地址 蓝色区域表示这块网卡的ipv6地址 二.进入虚拟网卡配置文件,修改ip地址,通过cd工具 1.“ cd /etc/sysconfig/network-scripts ” 进入network-scripts目录 2.“ ls ” 查看当前目录...
  • 队列的两种存储方式的介绍与实现

    千次阅读 2017-07-31 14:38:03
    队列是一特殊的线性表,它的特殊之处在于它必须在队列的头部进行删除元素,在队列尾部插入元素。我们把队列的头部称为对头(front),队列尾部叫做队尾 (rear)。进行删除元素位置叫队头(front),进行插入元素的位置叫...
  • C++中如何计算区域是否交集

    千次阅读 2013-08-24 03:18:30
    判断个矩形是否相交,可以自己写一个函数判断,也可以用你说的那个函数判断,但你说的那个函数主要的目的不是为了判断个矩形是否相交。 用该函数的方法:  HRGN hRgn1 = CreateRectRgn(rc1.left, rc1.top, rc...
  • 平面区域填充算法是计算机图形...区域填充中最常用的是多边形填色,本文中我们就讨论几多边形区域填充算法。一、种子填充算法(Seed Filling) 如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法...
  • C#中命名空间嵌套的两种方法

    千次阅读 2007-04-07 21:56:00
    在C#中一个重要的管理代码的方法,就是命名空间.现在我就和大家谈谈命名空间的两种表示形式:第一种方法:namespace a{ namespace b { //类区域 public class a
  • 运动区域提取算法及Matlab实现

    万次阅读 2011-07-17 19:34:37
    本文提出了一基于累积差分和数学形态学处理的运动区域提取算法。在时域窗口内,首先对图象进行降级处理得到灰度带图象,对灰度带差分图象累积并进行数学形态学处理得到运动目标的轨迹模版,将轨迹模版与当前帧差分...
  • 从图中可以看到结构体PodSpec个属性是Volumes,通过这个Volumes属性可以关联到结构体Volume和结构体VolumeSource,而且这个Volumes属性是一个数组类型,就是说POD可以关联到多个不同类型的卷上面。 结构体
  • ♥,.*,.♥,.*,.♥,.*,.♥,.*♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥♥,.*,.♥,.*,.♥,.*,.♥,.*♥,.*,.♥,.*,....2.区域填充(种子填充算法) ...4.多边形的扫描转换与区域填充比较 ♥,....
  • 计算机图形学——区域填充算法

    千次阅读 2019-10-07 15:08:04
    一、区域填充概念比奇中文网 https://m.biqi.org/ 区域:指已经表示成点阵形式的填充图形,是象素的集合。 区域填充:将区域内的一点...1、区域有两种表示形式 1)内点表示:枚举出区域内部的所有象素,内部所有象素...
  • 科研必备之图像局部区域放大(Matlab或QT实现)Matlab版本QT版本(含界面) 在撰写图像处理领域相关的论文中通常需要将图片的某个小块进行放大,以便论文审稿者看到图像清晰的细节信息,本文主要使用matlab和QT...
  • 容易混淆的是,这个词其实含义,适用于不同的场合,必须加以区分。 含义一:数据结构 stack的第一含义是一组数据的存放方式,特点为LIFO,即后进先出(Last in, first out)。 在这种数据结构中,数据
  • 区域生长(基于区域的图像分割)

    千次阅读 2014-05-08 14:51:16
    1. 区域生长 区域增长方法是根据同一物体区域内象素的相似性质来聚集象素点的方法,从初始区域(如小邻域或甚至于每... 区域增长方法是一比较普遍的方法,在没有先验知识可以利用时,可以取得最佳的性能,可以用来
  • 对于这样一个分段函数而言,以下两种方式可以很好的解决 利用逻辑表达式 比如第一个就可以表示为: 即当 t 在某一个范围内那段函数才生效,否则乘上逻辑式因子就为 0,得到的效果图如下: 利用...
  • 此次研究两种图像分割法,分别是基于形态学的分水岭算法和基于图割理论的GrabCut算法。OpenCV均提供了两张算法或其变种。鉴于研究所需,记录一些知识点,开发平台为OpenCV2.4.9+Qt5.3.2。 一、使用分水岭算法进行...
  • OSPF Stub区域与NSSA区域

    千次阅读 2019-09-03 17:44:32
    Stub:OSPFSTUB区域是一个末梢区域,当一个OSPF区域处于整个自治系统边界时,而又不含其他路由协议,这时就可以配置OSPF Stub区域。 NSS:OSPF路由协议是目前因特网中应用最为广泛一IGP,而NSSA则是在该协议...
  • 代码的两种命名方法:驼峰命名、匈牙利命名(优缺点) 一、骆驼命名法:  小驼峰法(camel方法)变量一般用小驼峰法标识。  第一个单词以小写字母开始;第二个单词的首字母大写或每一个单词的首字母都采用大写...
  • 区域生长算法原理及MATLAB实现

    万次阅读 多人点赞 2016-03-13 21:20:57
    1. 基于区域生长算法的图像分割原理 数字图像分割算法一般是基于灰度值的个基本特性之一:不连续性和相似性。前一性质的应用途径是基于图像灰度...令R表示整幅图像区域,那么分割可以看成将区域R划分为n个子区域R1
  • 接上文 计算机图形学 学习笔记(二):多边形扫描转换:X扫描线算法 和 改进的X扫描线...区域可采用* 内点表示* 和 边界表示 两种表示形式。 内点表示:枚举出区域内部的所有像素,内部的所有像素着同一个颜色,边界像
  • C++中表示字符串的两种类型:C字符串和string 一、C字符串, 1、表示字符串时,将字符串表示成一个基类型为char的一个数组,其中数组的最后一个元素一定是’\0’,为C字符串的结束标记,称为空字符;以这种方式存储的...
  • 两种改进的LPB算法,CLBP和ELBP

    千次阅读 2018-05-31 14:24:55
    最近看了篇关于CLBP和ELBP的文章。现在对我所了解的LBP相关知识做一个小小的总结传统LBP其中$g_{c}$是中心像素的灰度值,$g_{p}$是其邻域像素的灰度值。通过比较中心像素周围邻域像素与中心像素的大小,大于中心...
  • OpenCV2学习笔记(四):两种图像分割方法比较

    万次阅读 多人点赞 2015-02-23 16:16:44
    此次研究两种图像分割法,分别是基于形态学的分水岭算法和基于图割理论的GrabCut算法。OpenCV均提供了两张算法或其变种。鉴于研究所需,记录一些知识点,开发平台为OpenCV2.4.9+Qt5.3.2。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 395,738
精华内容 158,295
关键字:

区域的表示有哪两种形式