C语言入门之数组与字符/字符串

嵌入式技术

1372人已加入

描述

1、介绍数组

一个常量变量就是一个用来存储数值的命名区域。同样,一个数组就是一个用来存储一系列变量值的命名区域,因此,可以使用数组组织常量变量。也就是说,数组是一组有序数据的集合,存储在数组中的值称为数组元素。每个数组元素有一个相关的索引(也称为关键字),它可以用来访问元素。在大多数编程语言中,数组都具有数字索引,而且这些索个通常是从0或1开始的。数组中的每个元素都属于同一个数据类型。

一维数组是由数字组成的以单纯的排序结构排列的结构单一的数组。一维数组是计算机程序中最基本的数组。二维及多维数组可以看作是一维数组的多次叠加产生的。

C语言

2、一维数组

当数组中每个元素都只带有一个下标时,称这样的数组为一维数组。通过给出的数组名称和这个元素在数组中的位置编号(即下标),程序可以引用数组中的任意一个元素,一维数组的引用定义格式为:类型+数组名[下标]如:int  a[10]

其中,a是一维数组的数组名,该数组有10个元素,依次表示为a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]。需要注意的是,数组是从零开始是,所以a[10]不属于这一个数组的空间范围中。当在说明部分定义了一个数组变量后,编译程序会在内存空间中开辟一串连续的存储单元。对于数组而言,程序的执行部分使用的是数组变量而不是数组类型。在引用时,下标必须是整数,但可以是整型变量或整型表达式。如果使用表达式,会先计算表达式以确定下标。程序只能逐个应用数组中的元素而不能一次引用整个数组,再定义数组时,需要指定数组中元素的个数,方括号里边的常量数值表示了数组的长度。在数组定义前加const关键字可将整个数组变为只读,将不再可以对数组进行写入数据。

如: int a;  float a[10]; (非法)    int n=5;  int a[n];(非法)    int a[5+6]; (合法的)

初始化:(注意,在使用数组之前,一定要先初始化)

1、数组的初始化可以在定义时一并完成

2、可以只给部分元素赋初值,其他的元素赋0。

3、如给全部元素赋值,则在数组中说明,可以不给出数组元素的个数

4、数组的初始化可以是用循环进行输入数值赋值,也可以是在程序中指定赋值

例子:

 

#include//寻找数字并查看在哪个位置
int search(int n, int a[], int max);
int main(void) 
{    int a[] = {1,6,5,7,4,3,2,8,11,9,10};//初始化一      
          /* int a[10] = {0}//初始化二  全都初始化为零         
       for (i = 0; i < 10; i++) {//初始化三自己输入初始化(这种初始化最好定义在二之上,否则其他如果有元素没有被赋值的话会出错)    
          scanf("%d", &a[i]);            
 }           
     */    int n;    scanf("%d", &n);       


     //整个数组占用的字节数可用sizeof(a)表示出来  
  int h = search(n, a, sizeof(a) / sizeof(a[0]));//用整个数组占用的字节数除以首元素的字节数可知道数组的大小   
 
if (h != -1) { 
printf("%d在第%d位上", n, h+1);  


  }else {  printf("没有这个数字");  
  }  
  return 0;
}


int search(int n, int a[], int max) {  
     int t = -1;  
      int i; 
   for (i = 0; i < max; i++) {//遍历数组     
   if (n == a[i]) 
    {            t = i;        
    break;    }  
 }   
 return t;
}

 

3、二维数组

二维数组本质上是以数组作为数组元素的数组即“数组的数组”,类型说明符 数组名[ 常量表达式][常量表达式]。

二维数组又称为矩阵,行列数相等的矩阵称为方阵。

对称矩阵a[i][j]=a[j][i]二维数组A[m][n],这是一个m行,n列的二维数组。设a[p][q]为A的第一个元素,即二维数组的行下标从p到m+p,列下标从q到n+q,按“行优先顺序”存储时则元素a[i][j]的地址计算为:(t为一个字节数)LOC (a[i][j]) = LOC(a[p][q]) + ((i−p) * n + (j −q)) * t 按“列优先顺序”存储时,地址计算为:LOC(a[i][j]) = LOC(a[p][q]) + ((j −q) * m + (i−p)) * t存放该数组至少需要的单元数为(m-p+1) * (n-q+1) * t 个字节二维数组只是形式上的二维,但是在计算机内部它的存储方式还是连续的线性的。它只是一种特殊的一维数组。

二维数组的定义和一维数组的概念规则基本相似,一般形式为:类型说明符+数组名【常量表达式】【常量表达式】。

初始化稍有不同

注意,二维数组的列数是必须要给出的,行数是可以有编译器来数。

每行一个{},逗号分离

最后的的逗号可以存在(有古老的传统)

如果省略,表示补零

例子:杨辉三角

 

#include//杨辉三角
int main(void) { 
   int n;   
 scanf("%d", &n);   
 int i, j;  
  int a[100][100] = { 0 };//先把所有元素初始化为零  
  //由与二维数组有两个下标,所以它的遍历需要双重循环来实现     
   for (i = 0; i < n; i++) {    
    a[i][0] = a[i][i] = 1;//将第一位数字和最后一位数组初始化为1   
 }   


     int t;  
  for (i = 1; i <=n; i++) {//遍历赋值  
  for (j = 1; j <=i-1; j++) {        
   a[i][j] = a[i - 1][j-1] + a[i - 1][j];//每一位上的数字相当于两肩上的和     
       }      
  }    


for (i = 0; i < n; i++) {//遍历输出   
     for (t = i; t < n; t++) {       
     printf("   ");     
   }          
    for (j = 0; j <=i; j++) {             
   printf("%6d", a[i][j]);      
  }         
   printf("
");     
   }  
  return 0;
}

 

Tips

1、编译器和运行环境都不会检查数组的下标是否越界,无论是对数组的单元读还是写,一旦程序运行,越界的数组访问就可能造成问题,导致程序崩溃。

2、但有时候也有可能运气好,不会造成严重后果。

3、所以这是程序员的责任来保持程序只使用有效的下标值,:[0 -  数组的大小减1]

4、数组可以出现在赋值号的左边或右边,在左边叫左值,在右边叫右值

5、如果在定义数值型数组时,指定了数组的长度,并且对其初始化,凡是未被“初始化”的元素,系统有时候会自动将它们初始化为零,如果是字符型,则初始化为‘’,如果是指针型,则初始化为NULL,即空指针,不过,最好还是自己初始化好比较好。

4、字符的输入输出

有五种输入:gets(),getchar(),getch ()scanf()          fgets()  (文件类)

有五种输出:puts(),putchar(),putch(),printf()          fputs()(文件类

输入:

1、gets()函数原形:char * gets(char * ptr);  用于从标准输入流stdin读入一个整行(以' '或EOF)结束,并且回车键会被过滤掉,不会被读到字符串中,写入指向的字符数组,并返回这个指针;出错或袭遇到文件结束时则返回NULL。行末的' '从流中取出,但不写入数组。gets()不检查被写入的数组大小。其可以无限读取,不会判断上限,以回车结束读取

2、getchar()函数原形:int getchar(void);    每次只读入一个字符,用于从标准输入流stdin读入字符,括回车键也会被读成一个字符,并返回这个字符。如果读到文件结尾,则返回EOF。注意到EOF不能用char类型表示,所以getchar()函数返回的是一个int型的数。它输入的字符被存放在sewll的缓冲区中,直到用户按回车才会执行,但是如果你输了多个字符,以后的getchar()再执行时就会直接从缓冲区中读取了

 

#includei
nt main(void) {  
  char n[5] = {0};int a = getchar(n);//第一次多次输入字符 
 (使用getchar时需要定义一个变量暂时存放数据)
int c = getchar(n);//后面这些就是直接从a输入的哪些被放到缓冲区的读取了
int b = getchar(n);
printf("%c", a);
printf("%c", b);
printf("%c", c);            
    //输入abc          
   char p;     
   // p=getch();//用它不用按回车键  
        p=getchar();   
      int b = getchar();       
    int c = getchar();     
     putchar(p);//输出abc    
    putchar(b);     
    putchar(c);}

 

3、getch()函数原形:int getch(void);  它的功能和getchar基本相同,差别在getch是直接从键盘获取值,不等用户按键,它直接返回用户输入的ASCII码值,出错就返回-1(getchar和getch都可以用来放在程序的末尾,当作“暂停键”使用,此时圆括号不需要参数,按任意键继续)

4、scanf()做为单个字符输入时使用%c数据类型符,用于字符串时使用%s数据类型符(注意使用%s时不用加&)

输出:

1、puts()函数原形:int puts(const char *s); 返回值:用来向标准输出设备(屏幕)输出字符串并换行,把字符串输出到标准输出设备,将''转换为回车换行,只能输出字符串, 不能输出数值或进行格式变换,可以将字符串直接写入puts()函数中:puts("Hello, world!"); ( puts()和gets()都是数组函数,输入或输出前要定义数组,一个简单的输入后再将输入的东西输出)(puts(st);st为数组名)

2、putchar()函数原形:int putchar(int char);返回值:该函数以无符号 char 强制转换为 int 的形式返回写入的字符,当输出正确的时候,返回输出字符转换为的unsigned int (无符号)值,当输出错误的时候,返回EOF(End of file)文件结束符,表达式可以是字符型或整型,它每次只能输出一个字符 如:“putchar('#')”输出字符“#”(其函数度原型在stdio.h中)

3、putch()函数原形:int putch(int ch);返回值:如果输出成功,函数返回该字符;否则返回EOF。在当前光标处向文本屏幕输出字符ch,然后光标自动右移一个字符位置(其函数原型在头文件conio.h中 )

使用方式:1、putch('转义字符');2、putch('单个字符');3、putch(字符变量);

注:需先定义 char 字符变量='单个字符';

4、printf()做为单个字符输出的时候使用%c数据类型说明符,做为字符串输出时使用%s数据类型说明符

(puts()的输入和printf的输出是有一定的区别的,puts()遇到‘'就终止,而用printf则不会这样。)

(printf函数可输出各种不同类型的数据,putchar函数只能输出字符数据,而puts函数可输出字符串数据。)

5、单字符数组

字符数组是指用来存放字符数据的数组。其定义的一般形式为: char 数组名[数据长度] 。字符数组用于存放字符或字符串,字符数组中的一个元素存放一个字符,它在内存中占用一个字节。用来存放字符数据的数组称为字符数组。字符数组中的一个元素存放一个字符。定义字符数组的方法与定义数值型数组的方法类似。由于字符型数据是以整数形式(ASCII代码)存放的,因此也可以用整型数组来存放字符数据。但这时每个数组元素占2个字节的内存单元,浪费存储空间,它也可以是多维数组。

初始化:

1、字符数组的初始化与数值型数组初始化没有本质区别。但它除了可以逐个给数组元素赋予字符外,也可以直接用字符串对其初始化。

2、用字符常量逐个初始化数组:char a[5]={'a','b',,'c','d','e',}; 把8个字符依次分别赋给c[0]~c[4]这5个元素

3、如果在定义字符数组时不进行初始化,则数组中各元素的值是不可预料的。如果字符个数大于数组长度,则出现语法错误。如果初值个数小于数组长度,则只将这些字符赋给数组中前面那些元素,其余的元素自动定为空字符(即'')。如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度

例子:输入一行字符,统计其中有多少个单词和有多少个a(大小写都算),单词之间用空格分隔开

 

#include
int main(void) 
{  
  char a[100] = {0};  
  int sum = 0;  
  gets(a);//字符的输入函数      
          int i=0;    
    int t = 0;  
      while(1){      
      if (a[i] == '') {     
           break;       
     }else if (a[i] == ' ') {       
         sum++;         
   }        
    if (a[i] == 'a' || a[i] == 'A') {     
           t++;          
  }         
       i++;       
 }      
  printf("有%d个单词,%d个a", sum+1, t);     
   return 0;
}

 

6、字符串(数组)

1、C语言中没有字符串类型,字符串是存放在字符型数组中。字符反映在现实中就是文字、符号、数字等人用来表达的字符,反映在编程中字符就是字符类型的变量。C语言中使用ASCII编码对字符进行编程,编码后可以用char型变量来表示一个字符。C语言的字符串就是多个字符打包在一起共同组成的,字符串在内存中其实就是多个字节连续分布构成的

2、字符串通常以串的整体作为操作对象,以整数0(‘’也一样)或NULL结尾的,‘’ 标致着字符串的结束也是字符串的标志,但是计算长度时不包括这个0,这里补充一点:字符串在存储上类似字符数组,所以它每一位的单个元素都是可以提取的,如s=“abcdefgij”,则s[1]=“b”,s[9]="j",而字符串的零位正是它的长度,如s[0]=10,这可以给我们提供很多方便,如高精度运算时每一位都可以转化为数字存入数组

3、字符串或串(String)是由数字、字母、下划线组成的一串字符。一般记为 s=“a1a2···an”(n>=0)。字符(string)是符号或数值的一个连续序列,如符号串(一串字符)或二进制数字串(一串二进制数字)。串的两种最基本的存储方式是顺序存储方式和链接存储方式。

4、C语言的字符串不能运用运算符对其操作,通过数组的方式可以遍历字符串,唯一特殊的地方就是字符串字面量可以用来初始化字符数组,字符串以数组的形式出现,以数组或指针的形式访问(更多的时候是用指针的形式)

C语言标准库和string.h头文件里提供了一系列的字符串操作函数

5、字符串常量:char *s=“Hello world”;  s是一个指针,初始化指向一个字符串常量,由于这个常量所在的地方,所以实际上s是const 的char *s,但由于历史的原因,编译器接受不带const 的 char *s的写法,但是如果试图对s所指的字符串做写入有可能会造成严重后果,所以 如果需要修改字符串,应该用数组,char s[ ] ="Hello world";

" Hello" 会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还会有个零表示结束,两个相邻字符串常量会被自动链接起来。

初始化

1、直接用字符数组的方法初始化:char str[10]={ 'I',' ','a','m',' ',‘h’,'a','p','p','y'};(字符数组的赋值只能按元素一一赋值)

2、使用输入字符的输入函数进行输入赋值

3、也可以省略花括号 :char str[ ]="I am happy";

Tips

字符串可以代表为char*的形式,但是  char * 不一定是字符串,本意是指向字符的指针,可能指向的是字符的数组(就像int*一样) 注意:只有它所指的字符数组末尾有0,才能说它所指向的是字符串

char *a ="Hello" 和char  b[ ]="Hello" 的不同,做为数组的时候,它是个常量(这个字符串在这里 )。  做为指针,它是个变量(这个字符串不知道在哪里) (指针 可以用来处理参数,动态分配空间)所以  :如果要构造一个字符串—>用数组,如果要处理一个字符串—>用指针

 

 c语言中字符串是通过字符指针来间接实现的
 char *p="linux";    //字符串
   char a[]="linux;    //字符数组
   printf("p=%s.
",p);  
   printf("a=%s.
",a);

 

字符(串)处理头文件

1、#include //字符串处理

2、#include //字符处理

里分别包含有以下这些函数:

strlen求字符串长度

strcmp比较2个字符串是否一样

strcat字符串连接操作

strcpy字符串拷贝操作(要求两个字符串长度足够)

strncat字符串连接操作(前n个字符)

strncpy字符串拷贝操作(前n个字符)

strchr找一个字符,查询在字符串中第一个出现这个字符的位置

strstr查询s1是否是s2子串

3、里分别包含以下这些函数:

C语言

(使用函数时利用返回值来操作)

对于字符串的操作还有sprintf(把格式化的数据写入某个字符串中)和sscanf(读取格式化的字符串中的数据)这两个函数

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分