数组定义的语法:  类型  数组名[常量表达式];

tips:数组长度必须是常量表达式。

数组定义的语义:为数组中的所有元素分配连续的内存空间。

数组下标表达式的语义:获得数组中相应元素的引用(起始地址),从而可以对该元素的内存空间进行读或者写。

冒泡排序

#include <stdio.h>
int main()
{
    int a[6]={3,6,1,9,4,8};
    int i;int j;int t=0;
    for(j=0;j<6-1;j++)
    {
    	for(i=0;i<6-j-1;i++)
    	{
    		if(a[i]>a[i+1])
    		{
    			t=a[i];a[i]=a[i+1];a[i+1]=t;
			}
		}
	}
	for(i=0;i<6;i++)
	printf("%d ",a[i]);
	return 0;
	
 }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

选择排序

#include <stdio.h>
#include <stdlib.h>//用malloc必须引入这个库
int main()
{
    int*a;int n;
	scanf("%d",&n);
 	a=(int*)malloc(n*sizeof(int));//开辟4n个字节大小的空间 
	int i;int j;int t=0;int mindx;
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(i=0;i<n-1;i++)
	{
		mindx=i;
		for(j=i+1;j<n;j++)
		{
			if(a[j]<a[mindx])
			mindx=j;
		}
		t=a[i];a[i]=a[mindx];a[mindx]=t;
		
	}

for(i=0;i<n;i++)
printf("%d ",a[i]);

	return 0;
	
 }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

数组元素地址和动态数组

数组名是一个指针常量,代表数组首元素的地址。

指针变量可以指向数组元素(把某一元素的地址存到一个指针变量中)

int a[10] = {1,3,5,7,9,11,13,15,17,19 };
 int *p;
 p = &a[0];//等价于p=a
  • 1.
  • 2.
  • 3.

“p=a;”的作用是“把数组a的首元素的地址赋给指针变量p”,而不是“把数组a各元素的值赋给p”

指针算术:

 如果p的值为&a[0],则a+i和p+i就是元素a[i]的地址。

访问一个数组元素,可用两种等价方法:  

下标,如a[i]或p[i]

解引用,如*(a+i)或*(p+i)

#include <stdio.h>
#include <stdlib.h>
int main()
{
   int a[10];
   int i=0;
   for(i=0;i<10;i++)
   {
   	scanf("%d",&a[i]);
   	
   }
   for(i=0;i<10;i++)
   {
   	printf("%d ",a[i]);//通过数组名和下标访问数组元素;
   }
   printf("\n");
   int* p=a;
   for(i=0;i<10;i++)
   {
   	printf("%d ",*(a+i));//通过数组名和解引用访问数组元素
   }
   printf("\n");
   for(i=0;i<10;i++)
   {
   	printf("%d ",p[i]);//通过指针变量和下标访问数组元素;
   }
    printf("\n");
   for(i=0;i<10;i++)
   {
   	printf("%d ",*(p+i));//通过指针变量和解引用访问数组元素
   }

	return 0;
	
 }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.


内存分配——栈区,堆区,全局区、常量区和代码区

C语言之数组_指针变量

C语言之数组_数组_02

C语言之数组_字符串_03


内存分配方式有三种:    

1.从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。    

 2.在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。     

3.从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。记得
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

二维数组定义和访问

二维数组可被看作是一种特殊的一维数组,它的元素又是一个一维数组。

例如:把a看作是一个一维数组a[3],它有3个元素:a[0]、a[1]、a[2],每个元素的类型是float [4],也就是一个包含4个元素的一维数组。

二维数组定义的语义

为数组中的所有元素分配连续的内存空间

二维数组元素地址和动态数组

数组名是一个指针常量,代表数组首行的地址,也等于数组首元素的地址

行指针,类型为数组指针int (*)[4]:

a代表第1行的首地址

a+1代表第2行的首地址

a+i代表第i+1行的首地址

列指针,类型为整型指针int *:

a[0]和*a代表a[0][0]的地址

a[0]+1和*a+1代表a[0][1]的地址

a[i]和*(a+i)代表a[i][0]的地址

a[i]+1和*(a+i)+1代表a[i][1]的地址

a[i]+j和*(a+i)+j代表a[i][j]的地址

数组元素,类型为int:

a[0][1]和*(a[0]+1)和*(*a+1)代表元素a[0][1]

a[i][j]和*(a[i]+j)和*(*(a+i)+j)代表元素a[i][j]

用指针变量访问二维数组时,先计算出总元素数量,直接令p=*a(代表a[0][0]的地址),之后遍历12个元素

特殊:数组指针变量可以指向数组中的一行(把某一行的地址存到一个数组指针变量中)

#include <stdio.h>
int main()
{
  int a[3][4] = { 1,3,5,7,9,11,13,15,
                  17,19,21,23 };
  int (*p)[4], i, j;
  p = a;
  printf("enter row and colum:");
  scanf("%d,%d", &i, &j);
  printf("a[%d][%d] = %d\n",
         i,j,*(*(p + i) + j));
  return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
二维数组行地址作为函数参数

二维数组行地址可以作为函数实参,函数的形参是一个数组指针类型的变量:

函数调用时,可以将数组的行地址(数组名)传给形参,使得形参指向该数组的某一行。

?编写函数maxVal,用来求二维数组 中的最大元素,包含两个参数,一个二维数组行地址,一个数组的行数。编写主函数,定义一个3×4的矩阵,通过调用函数maxVal找到最大元素。

#include <stdio.h>
#include <stdlib.h>
void maxVal(int(*array)[4],int n)//注意4不能省略,实参数组第二维大小必须与之相同
{
	int i;int j;int maxdx;
	maxdx=array[0][0];
	for(i=0;i<n;i++)
	{
		for(j=0;j<4;j++)
		{
			if(array[i][j]>=maxdx)
			maxdx=array[i][j];
		}
	}
	printf("%d",maxdx);
}
 
int main()
{
	int a[3][4]={1,2,34,53,56,23,6,12,76,53,54,23};
	maxVal(a,3);
	
		return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

字符数组

字符数组与数值数组唯一的区别在于字符数组中的字符构成一个字符串,因此字符数组的输入输出可以有两种方法:

逐个字符输入输出(%c)

整个字符串输入输出(%s)

使用%s输入输出字符串时,需要数组的末尾有一个字符串结束标记 ’\0’

用%s格式进行输出时:从实参给定地址上的字符开始输出,以’\0’作为字符串输出结束。

char str1[6] = { 'H','e','l','\0','l','o' };

 printf("%s", str1);//传首地址即可

用scanf等函数和%s格式输入字符串时,输入的字符串应短于存储字符串的数组的长度,否则导致将字符串写入数组之外的内存空间。

char c[6];  scanf("%s", c);//传首地址即可

?printf(“%s”,str); 为什么用首地址就可以输出字符串?

printf(“%s “, s),它的原理其实也是通过字符串首地址输出字符串,传给它的其实是s所保存的字符串的地址,所以,printf(“%s”,0x00422020);也是等效的

操作字符串是通过它在内存中的存储单元的首地址进行的,这是字符串的终极本质。

字符数组元素地址

字符数组中各元素的值是可以改变的,但字符串常量中的内容是不可以被改变的

数组名是一个指针常量,代表数组首元素的地址

指针变量可以指向数组或字符串常量中的元素(把某一元素的地址存到一个指针变量中)

 【C语言】三种方式实现字符串(字符数组)的输入输出_c语言字符串数组输出-CSDN博客

printf和scanf都会跳过空格

访问字符串常量(用指针)
const char* string = "I love China!";
printf("%s\n", string);
  • 1.
  • 2.
访问字符数组中的字符串(用指针)
char string[] = "I love China!"
  char *p = string + 7;
  printf("%s\n", p);
  • 1.
  • 2.
  • 3.
访问字符数组中的字符串(用数组名)
char string[] = "I love China!";
  printf("%s\n", string);
  • 1.
  • 2.

对指针变量操作,就是对其指向的内存空间操作

void str_cat(char* dest, const char* src)

 dest[i] = '\0';//重要!防止越界

#include <stdio.h>
void str_cat(char* dest,const char* src)
{
	int i=0;
	while(dest[i]!='\0')
	{
		i++;
	}
	dest=dest+i;
	
	for(;*(src)!='\0';dest++,src++)
	{
		*dest=*src;
	}
	  dest[i] = '\0';//重要!防止越界
}

int main()
{
	char q[]="i love";
	char w[]="china";
	str_cat(q,w);
	printf("%s",q);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

#include <string.h>

函数gets:输入字符串


int main() {
  char str[20];
  gets(str);
  printf("%s\n", str);
  return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
函数puts:输出字符串
int main() {
  char str[20] = "China";
  puts(str);
  return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
函数strcat:连接字符串
int main() {
  char str1[30] = "Hello";
  char str2[] = "World";
  printf("%s", strcat(str1, str2));//将str2接在str1后,需确保str1足够大
  return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
函数strcpy:复制字符串
int main() {
  char str1[10], str2[] = "China";
  strcpy(str1, str2);      printf("%s\n", str1);
  strcpy(str1, "China");   printf("%s\n", str1);//将str2复制给str1,需确保str1足够大
  return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
函数strncpy:复制字符串

将字符串src前n个字符复制到字符数组dest中去,取代dest中原有的前n个字符,程序员需要确保dest足够大

int main()
{
	char q[]="ilove";
	char w[]="china";
	strncpy(q,w,3);
	printf("%s",q);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
函数strcmp:比较字符串

比较字符串s1和字符串s2的字典序大小。函数返回值为:

如果s1==s2,0

如果s1>s2,正数

如果s1<s2,负数

?字典序

字典序(dictionary order),又称 字母序(alphabetical order),含义是表示英文单词在字典中的先后顺序,在计算机领域中扩展成两个任意字符串的大小关系。 

对于两个不同的字符串,从左到右逐个比较它们的字符

如果在某个位置上它们的字符不同,则将它们按照该位置上的字符的字母顺序进行排序,即较小的字符排在前面,较大的字符排在后面。

如果一直比较到其中一个字符串结束,则较短的字符串排在前面;

如果两个字符串完全相同,则它们的字典序相同。可以将它们看作是按照字母表的顺序进行排列的。

函数strlen:计算字符串长度

计算字符串长度,也就是在第一个’\0’字符之前的字符个数

函数strlwr:转换为小写字母
int main()
{
	char q[]="ILOVE";
	strlwr(q);
	printf("%s",q);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
函数strupr:转换为大写字母

指针数组

元素是指针类型的数组。也就是说,数组中的每一个元素都存放一个地址,相当于一个指针变量。

int i, j, k;

  int* p[4];

  p[0] = &i; p[1] = &j;

指向指针数组元素的指针变量,每一个指针数组元素又指向一个字符串或数字

char* name[] = { "write","computer",

                   "program","compile" };

  char** p;   int i;

  for (i = 0; i < 5; i++)

  {

    p = name + i;

    printf("%s\n", *p);

  }

定义一个整型数组,然后定义一个指针数组,其元素分别指向整型数组中的一个元素,定义一个指向指针数组元素的指针变量,遍历指针数组元素,同时输出整型数组各元素的值

int main()
{
int a[3]={43,4,65};
int* b[3]={&a[0],&a[1],&a[2]};
int** q=b;int i;
for(i=0;i<3;i++)
{
	printf("%d ",**q);
	q++;
}
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

C语言之数组_字符串_04