成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

設(shè)計(jì)一個(gè)C語言的動態(tài)擴(kuò)容緩沖區(qū)-創(chuàng)新互聯(lián)

知識要點(diǎn)
  1. 字符串
  2. 面向?qū)ο蟮腃語言設(shè)計(jì)
  3. 動態(tài)內(nèi)存分配
  4. Linux 文件 API
  5. 獲取線路


正文
struct strbuf {int len;     //當(dāng)前緩沖區(qū)(字符串)長度
  int alloc;   //當(dāng)前緩沖區(qū)(字符串)容量
  char *buf;   //緩沖區(qū)(字符串)
};

HINT:

創(chuàng)新互聯(lián)從2013年創(chuàng)立,先為武陟等服務(wù)建站,武陟等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為武陟企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
  • strbuf 的成員 len 代表的是 buf 緩沖區(qū)的長度,每次我們將字符串追加入 strbuf 中,我們都應(yīng)該使用 strbuf_setlen() 去更新 strbuf 的長度 len,注意 123\0456 的長度不是 3,而是 7。
  • strbuf 的成員 alloc 代表的是 buf 緩沖區(qū)的容量,也就是我們每次動態(tài)分配的數(shù)組大小,每當(dāng)我們需要向 sb 內(nèi)追加一個(gè)字符串,我們需要計(jì)算當(dāng)前的字符串長度加上追加的字符串長度,如果超過了當(dāng)前的容量,我們就需要把容量擴(kuò)大一倍,然后將字符串添加進(jìn)去。

在這里插入圖片描述

//初始化 sb 結(jié)構(gòu)體,容量為 alloc。
void strbuf_init(struct strbuf *sb, size_t alloc)//數(shù)據(jù)類型解釋見下
{sb->len=0;
    sb->alloc=alloc;
    sb->buf=(char *)malloc(sizeof(char)*alloc);//強(qiáng)制類型轉(zhuǎn)換(void*--char*)
    strcpy(sb->buf,"");
}


//將字符串填充到 sb 中,長度為 len, 容量為 alloc。
void strbuf_attach(struct strbuf *sb, void *str, size_t len, size_t alloc)
{sb->buf=(char*)str;//強(qiáng)制類型轉(zhuǎn)換(void*--char*)
    sb->len=len;
    sb->alloc=alloc;
}


//釋放 sb 結(jié)構(gòu)體的內(nèi)存。
void strbuf_release(struct strbuf *sb)
{free(sb->buf);//參數(shù)是malloc()返回的地址,當(dāng)時(shí)用buf存該地址
    sb->buf=NULL;//把指針設(shè)為NULL
    sb->len=0;
    sb->alloc=0;
}


//交換兩個(gè) strbuf。
void strbuf_swap(struct strbuf *a, struct strbuf *b)
{struct strbuf t;
    
法一:
    t=*a;
    *a=*b;
    *b=t;
    
法二:
    t.len=a->len;
    t.alloc=a->alloc;
    t.buf=a->buf;
    
    a->len=b->len;
    a->alloc=b->alloc;
    a->buf=b->buf;

    b->len=t.len;
    b->alloc=t.alloc;
    b->buf=t.buf;
    
}


//將 sb 中的原始內(nèi)存取出,并將 sz 設(shè)置為其 alloc 大小 。
char *strbuf_detach(struct strbuf *sb, size_t *sz)
{*sz=sb->alloc;//sz=&(sb->alloc)編譯錯(cuò)誤
                  //因?yàn)閏annot convert ‘int*’ to ‘size_t*’ {aka ‘long unsigned int*’} in assignment
    return sb->buf;//注意函數(shù)的返回類型
}


//比較兩個(gè) strbuf 的內(nèi)存是否相同。
int strbuf_cmp(const struct strbuf *first, const struct strbuf *second)
{// int tag=1;錯(cuò)
    // if(first->len!=second->len)tag=0;
    // if(first->alloc!=second->alloc)tag=0;
    // if(strcmp(first->buf,second->buf)!=0)tag=0;
    // return tag;//相同‘1’,不同‘0’
    
    if(first->len>second->len)
        return 1;
    if(first->lenlen)
        return -1;
    else 
        return 0;
}


//清空 sb 。
void strbuf_reset(struct strbuf *sb)//清空指的是讓內(nèi)存沒有東西,而非釋放(128G內(nèi)存恢復(fù)出場設(shè)置)
{// sb->len=0;錯(cuò)
    // sb->alloc=0;
    // free(sb->buf);
    // sb->buf=NULL;

法一:
    int i; 
    for(i=0;ilen;i++){sb->buf[i]='\0';
     }
     sb->len=0;
    // sb->alloc=0  因?yàn)閍lloc是申請到的內(nèi)存大小,所以不能令為零(否則恢復(fù)出場設(shè)置后128G空間都沒了)

法二:
    memset(sb->buf,0,sb->len);//函數(shù)解釋見下
    sb->len=0;
    
}

size_t

無符號整數(shù),32位下為unsigned int,64位下為unsigned long
在數(shù)組下標(biāo)和內(nèi)存管理函數(shù)之類的地方廣泛使用

memset

void *memset(void *s, int c, size_t n);

  • s指向要填充的內(nèi)存塊。
    c是要被設(shè)置的值。
    n是要被設(shè)置該值的字符數(shù)。
    返回類型是一個(gè)指向存儲區(qū)s的指針。

在這里插入圖片描述

//確保在 len 之后 strbuf 中至少有 extra 個(gè)字節(jié)的空閑空間可用。
  //(128G總內(nèi)存空間在已用100G后,確保至少有30G空閑空間可以用)->如果不夠,再申請一塊內(nèi)存(再買內(nèi)存卡)
void strbuf_grow(struct strbuf *sb, size_t extra)
{if(sb->alloc-sb->len< extra){sb->buf=(char*)realloc(sb->buf,sb->alloc+extra);//默認(rèn)buf之前申請過一塊內(nèi)存,返回值為剛申請到的內(nèi)存首地址
        sb->alloc += extra;                             //函數(shù)解釋見下
    }
}


//向 sb 追加長度為 len 的數(shù)據(jù) data 。
void strbuf_add(struct strbuf *sb, const void *data, size_t len)
{// if(sb->len+len<= sb->alloc){ //錯(cuò)
    //     sb->buf=strcat(sb->buf,(const char*)data);//(要不要強(qiáng)制類型轉(zhuǎn)換為char*?)要!
    // }
    // else {//     strbuf_grow(sb,sb->alloc);//再來一倍
    //     sb->buf=strcat(sb->buf,(const char*)data);
    // }
    // sb->len+=len;
    
法一:
    if(sb->len+len >= sb->alloc)
    {sb->buf=(char*)realloc(sb->buf,sb->len+len+1);//包括\0
        sb->alloc=sb->len+len+1;//更新擴(kuò)容后的內(nèi)存大小256G
    }
    
法二:
	strbuf_grow(sb->buf,len+1);
	
    memcpy(sb->buf+sb->len,data,len);//函數(shù)解釋見下
    sb->len+=len;
    // sb->buf+sb->len='\0'; //錯(cuò)
    //*(sb->buf+sb->len)='\0';  //ok!
    sb->buf[sb->len]='\0';

}


//向 sb 追加一個(gè)字符 c。
void strbuf_addch(struct strbuf *sb, int c)
{// char a[1];
    // a[0]=c;
	// if(sb->len+1<= sb->alloc)
	//     sb->buf=strcat(sb->buf,a);
	// else {//     strbuf_grow(sb,sb->alloc);
	//     sb->buf=strcat(sb->buf,a);
	// }
	// sb->len+=1;

法一:
    if(sb->len+1 >= sb->alloc){sb->buf=(char*)realloc(sb->buf,(sb->alloc)*2);//內(nèi)存翻兩倍
        sb->alloc=sb->alloc*2;
    }
    memcpy(sb->buf+sb->len,&c,1);
    sb->len+=1;
    sb->buf[sb->len]='\0';

法二:
	strbuf_add(sb,&c,1);

}


//向 sb 追加一個(gè)字符串 s。
void strbuf_addstr(struct strbuf *sb, const char *s)
{法一:
    int n=strlen(s);
    if(sb->len+n >= sb->alloc){sb->buf=(char*)realloc(sb->buf,sb->len+n+1);
        sb->alloc=sb->len+n+1;
    }
    memcpy(sb->buf+sb->len,s,n);
    // sb->buf=strcat(sb->buf,s); 錯(cuò)->解釋見下
    sb->len+=n;
    sb->buf[sb->len]='\0';

法二:
	strbuf_add(sb,s,strlen(s));
}


//向一個(gè) sb 追加另一個(gè) strbuf 的數(shù)據(jù)。
void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)//追加一個(gè)結(jié)構(gòu)體
{法一:
    if(sb->len+sb2->len >= sb->alloc){sb->buf=(char*)realloc(sb->buf,sb->len+sb2->len+1);
        sb->alloc=sb->len+sb2->len+1;
    }
    sb->buf=strcat(sb->buf,sb2->buf);
    sb->len+=sb2->len;

法二:
	strbuf_addstr(sb,sb2->buf);
}


//設(shè)置 sb 的長度 len。
void strbuf_setlen(struct strbuf *sb, size_t len)
{if(len >= sb->alloc)//(要安裝應(yīng)用,先判斷是否裝的下)
    {sb->buf=(char*)realloc(sb->buf,len+1);
        sb->alloc=len+1;
    }
    sb->len=len;
    sb->buf[sb->len]='\0';
}


//計(jì)算 sb 目前仍可以向后追加的字符串長度。
size_t strbuf_avail(const struct strbuf *sb)
{return (sb->alloc-(sb->len+1));//末尾的\0
}


//向 sb 內(nèi)存坐標(biāo)為 pos 位置插入長度為 len 的數(shù)據(jù) data 。
void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
{if(sb->len+len >sb->alloc){strbuf_grow(sb,len+1);
    }
    // int i;錯(cuò)
    // char a[len];
    // strcpy(a,(const char*)data);
    // for(i=0;i//     sb->buf[pos+i]=a[i];  //默認(rèn)原來位置沒有數(shù)據(jù)->不行
    // }
    memmove(sb->buf+pos+len,sb->buf+pos,sb->len-pos);//把pos位置后面的數(shù)據(jù)移到pos+len的地方,空出來的len長度來存放data,函數(shù)解釋見下
    memcpy(sb->buf+pos,data,len);//sb->buf[pos]錯(cuò)
    sb->len+=len;
    sb->buf[sb->len]='\0';
}

realloc

void* realloc(void* memblock, size_t size)

  • memblock: 先前開辟的內(nèi)存塊的指針(也就是malloc或calloc之前申請的那塊內(nèi)存空間,即需要調(diào)整大小的內(nèi)存空間)
  • size: New size in bytes,新的字節(jié)數(shù),注意不是增加的字節(jié)數(shù),而是新開辟的那塊內(nèi)存空間的字節(jié)數(shù)(sizeof(…))
  • 返回值: 新內(nèi)存的起始地址(一般要xx=realloc)

memcpy

void *memcpy(void *dest, void *source, size_t n)

  • dest:指向用于存儲復(fù)制內(nèi)容的目標(biāo)數(shù)組
  • source:指向要復(fù)制的數(shù)據(jù)源
  • n :要被復(fù)制的字節(jié)數(shù)(sizeof(…))
  • 返回值:指向dest的指針(一般不用xx=,而是直接調(diào)用即可)

1.正常在復(fù)制字符串時(shí)用strcpy,而需要復(fù)制其他類型數(shù)據(jù)時(shí)則一般用memcpy
2.strcpy不需要指定長度,它遇到被復(fù)制字符的串結(jié)束符"\0"才結(jié)束,所以容易溢出。memcpy則可控制需要復(fù)制長短n
3.source和destin所指的內(nèi)存區(qū)域可能重疊,但是如果source和dest所指的內(nèi)存區(qū)域重疊,那么這個(gè)函數(shù)并不能夠確保source所在重疊區(qū)域在拷貝之前不被覆蓋。而使用memmove可以用來處理重疊區(qū)域。

memmove

void *memmove(void *dest, const void *source, size_t n)

  • dest:指向用于存儲復(fù)制內(nèi)容的目標(biāo)數(shù)組
  • source:指向要復(fù)制的數(shù)據(jù)源
  • n:要被復(fù)制的字節(jié)數(shù)
  • 返回值:指向dest的指針(一般不用xx=,而是直接調(diào)用即可)

能夠?qū)Ρ旧磉M(jìn)行覆蓋拷貝的函數(shù),其又同時(shí)兼?zhèn)淞?memcpy函數(shù) 可做的事


在這里插入圖片描述

//去除 sb 緩沖區(qū)左端的所有 空格,tab,'\t'。
void strbuf_ltrim(struct strbuf *sb)
{while((*(sb->buf)==' '||sb->buf[0]=='\t')&&sb->buf[0]!='\0')//這兩種都可以,就是不行sb->buf==' ',因?yàn)?    {                //C++ forbids comparison between pointer and integer
        sb->buf=(char*)memmove(sb->buf,sb->buf+1,sb->len-1);//全部向左平移一位
        sb->len--;
    }
}


//去除 sb 緩沖區(qū)右端的所有 空格,tab, '\t'。
void strbuf_rtrim(struct strbuf *sb)
{while((sb->buf[(sb->len)-1]==' '||sb->buf[(sb->len)-1]=='\t')&&sb->buf[(sb->len)-1]!='\0')
    {// sb->buf+(sb->len)-1='\0';錯(cuò)
        // sb->buf=(char*)memmove(sb->buf+(sb->len)-1,sb->buf+(sb->len),1);
        sb->buf[(sb->len)-1]='\0';
        sb->len--;
    }
}


//刪除 sb 緩沖區(qū)從 pos 坐標(biāo)長度為 len 的內(nèi)容。
void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
{// int i;多此一舉
    // for(i=0;i//     sb->buf[pos+i]=0;
    // }
    memmove(sb->buf+pos,sb->buf+pos+len,sb->len-pos-len);//strlen(sb->buf+pos+len)+1  OK!
    sb->len=sb->len-len;
    sb->buf[sb->len]='\0';
}

在這里插入圖片描述

//sb 增長 hint ? hint : 8192 大小, 然后將文件描述符為 fd 的所有文件內(nèi)容追加到 sb 中。
ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)//數(shù)據(jù)類型解釋見下
{ssize_t result; //根據(jù)函數(shù)返回值定數(shù)據(jù)類型
    sb->buf=(char*)realloc(sb->buf,sb->alloc+(hint ? hint : 8192));//不是sb->len+(...)
    sb->alloc+=(hint ? hint : 8192);
    
    result=read(fd,sb->buf+sb->len,sb->alloc-sb->len-1);//函數(shù)解釋見下
    if(result){sb->len+=result;
        sb->buf[sb->len]='\0';
    }
    return result;
}


//將 將文件句柄為 fp 的一行內(nèi)容(拋棄換行符)讀取到 sb 。
int strbuf_getline(struct strbuf *sb, FILE *fp)
{char ch;
	// ch=fgetc(fp); //返回值為int,然后再ch!=EOF ->ok因?yàn)镋OF=-1
	法一:
	while((ch = fgetc(fp))!='\n' && ch!=EOF)
	{		strbuf_addch(sb, ch);
	}
	法二:
	while((ch = fgetc(fp))!='\n' && feof(fp)==0)//順序不能錯(cuò),函數(shù)解釋見下
	{		strbuf_addch(sb, ch);
	}
    return 1;
}

read

ssize_t read(int fd ,void *buf, size_t count);
作用:從文件描述符對應(yīng)的文件讀取數(shù)據(jù),調(diào)用成功返回讀出的字節(jié)數(shù)
頭文件:include

  • fd:文件描述符
  • buf:讀出數(shù)據(jù)的緩沖區(qū)(將文件中讀出目標(biāo)數(shù)據(jù),放入buf緩沖區(qū)中)
  • count:每次讀取的字節(jié)數(shù)(是請求讀取的字節(jié)數(shù),讀上來的數(shù)據(jù)保存在緩沖區(qū)buf中,同時(shí)文件的當(dāng)前讀寫位置向后移)
  • 返回值:成功返回讀出的字節(jié)數(shù);失敗返回-1;EOF返回0

ssize_t

有符號整型,在32位機(jī)器上等同與int,在64位機(jī)器上等同與long int

文件描述符

  • 操作系統(tǒng)利用文件描述符來訪問文件。
  • 文件描述符是非負(fù)整數(shù)。
  • 打開現(xiàn)存文件或新建文件時(shí),內(nèi)核會返回一個(gè)文件描述符。
  • 讀寫文件也需要使用文件描述符來指定待讀寫的文件。
  • 只要獲取到文件描述符,就可以找到對應(yīng)的文件

文件句柄pf/fp

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
出錯(cuò)返回NULL

fgetc

int fgetc(FILE *filename)

  • 在文件處理中,通過fgetc()函數(shù),我們從輸入流中獲取下一個(gè)字符,并將文件指針加1 (調(diào)用一次,filename向后移動一位)
  • 返回一個(gè)整數(shù)值,該值是無符號char的轉(zhuǎn)換。 它還返回EOF ,而EOF也是一個(gè)整數(shù)值-1 。

在這里插入圖片描述

feof

int feof(FILE *fp)

  • 當(dāng)文件被打開,光標(biāo)處于默認(rèn)的開頭時(shí),光標(biāo)后都有信息,這時(shí)候調(diào)用feof()來查看光標(biāo)后是否還有內(nèi)容,就沒意義
  • 先使用getc(),從文件中讀取一個(gè)字符,讓光標(biāo)向后移動一個(gè)字符。這時(shí)空文件的光標(biāo)就已經(jīng)移動到EOF的后面,這時(shí)使用feof()就會返回1了
  • 原理:站在光標(biāo)所在位置,向后看看還有沒有字符。如果有,返回0如果沒有,返回非0。它并不會讀取相關(guān)信息,只是查看光標(biāo)后是否還有內(nèi)容。

在這里插入圖片描述

//實(shí)現(xiàn)字符串切割
//將長度為 len 的字符串 str 根據(jù)切割字符 terminator 切成多個(gè) strbuf,并從結(jié)果返回,
//max 可以用來限定大切割數(shù)量。返回 struct strbuf 的指針數(shù)組,數(shù)組的最后元素為 NULL
struct strbuf **strbuf_split_buf(const char *str, size_t len, int terminator, int max)
{//分配內(nèi)存
    struct strbuf **p=(struct strbuf**)malloc(sizeof(struct strbuf*)*(max+1));//切3次,有3+1塊
                   //由于要返回struct strbuf的指針數(shù)組,因此定義**p,相當(dāng)于*p[],
                   //即數(shù)組p里面每個(gè)單元都是一個(gè)struct strbuf*指針,單獨(dú)指向一個(gè)結(jié)構(gòu)體(而每個(gè)結(jié)構(gòu)體的buf指向一塊內(nèi)存空間,所以下面需要兩次申請malloc)
//指針保存被切割字符串的首末地址
    const char *begin=str;
    const char *end=str+len;  // 字符串str \0的位置
    const char *next;
    int i=0;
    int len2;
//首元素是被切割字符的話,就直接跳過(p[]里放空內(nèi)容沒有意義)
    while(*begin==terminator)
        begin++;
//從第一個(gè)非切割字符開始,往后遍歷整個(gè)str,找切割字符terminator
    for (next=begin;next<=end;next++)
    {if (*next==terminator||next==end)//注意是否要*
        {len2=next-begin;//地址之差,長度即為小塊的字符串
            p[i]=(struct strbuf*)malloc(sizeof(struct strbuf));//為指針p[i]所指向的結(jié)構(gòu)體申請一塊內(nèi)存,用于存放結(jié)構(gòu)體(然后p[i]指向了這塊空間,也就指向了那個(gè)結(jié)構(gòu)體)
            p[i]->len=len2;
            p[i]->alloc=len2+1;
            p[i]->buf=(char*)malloc(sizeof(char)*(len2+1));// 因?yàn)榻Y(jié)構(gòu)體里的buf為指針,又指向了一塊內(nèi)存,所以向上面各個(gè)函數(shù)一樣,malloc?。ㄗ⒁鈂0)
            memcpy(p[i]->buf,begin,len2);//len2長度的限制,從而實(shí)現(xiàn)將一小塊字符串拷貝到buf中
            *(p[i]->buf+len2)='\0';
            i++;
           //連續(xù)的切割字符沒有意義,跳過
            while(*next==terminator&&next<=end)
                next++;
           //新的頭(每切一塊,頭就向后移動對應(yīng)的長度)
            begin=next;
        }
        if(i==max)
            break;
    }
    p[i]=NULL;
    return p;
}


//實(shí)現(xiàn)判斷一個(gè) strbuf 是否以指定字符串開頭的功能
//target_str:目標(biāo)字符串,str:前綴字符串,strnlen:target_str 長度,前綴相同返回 true 失敗返回 false
bool strbuf_begin_judge(char* target_str, const char* str, int strnlen)//返回值解釋見下
{法一:
     if(strnlen==0 || memcmp(target_str,str,strlen(str))==0)//相同返回0,函數(shù)解釋見下
         return true;
     else 
         return false;

法二:
    int i;
    for(i=0;iif(str[i]=='\0')
            break;
        if(target_str[i]!=str[i])
            return false;
    }
    return true;
}


//獲取字符串從坐標(biāo) [begin, end) 的所有內(nèi)容(可以分成引用和拷貝兩個(gè)模式)
//target_str:目標(biāo)字符串,begin:開始下標(biāo),end:結(jié)束下標(biāo),len:target_buf的長度
//下標(biāo)從0開始,[begin, end)區(qū)間,參數(shù)不合法返回 NULL
char* strbuf_get_mid_buf(char* target_buf, int begin, int end, int len)
{if(end

memcmp

int memcmp(const void *str1, const void *str2, size_t n)

  • str1 : 指向內(nèi)存塊的指針
  • str2 : 指向內(nèi)存塊的指針
  • n : 要被比較的字節(jié)數(shù)
  • 返回值 :當(dāng)str1????當(dāng)str1=str2時(shí),返回值=0
    ????當(dāng)str1>str2時(shí),返回值>0

如果兩個(gè)字符串相同而且n大于字符串長度的話,memcmp不會在\0處停下來,會繼續(xù)比較\0后面的內(nèi)存單元,直到_res不為零或者達(dá)到n的次數(shù)。

  • 但strncmp必定會在最短的字符串的末尾停下來,即使count還未為零

boll

頭文件:include
只能用來存放兩個(gè)值:true (1) 和 false (0)

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁名稱:設(shè)計(jì)一個(gè)C語言的動態(tài)擴(kuò)容緩沖區(qū)-創(chuàng)新互聯(lián)
文章源于:http://jinyejixie.com/article38/hgdsp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)定制網(wǎng)站、域名注冊、品牌網(wǎng)站建設(shè)網(wǎng)站排名、標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

平乡县| 阳春市| 清徐县| 海城市| 定兴县| 柳河县| 定陶县| 麻城市| 灵璧县| 泾川县| 祥云县| 绥德县| 平果县| 长乐市| 和平区| 金堂县| 仙桃市| 葫芦岛市| 北安市| 墨脱县| 巴彦淖尔市| 分宜县| 运城市| 资源县| 牙克石市| 隆子县| 静乐县| 荥经县| 平潭县| 临颍县| 子洲县| 临洮县| 祁连县| 榆中县| 冕宁县| 仁化县| 会宁县| 锡林浩特市| 山阴县| 红桥区| 尼玛县|