说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

字符数组-C语言教程

HTML文档下载 WORD文档下载 PDF文档下载
在C语言中,数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。用来存放字符量的数组称为字符数组。
7.3 字符数组
用来存放字符量的数组称为字符数组。
7.3.1 字符数组的定义
形式与前面介绍的数值数组相同。
例如:
    char c[10];
由于字符型和整型通用,也可以定义为int c[10]但这时每个数组元素占2个字节的内存单元。
字符数组也可以是二维或多维数组。
例如:
    char c[5][10];
即为二维字符数组。
7.3.2 字符数组的初始化
字符数组也允许在定义时作初始化赋值。
例如:
    char c[10]={‘c’, ‘  ’, ‘p’, ‘r’, ‘o’, ‘g’, ‘r’, ‘a’,’m’};
赋值后各元素的值为:
    数组C    c[0]的值为‘c’
c[1]的值为‘ ’
c[2]的值为‘p’ 
c[3]的值为‘r’
c[4]的值为‘0’
c[5]的值为‘g’
c[6]的值为‘r’
c[7]的值为‘a’
c[8]的值为‘m’
其中c[9]未赋值,由的值为‘p’系统自动赋予0值。
当对全体元素赋初值时也可以省去长度说明。
例如:
    char c[]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`};
这时C数组的长度自动定为9。
7.3.3 字符数组的引用
【例7.8】
main(){  int i,j;  char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}};  for(i=0;i<=1;i++)    {      for(j=0;j<=4;j++)          printf("%c",a[i][j]);      printf("\n");    }}
本例的二维字符数组由于在初始化时全部元素都赋以初值,因此一维下标的长度可以不加以说明。
7.3.4 字符串和字符串结束标志
在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。前面介绍字符串常量时,已说明字符串总是以'\0'作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符'\0'存入数组,并以此作为该字符串是否结束的标志。有了'\0'标志后,就不必再用字符数组的长度来判断字符串的长度了。
C语言允许用字符串的方式对数组作初始化赋值。
例如:
    char c[]={'c', ' ','p','r','o','g','r','a','m'};
可写为:
        char c[]={"C program"};
    或去掉{}写为:
        char c[]="C program";
用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志'\0'。上面的数组c在内存中的实际存放情况为:

C

 

p

r

o

g

r

a

m

\0

    ‘\0'是由C编译系统自动加上的。由于采用了‘\0'标志,所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。
7.3.5 字符数组的输入输出
在采用字符串方式后,字符数组的输入输出将变得简单方便。
除了上述用字符串赋初值的办法外,还可用printf函数和scanf函数一次性输出输入一个字符数组中的字符串,而不必使用循环语句逐个地输入输出每个字符。
【例7.9】
main(){  char c[]="BASIC\ndBASE";  printf("%s\n",c);}
注意在本例的printf函数中,使用的格式字符串为“%s”,表示输出的是一个字符串。而在输出表列中给出数组名则可。不能写为:
printf("%s",c[]);
【例7.10】
main(){  char st[15];  printf("input string:\n");  scanf("%s",st);  printf("%s\n",st);}
本例中由于定义数组长度为15,因此输入的字符串长度必须小于15,以留出一个字节用于存放字符串结束标志`\0`。应该说明的是,对一个字符数组,如果不作初始化赋值,则必须说明数组长度。还应该特别注意的是,当用scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符。
例如当输入的字符串中含有空格时,运行情况为:
    input string:
        this is a book
输出为:
this
从输出结果可以看出空格以后的字符都未能输出。为了避免这种情况,可多设几个字符数组分段存放含空格的串。
程序可改写如下:
【例7.11】
main(){  char st1[6],st2[6],st3[6],st4[6];  printf("input string:\n");  scanf("%s%s%s%s",st1,st2,st3,st4);  printf("%s %s %s %s\n",st1,st2,st3,st4);}
    本程序分别设了四个数组, 输入的一行字符的空格分段分别装入四个数组。然后分别输出这四个数组中的字符串。
在前面介绍过,scanf的各输入项必须以地址方式出现,如 &a,&b等。但在前例中却是以数组名方式出现的,这是为什么呢?
这是由于在C语言中规定,数组名就代表了该数组的首地址。整个数组是以首地址开头的一块连续的内存单元。
如有字符数组char c[10],在内存可表示如图。

C[0]

C[1]

C[2]

C[3]

C[4]

C[5]

C[6]

C[7]

C[8]

C[9]

设数组c的首地址为2000,也就是说c[0]单元地址为2000。则数组名c就代表这个首地址。因此在c前面不能再加地址运算符&。如写作scanf("%s",&c);则是错误的。 在执行函数printf("%s",c) 时,按数组名c找到首地址,然后逐个输出数组中各个字符直到遇到字符串终止标志'\0'为止。
7.3.6 字符串处理函数
C语言提供了丰富的字符串处理函数, 大致可分为字符串的输入、输出、合并、修改、比较、转换、复制、搜索几类。 使用这些函数可大大减轻编程的负担。用于输入输出的字符串函数,在使用前应包含头文件"stdio.h",使用其它字符串函数则应包含头文件"string.h"。
下面介绍几个最常用的字符串函数。
1. 字符串输出函数 puts
   格式:  puts (字符数组名)
   功能:把字符数组中的字符串输出到显示器。 即在屏幕上显示该字符串。
【例7.12】
#include"stdio.h"main(){  char c[]="BASIC\ndBASE";  puts(c);}
    从程序中可以看出puts函数中可以使用转义字符,因此输出结果成为两行。puts函数完全可以由printf函数取代。当需要按一定格式输出时,通常使用printf函数。
2. 字符串输入函数gets
   格式:  gets  (字符数组名)
   功能:从标准输入设备键盘上输入一个字符串。
 本函数得到一个函数值,即为该字符数组的首地址。
【例7.13】
#include"stdio.h"main(){  char st[15];  printf("input string:\n");  gets(st);  puts(st);}
    可以看出当输入的字符串中含有空格时,输出仍为全部字符串。说明gets函数并不以空格作为字符串输入结束的标志,而只以回车作为输入结束。这是与scanf函数不同的。
3. 字符串连接函数strcat
   格式:  strcat (字符数组名1,字符数组名2)
   功能:把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符串1后的串标志“\0”。本函数返回值是字符数组1的首地址。
【例7.14】
#include"string.h"main(){  static char st1[30]="My name is ";  int st2[10];  printf("input your name:\n");  gets(st2);  strcat(st1,st2);  puts(st1);}
    本程序把初始化赋值的字符数组与动态赋值的字符串连接起来。要注意的是,字符数组1应定义足够的长度,否则不能全部装入被连接的字符串。
4. 字符串拷贝函数strcpy
   格式:  strcpy (字符数组名1,字符数组名2)
   功能:把字符数组2中的字符串拷贝到字符数组1中。串结束标志“\0”也一同拷贝。字符数名2,也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。
【例7.15】
#include"string.h"main(){  char st1[15],st2[]="C Language";  strcpy(st1,st2);  puts(st1);printf("\n");}
本函数要求字符数组1应有足够的长度,否则不能全部装入所拷
贝的字符串。
5. 字符串比较函数strcmp
   格式:  strcmp(字符数组名1,字符数组名2)
   功能:按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。
          字符串1=字符串2,返回值=0;
  字符串2〉字符串2,返回值〉0;
  字符串1〈字符串2,返回值〈0。
本函数也可用于比较两个字符串常量,或比较数组和字符串常量。
【例7.16】
#include"string.h"main(){ int k;  static char st1[15],st2[]="C Language";  printf("input a string:\n");  gets(st1);  k=strcmp(st1,st2);  if(k==0) printf("st1=st2\n");  if(k>0) printf("st1>st2\n");  if(k<0) printf("st1<st2\n");}
本程序中把输入的字符串和数组st2中的串比较,比较结果返回到k中,根据k值再输出结果提示串。当输入为dbase时,由ASCII 码可知“dBASE”大于“C Language”故k〉0,输出结果“st1>st2”。
6. 测字符串长度函数strlen
   格式:  strlen(字符数组名)
   功能:测字符串的实际长度(不含字符串结束标志‘\0’) 并作为函数返回值。
【例7.17】
#include"string.h"main(){ int k;  static char st[]="C language";  k=strlen(st);  printf("The lenth of the string is %d\n",k);}
7.4 程序举例
【例7.18】把一个整数按大小顺序插入已排好序的数组中。
为了把一个数按大小插入已排好序的数组中,应首先确定排序是从大到小还是从小到大进行的。设排序是从大到小进序的,则可把欲插入的数与数组中各数逐个比较,当找到第一个比插入数小的元素i时,该元素之前即为插入位置。然后从数组最后一个元素开始到该元素为止,逐个后移一个单元。最后把插入数赋予元素i即可。如果被插入数比所有的元素值都小则插入最后位置。
main(){  int i,j,p,q,s,n,a[11]={127,3,6,28,54,68,87,105,162,18};  for(i=0;i<10;i++)      { p=i;q=a[i];	for(j=i+1;j<10;j++)	if(q<a[j]) {p=j;q=a[j];}	if(p!=i)	{	  s=a[i];	  a[i]=a[p];	  a[p]=s;	}	printf("%d ",a[i]);      }    printf("\ninput number:\n");    scanf("%d",&n);    for(i=0;i<10;i++)      if(n>a[i])      {for(s=9;s>=i;s--) a[s+1]=a[s];      break;}      a[i]=n;    for(i=0;i<=10;i++)      printf("%d ",a[i]);    printf("\n");}
本程序首先对数组a中的10个数从大到小排序并输出排序结果。然后输入要插入的整数n。再用一个for语句把n和数组元素逐个比较,如果发现有n>a[i]时,则由一个内循环把i以下各元素值顺次后移一个单元。后移应从后向前进行(从a[9]开始到a[i]为止)。 后移结束跳出外循环。插入点为i,把n赋予a[i]即可。 如所有的元素均大于被插入数,则并未进行过后移工作。此时i=10,结果是把n赋于a[10]。最后一个循环输出插入数后的数组各元素值。
    程序运行时,输入数47。从结果中可以看出47已插入到54和 28之间。
【例7.19】在二维数组a中选出各行最大的元素组成一个一维数组b。
a=( 3  16 87  65
  4  32 11 108 
10 25 12  37)
b=(87 108 37)
本题的编程思路是,在数组A的每一行中寻找最大的元素,找到之后把该值赋予数组B相应的元素即可。程序如下:
main(){    int a[][4]={3,16,87,65,4,32,11,108,10,25,12,27};    int b[3],i,j,l;    for(i=0;i<=2;i++)      { l=a[i][0];	for(j=1;j<=3;j++)	if(a[i][j]>l) l=a[i][j];	b[i]=l;}    printf("\narray a:\n");    for(i=0;i<=2;i++)      { for(j=0;j<=3;j++)	printf("%5d",a[i][j]);	printf("\n");}      printf("\narray b:\n");    for(i=0;i<=2;i++)      printf("%5d",b[i]);    printf("\n");}
程序中第一个for语句中又嵌套了一个for语句组成了双重循环。外循环控制逐行处理,并把每行的第0列元素赋予l。进入内循环后,把l与后面各列元素比较,并把比l大者赋予l。内循环结束时l 即为该行最大的元素,然后把l值赋予b[i]。等外循环全部完成时,数组b中已装入了a各行中的最大值。后面的两个 for语句分别输出数组a和数组b。
【例7.20】输入五个国家的名称按字母顺序排列输出。
    本题编程思路如下:五个国家名应由一个二维字符数组来处理。然而C语言规定可以把一个二维数组当成多个一维数组处理。 因此本题又可以按五个一维数组处理, 而每一个一维数组就是一个国家名字符串。用字符串比较函数比较各一维数组的大小,并排序,输出结果即可。
编程如下:
main(){    char st[20],cs[5][20];    int i,j,p;    printf("input country's name:\n");    for(i=0;i<5;i++)      gets(cs[i]);    printf("\n");    for(i=0;i<5;i++)      { p=i;strcpy(st,cs[i]);	for(j=i+1;j<5;j++)      if(strcmp(cs[j],st)<0) {p=j;strcpy(st,cs[j]);}    if(p!=i)      {	strcpy(st,cs[i]);	strcpy(cs[i],cs[p]);	strcpy(cs[p],st);      }    puts(cs[i]);}printf("\n");}
本程序的第一个for语句中,用gets函数输入五个国家名字符串。上面说过C语言允许把一个二维数组按多个一维数组处理,本程序说明cs[5][20]为二维字符数组,可分为五个一维数组cs[0],cs[1],cs[2],cs[3],cs[4]。因此在gets函数中使用cs[i]是合法的。 在第二个for语句中又嵌套了一个for语句组成双重循环。这个双重循环完成按字母顺序排序的工作。在外层循环中把字符数组cs[i]中的国名字符串拷贝到数组st中,并把下标i赋予P。进入内层循环后,把st与cs[i]以后的各字符串作比较,若有比st小者则把该字符串拷贝到st中,并把其下标赋予p。内循环完成后如p不等于i说明有比cs[i]更小的字符串出现,因此交换cs[i]和st的内容。至此已确定了数组cs的第i号元素的排序值。然后输出该字符串。在外循环全部完成之后即完成全部排序和输出。
7.5 本章小结
1.数组是程序设计中最常用的数据结构。数组可分为数值数组(整数组,实数组),字符数组以及后面将要介绍的指针数组,结构数组等。
2.数组可以是一维的,二维的或多维的。
3.数组类型说明由类型说明符、数组名、数组长度(数组元素个数)三部分组成。数组元素又称为下标变量。 数组的类型是指下标变量取值的类型。
4.对数组的赋值可以用数组初始化赋值,输入函数动态赋值和赋值语句赋值三种方法实现。 对数值数组不能用赋值语句整体赋值、输入或输出,而必须用循环语句逐个对数组元素进行操作。
3D打印狂潮:可检测皮肤疾病的低价手机显微镜 浅谈导航设计,开发者必备的十大实用技巧 【云先锋 41】上海越诚:基于云服务的建站类iService软件超市 董西成:Hadoop将在高速发展和完善中扩大优势! 【走近讲师】 华云数据郁珉:公有云市场八仙过海 价格不是唯一标准! Facebook、Twitter、Google移动广告之争 开发者的黄金时代=运维人员的恶梦? 研发团队平稳度过“从小到大”并非易事 诺基亚品牌手机不久将消失 Stephen Elop回应不是木马 看七家科技公司Logo的最初模样 移动UI框架Fries:私人定制最Sexy的用户界面 必须Mark!最佳HTML5应用开发工具推荐 百度技术开放日感悟:看百度如何获取大数据时代的“船票” 谷歌亚马逊微软的烧钱游戏 拉手网CTO官冲:团购网在大数据应用上的探索 究竟谁真正关心比特币,不妨看看基于大数据的百万条推特分析 Firefox 29正式版:高度自定义模式、全新菜单和Australis UI 冼茂源:HBase在垂直搜索业务以及数据存储中的应用! 阿里云计算北京布点 全球第三个云数据中心开放 【走近讲师】友友天宇CEO姚宏宇:与行业结合是私有云厂商的重要出路 万亿移动支付产业的难点和痛点 削减硬件运营成本?亚马逊或自主研发ARM架构芯片 开源框架eMobc:XML开发原生移动应用so easy iOS应用安全开发,你不知道的那些事 市场化API的十个捷径 MongoDB和Cloudera结盟,欲征服大数据市场 红帽收购Inktank,将统一Gluster与Ceph? 那些巨头公司Logo是这么演变来的…… 以史为镜,剖析PaaS大迷局 “心脏出血”还不够?又曝OAuth和OpenID登录漏洞 走近讲师:搜狐于顺治讲述搜狐PaaS云平台实践之路 装了“猫”为何还有630错误(电话线也接了)? excel 問題 各位:数据窗口有一检索变量,现在想retrieve出所有的记录,检索变量应该怎样赋值?谢谢! linux和windows是不是只能分别装在两个分区中 关于图像处理:如何使图像锐化与柔化? 帮帮我啦! 我在使用jdbc读取数据的时候,碰到了内存溢出的问题,怎么回事呀 哪里有餐饮系统的介绍?90不够的话,先欠着,多谢了! 在两个ASP程序之间怎么传递参数? ccl2000(不帅不酷的Goblin):其实你真的很酷很帅的。 大侠帮帮我啦(关于SQL语句的问题) 关于Vxd的编译问题 用VC编的程序,一运行就说“执行非法操作”,问题出在哪里?? SQL Server有病 一个关于api的简单问题 《易佳自定义报表》用后很失望 请教各位高手一个有关报表控件的问题? 小妹向大家请教!可不可以直接在本页的代码中改变该页面浏览时的属性? 家菲猫:惊悉你昨晚惨遭不幸,被窃大量钱物,今日一天无法和你联系上,估计手机和通信录已全部丢失,如果今晚无法来我处,明早8点以前请务必携猫 MM 赶到上海南站!!! MDI文档模板和应用程序调用问题请教,大侠请进! 一个c++问题???? 请问各位高手,sqlserver2k加密的存储过程是否能解密,看到它的实际的语句?可否能跟踪加密的存储过程? 我下载了一个formula one ,发现她的界面跟excel差不多,在pb中怎么用? 高分求XML 高级编程(足本)[01.pdf到10.pdf]!!!! 招聘汇编程序员 ie 中true dbgrid 的问题 急招聘汇编程序员 关于WINDONWS文件夹 WIN2000有关用户管理的问题 谁可以告诉我怎么调用已有的EXE文件。 有谁知道广州或南海的高级程序员考试的辅导点 如何把系统时间作为一个文件的保存名? TURBO C语言对磁盘操作的问题 着急招聘汇编程序员 为什么大家得的都是0分? 这行代码是什么意思: 不知怎的,不小心访问到一个网站。我已设为使用空页,可它还是要先启动,画面又恶劣,怎么办? 还是关于从字符串中提取汉字的问题,我是从*.txt取出一个字符串(readln),结果无法提取汉字 请大家帮忙,白送分的 为什么我无法安装win2000??? 如何只显示数据库中的最后一条记录?(只显示一条) delphi中编的COM控件如何在WWW服务器上使用? 如何运行时拖动一个控件,如BUTTON等。 别兴奋了,进入正题吧!老是报到什么的,快讨论呀! 着急死我了 请大家帮我编译一下这个程序吧!!! 读日志文件函数ReadEventLog怎么用,每次调为什么失败?数据结构怎么定义?怎样读已知记录号的一条日志?请检查以下函数为什么不正确? 请问怎样实现菜单的渐变?就是鼠标移动到一个菜单的时候就出现一个渐变的选单背景。谢了。以后加分。 请问哪里有下载VS.net beta2 ? hehe着急 请问一个有关报表的问题?本人十分焦急,望在线的高手都来看一看,谢谢! “理想”对于人生具有怎样的意义?十万火急, 为什么酸碱盐溶液能导电?既有正离子,又有负离子,这不就乱了套? 钠的熔点和沸点是高还是低钠的熔点是97.81℃和沸点是882.9℃ 说明文的定义是什么?说明对象的特征是什么? 酸碱盐的水溶液导电时,溶液中作定向移动的是 为什么熔点比沸点低 蒸馏和分馏有什么区别? 酸碱盐的水溶液导电的原因 为什么水加压沸点升高,冰加压熔点却降低? 你的目标理想是什么? 分馏和蒸馏的区别是什么? 电解质溶液导电是物理过程还是化学过程?原理是什么呢? 嘎子有哪些理想?分别是什么 分馏是什么?与蒸馏有什么不同? 电解质溶液的导电过程属于物理变化? 方向是什么意思 蒸馏与分馏有什么区别? 金属导电是物理变化吗 论文选题的目的 意义 怎么写? 过滤,结晶,分馏,萃取,分液,蒸馏的区别 为什么海水晒盐属于物理变化?为什么米饭烧焦属于化学变化? 发布文章最终目的是什么?发布文章的目的是的让百度收录就可以了是吗? 请问:分馏与蒸馏之间的区别是什么?感激不尽! 海水晒盐是物理变化还是化学变化 论文选题的目的和意义我的论文题目是《正当防卫与防卫过当》请帮我谈谈选题的目的和意义!小弟在这里谢谢你们了! 化学中【蒸馏】【分馏】【萃取】分别是什么啊?有什么区别啊? 海水晒盐是如何变化的?其中有没有化学变化? 两会是什么?两会的目的和意义是什么?作文500字 石油裂化,裂解,煤干熘,石油分熘,皂化反应,具体都是什么, 海水晒盐属于化学中的蒸发吗?我的问题不涉及海水晒盐是否属于化学变化,是想知道蒸发必须加热,而海水晒盐不需要加热,即海水晒盐属于蒸发吗? 论文的意义和目的大神们帮帮忙我写了关于社会保障与社会和谐的论文,谁能帮我写下研究这个课题的目的和意义啊 熔融状态下的氯化钠,离子键已经断了,再使它导电,不就是离子的定向移动吗.我觉得应该不是化学变化呀啊 海水晒盐是化学变化吗 互联网是哪种语言编的 NaCl水中溶解电离电离后为什么一个Cl-周围有6个水分子Na+周围有5个水分子 熔融盐和电解质溶液导电为什么是化学变化 给我的幻想打了一个零分是什么意思?其中幻想可以换成理想吗?为什么? 下列物质溶解在水中,能电离出氯离子的 A.NaCl B.HCl C.KClO3 D.AgCl这种题都怎么做的,是背下来的吗 溶液导电变化分析用如图所示装置分别进行如下实验,测定导电性变化,请按照要求选择填 空.A.导电性变化不大 B.导电性明显增强 C.导电性明显减弱 D.导电性由强到弱再到强 (1)向 AgNO3 溶 军旅题材的电影电视剧里的“十点钟方向”或是几点钟方向等等,我们常常在军旅题材的电影电视剧里听到多少多少方向的,这个方向是什么方向?如果判断、辩别? 在化学中,Nacl在水中电离时,会跟水分子,水的离子发生什么反应?又生成什么? 氯化钠溶液与硝酸钙溶液能否发生化学变化理由是( ) 看战争电影时总听到说方位在几点钟方向,具体是怎样的? 初中化学 氯化钠溶解在水中电离成氯离子和钠离子 就不是以氯化钠这个化合物的形式存在的 这是溶液的性质改变了么 还是氯化钠溶液?既然都已经散了 不是氯化钠了 怎么还是氯化钠溶液详 熔融食盐是否为为电解质,能导电吗?说明一下 谢谢 一直闹不清楚电影中说的几点钟方向是什么意思? 氯化钠溶于水成为自由移动的离子是化学变化,那没生成新物质啊 电解质溶液或熔融电解质导电的原因是什么?导电的实质是什么? 电影中所说的几点方向是什么意思 NaCl在水溶液中电离是不是化学反应? 煤的气化是物理变化还是化学变化 美国战争片上经常说的十点钟方向,那这个几点钟方向是什么意思?如题 氯化钠的电离把氯化钠加热到液态就能电离出氯离子和钠离子,那么继续加热到氯化钠气体是不是还能继续导电呢?为什么呢意思就是氯化钠气体是不是也能电离出钠离子和氯离子 煤的气化为什么不是物理变化 理想的含义.特征及其对人生的意义? 酸碱盐的水溶液导电原因 硅的熔点比铝高,沸点比铝低,这是为什么?物质由固体变为液体和由液体变为气体所克服的作用力具体有何不同? 理想集成运放具有什么特点?A.开环差模增益Aud=∞,差模输入电阻Rid=∞,输出电阻Ro=∞B.开环差模增益Aud=∞,差模输入电阻Rid=∞,输出电阻Ro=0C.开环差模增益Aud=0,差模输入电阻Rid=∞,输出电阻Ro=∞D 酸碱盐的水溶液靠什么导电?大家不要想得太麻烦.【最好给个原因啊... 有没有什么材料的熔点比较低,沸点非常高的比如熔点只有1~200度 沸点却在2000度以上的
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn