06 数组程序设计

1.一维数组

1.1 一维数组的定义

定义:<类型>变量名称[元素数量] 例如,

int a[100];

double b[200];

数组是一个容器,特点是

  • 所有元素具有相同的数据类型
  • 一旦创建,不能改变大小
  • 数组中的元素在内存中连续依次排列

举例:

int a[10];

10个单元 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9],每个单元是一个int类型的变量,可以出现在赋值的左边或右边 a[2] = a[1] +1,在赋值左边的叫做左值。

放在方括号[]中的数字叫做下标或者索引,从0开始计数。有效的下标范围[0,数组的大小-1]

1.2 一维数组的初始化

1)定义数组时,对元素赋初值
  • 对全部元素赋值 int a[10]={0,1,2,3,4,5,6,7,8,9}; 这时[ ]中的10可以不写
  • 对部分元素赋值 int a[10]={0,1,2,3,4}; 系统自动给后5个元素赋初值为0
  • 若想将数组元素全部赋值为0,可以对全部元素赋值,也可int a[10]={0}; 还可直接写空的大括号,如:int a[10]={};
  • 在指定数组长度并初始化时,未被初始化的元素,如果是字符型数组,初始化为 ’\0’,如果是指针型数组,初始化为NULL,即空指针
  • int b, a[b];是错误的,不能用变量说明数组大小
2)定义数组后,对元素赋初值
 
int a[10]; a[10]={0,1,2,3,4,5,6,7,8,9}; 会导致编译错误。所以要么在定义时直接赋值,或者定义后用 for循环 读入数组。如:
for(int i=0;i<10;i++)
{
	a[i]=i;
	printf("%d\t",a[i]);
}
 

1.3 一维数组的引用

格式:数组名[下标]。下标可以是整型常量或整型表达式。如:

a[0] = a[5]+a[7]-a[2*3]

a[i+j]

a[i++]

在C语言中只能逐个的使用下标变量,而不能一次引用整个数组。

#include<stdio.h>
int main()
{
	int i,a[10]={1,2,3,4};
	for(i=0;i<10;i++)
	{
		printf("%d\n",a[i]);
	}
}

如果没有初始化,会导致输出不可知数。如:

//错误示范
#include<stdio.h>
int main()
{
	int i,a[10];
	for(i=0;i<10;i++)
	{
		printf("%d\n",a[i]);
	}
}

2.二维数组

2.1 二维数组的定义

定义:<类型>变量名称[元素数量] [元素数量]。例如,

int a[3][5];

通常认为a是一个三行五列的矩阵。

a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]

2.2 二维数组的初始化

int a[][5] = {
    {0,1,2,3,4},
    {2,3,4,5,6}.
    };
  • 列数必须给出,行数可以由编译器来数出
  • 每行一个 {} ,用逗号分离
  • 最后的逗号可以存在
  • 如果省略,表示补零
  • 可以用定位

2.3 二维数组的引用

3.字符数组与字符串

3.1 字符串的输入输出

char string[8];
scanf("%s",string);
printf("%s",string);

scanf 读入一个单词(到空格、tap 或回车为止);
scanf 是不安全的,因为不知道要读入的内容和长度。

#include <stdio.h>
int main(void)
{
	char word[8];
	scanf("%s",word);
	printf("%s##\n",word);
	
	return 0;      
}

#include <stdio.h>
int main(void)
{
	char word[8];
	char word2[8];
	scanf("%s",word);
	scanf("%s",word2);
	printf("%s##%s##\n",word,word2);
	
	return 0;  
}

因此,限制读入个数来避免崩溃。

#include <stdio.h>
int main(void)
{
	char word[8];
	char word2[8];
	scanf("%7s",word);//至多读前7个
	scanf("%7s",word2);
	printf("%s##%s##\n",word,word2);
	
	return 0;      
}

  • char [8];
  • scanf("%7s",string);

在%和s之间的数字表示最多允许读入的字符的数量,这个数字应该比数组的大小小一。

3.2 字符串函数

strlen

  • size_t strlen(const char*s)
  • 返回s的字符串长度(不包括结尾的0)
include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
	char line[] = "Hello";
	printf("strlen=%lu\n",strlen(line));
	printf("sizeof=%lu\n",sizeof(line));
	
	return 0;
}

strcmp

  • int strcmp(const char *s1,const char *s2);
  • 比较两个字符串,返回:
    •  0:s1==s2
    •  1:s1>s2
    • -1:s1<s2
include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
	char s1[] = "abc";
	char s2[] = "abc";
	printf("%d\n",strcmp(s1,s2));
	
	return 0;
}

结果为0,表示比较的两个字符串相等。

 若改成 char s2[] = "bbc"; ,结果为 -1。意思是 s1<s2 。因为与b相比,a在字母表更前的位置,所以b比a大。

如果改成char s2[] = "Abc"; ,结果为 1 。意思是 s1>s2 。因为小写字母比大写字母大。

但有些编译器会把两个字符的ASCII码之差作为比较结果由函数值返回。

如果加上空格char s2[] = "abc "; ,结果是 -1 。

有些编译器上,输出的是 -32 。

s1[ ] a b c \0  
s2[ ] a b c (space) \0

即  '\0' - ' ' = 0 -32 = -32 。

strcpy

  • char * strcpy(char *restrict dst, const char *restrict scr);
  • 把 src 的字符串拷贝到 dst
  • restrict 表明 src 和 dst 不重叠(C99)
  • 返回 dst 为了能链接器代码

strcat

  • char * strcat(char *restrict s1, const char *restrict s2);
  • 把 s1 拷贝到 s2 后面,接成一个长字符串
  • 返回 s1
  • s1 必须有足够的空间

本来是这样的两个字符串:

src a b \0
dst c d \0

把 dst 的 '\0' 变成 src 的 a ,依次排下去,最后是 '\0' 。变成这样:

c d a b \0

这就是链接,实质上也是一种拷贝。

如果需要拷贝或者链接的地方没有足够的空间,strcpy 和 strcat 都可能出问题。

解决办法是使用安全版本 strncpy 和 strncat 。

strchr

  • 字符串中找字符
  • char * strchr(const char *s, int c);
  • char * strrchr(const char *s,int c);
  • 返回NULL表示没有找到

下一篇:07 指针基础

posted @ 2022-11-06 16:03  许悠  阅读(45)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end
1 2 3
4