C程序设计 谭浩强 第六章

本文详细介绍了C语言中一维、二维和字符数组的定义、引用、初始化以及常见操作,如数组元素的引用、初始化、赋值等。此外,还展示了多个使用数组实现的算法,如筛选法求素数、选择法排序、求矩阵对角线元素之和、插入排序、数组逆序、杨辉三角和魔方阵的输出,以及查找数组中的鞍点、折半查找、字符串操作等。文章最后给出了字符数组的编码与解码示例,以及自定义字符串复制和比较函数。
摘要由CSDN通过智能技术生成

数组

在这里插入图片描述

一维数组

如何定义

类型符 数组名[常量表达式];

  • 数组名的命名规则和变量名相同,遵循标识符命名规则。
  • 常量表达式中可以包括常量和符号常量,如“int a[3+5]”是合法的。不能包含变量,如“int a[n]”是不合法的。

引用数组元素

数组名[下标]

例如,a[0]就是数组a中序号为0的元素,它和一个简单变量的地位和作用相似。

初始化

  • 在定义数组时对全部数组元素赋予初值

    int a[10] = {0,1,2,3,4,5,6,7,8,9,};
    
  • 可以只给数组中的一部分元素赋值

    int a[10] = {0,1,2,3,4};
    //表面只给前面5个元素赋初值,系统自动给后5个元素赋初值为0
    
  • 如果想使一个数组中全部元素值为0,可以写成

    int a[10] = {0,0,...,0};
    //或者
    int a[10] = {0}
    
  • 如果数组不被部分赋初值,那么数组中的数不会被默认赋值为0

二维数组

如何定义

类型说明符 数组名[常量表达式] [常量表达式]

float a[3][4],b[5][10];

引用二维数组

数组名[下标] [下标]

初始化

  • 分行给二维数组赋初值

    int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
    
  • 可以将所有数据写在一个花括号内,按数组元素在内存中的排列顺序对各元素赋初值。

    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    
  • 可以对部分元素赋初值。

    int a[3][4] = {{1},{5},{9}};
    //它的作用是对各行第1列(即序号为0的列)的元素赋初值,其余元素值自动为0。
    
  • 如果对全部元素都赋初值(即提供全部初始数据),则定义数组时对第1维的长度可以不指定,但第2维的长度不能省。

    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    //==
    int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    

字符数组

如果初值个数小于数组长度,则只将这些字符赋给数组中前面那些元素,其余的元素自动定为空字符(即’\0’)

char c[10] = {'c',' ','p','r','o','g','r','a','m'};

如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。

char c[] = {'I',' ','a','m',' ','h','a','p','p','y'};

为了测定字符串的实际长度,C语言规定了一个“字符串结束标志”,以字符串’\0’作为结束标志。如果字符数组中存有若干字符,前面9个字符都不是空字符(‘\0’),而第10个字符是’\0’,则认为数组中有一个字符串,其有效字符为9个。

字符串常用函数

strcat

char strcat (char *dest, const char *src)
把src 所指向的字符串追加到dest所指向的字符串的结尾。

strcpy&strncpy

char strcpy (char *dest, const char *src)
把 src 所指向的字符串复制到 dest。

char strncpy (char *dest, const char *src, size_t n)
把 src 所指向的字符串复制到 dest,最多复制 n 个字符。

strcmp

int strcmp (const char *str1, const char *str2)
把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。

strlwr

函数作用是将字符串中大写字母换成小写字母。

strupr

函数作用是将字符串中小写字母换成大写字母。

习题

1. 用筛选法求100之内的素数

#include<stdio.h>
#include<math.h>
#include<stdlib.h>

int main()
{
	int prime[101] = {0};
	
	int i;
	for(i=2;i<=sqrt(100);i++)
	{
		if(prime[i]==0)
		{
			int j = 0;
			for(j=i*i;j<=100;j+=i)
				prime[j] = 1;
		}
	}
	
	for(i=2;i<=100;i++)
	{
		if(prime[i]==0)
			printf("%d ",i);
	}
	printf("\n");
	
	return 0;
}

2.用选择法对10个整数排序

#include<stdio.h>

int main()
{
	int min;
	int intArr[10] = {-3,6,0,1,2,9,10,1,3,5};
	
	int i,j;
	for(i=0;i<10;i++)
	{
		min = i;
		for(j=i;j<10;j++)
		{
			if(intArr[min]>intArr[j])
			{
//				int t;
				min = j;
			}
		}
		if(min != i)
		{
			int t;
			t = intArr[min];
			intArr[min] = intArr[i];
			intArr[i] = t;
		}
	}
	
	
	printf("------------\n");
	for(i=0;i<10;i++)
	{
		printf("%d ",intArr[i]);
	}
	printf("\n");
	
	return 0;
}

3. 求一个3 X 3的整形矩阵对角线元素之和

#include<stdio.h>

int main()
{
	int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
	
	int sum = 0;
	sum = arr[0][0] + arr[1][1] + arr[2][2];
	
	printf("%d\n",sum);
	
	return 0;
}

4. 有一个已经排好序的数组,要求输入一个数后,按原来顺序的规律将它插入数组中

#include<stdio.h>

int main()
{
	int insertNum;
	scanf("%d",&insertNum);
	printf("========插入到数组========\n");
	int intArr[10] = {2,6,9,10,13};
	
	int i;
	for(i=4;i>=0;i--)
	{
		if(insertNum>intArr[i])
			break;
	}
	int j = 4;
	for(j=4;j>i;j--)
	{
		intArr[j+1] = intArr[j];
	}
	intArr[j+1] = insertNum;
	
	printf("===========\n");
	for(i=0;i<6;i++){
		printf("%d ",intArr[i]);
	}
	printf("\n");
	
	return 0;
}

5. 将一个数组中的值按逆序重新存放。例如:原来顺序为8 6 5 4 1。要求改为1,4,5,6,8

#include<stdio.h>

int main()
{
	int intArr[] = {-3,6,0,1,2,9,10,1,3,5};
	
	int i;
	for(i=0;i<5;i++)
	{
		int t;
		t = intArr[i];
		intArr[i] = intArr[10-i-1];
		intArr[10-i-1] = t;
	}
	
	printf("==========\n");
	for(i=0;i<10;i++)
	{
		printf("%d ",intArr[i]);
	}
	
	return 0;
}

6. 输出一下的杨慧三角(要求输出10行)

#include<stdio.h>
int main()
{
	int arr[11][11];
	arr[1][1] = 1;
	arr[2][1] = 1;
	arr[2][2] = 1;
	int i,j;
	for(i=3;i<=10;i++)
	{
		for(j=1;j<=i;j++)
		{
			if(j==1||j==i)
				arr[i][j] = 1;
			else
				arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
		}
	}
	
	printf("============\n");
	for(i=1;i<=10;i++)
	{
		for(j=1;j<=i;j++)
		{
			printf("%-6d",arr[i][j]);
		}
		printf("\n");
	}
	
	return 0;
}

7. 输出"魔方阵"。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。例如:

奇数的魔方阵

(1)将1放在第一行中间一列;
(2)从2开始直到n×n止各数依次按下列规则存放;每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列);
(3)如果上一个数的行数为1,则下一个数的行数为n(指最下一行);例如1在第一行,则2应放在最下一行,列数同样加1;
(4)当上一个数的列数为n时,下一个数的列数应为1,行数减去1。例如2在第3行最后一列,则3应放在第二行第一列;
(5)如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。例如按上面的规定,4应该放在第1行第2列,但该位置已经被占据,所以4就放在3的下面;

偶数的魔方阵(四阶魔方阵)

#include<stdio.h>

int main()
{
	printf("3阶魔方阵输出\n");
	
	int i, j, num, preRow, preCol, nowRow, nowCol;
	num = 1;
	int cube3 = 3 * 3;
	int intArr[3][3] = {0};
	while(num <= cube3){
		
		if(1 == num) {
			nowRow = 0; nowCol = 1;
			preRow = 0; preCol = 1;
			intArr[0][1] = num;
		}else {
			if(preRow == 0 && preCol != 2) {	//在第一行
//				intArr[2][preCol+1] = num;
//				preRow = 2; preCol = preCol + 1;
				nowRow = 2; nowCol = preCol + 1;
			}else if(preCol == 2 && preRow != 0) {	//在最后一列
//				intArr[preRow-1][0] = num;
//				preRow = preRow - 1; preCol = 0;
				nowRow = preRow - 1; nowCol = 0;
			}else if(preRow == 0 && preCol == 2) {	//第一行,最后一列
//				intArr[]
//				preRow = 2; preCol = 0;
				nowRow = 2; nowCol = 0;
			}else {
				nowRow = preRow -1;
				nowCol = preCol + 1;
			}
			
			if(intArr[nowRow][nowCol] != 0) { //上一行,下一列有数
//				intArr[preRow+1][preCol] = num;
//				preRow = preRow + 1;
//				preRow = preRow - 2; 
				nowRow = preRow + 1;
				nowCol = preCol;
				
			}
				
				intArr[nowRow][nowCol] = num;
				preRow = nowRow; preCol = nowCol;
		}	
		
		num++;
	}
	
	printf("输入3阶的魔方阵\n");
	for(i = 0; i < 3; i++) {
		for(j = 0; j < 3; j++) {
			printf("  %d  ",intArr[i][j]);
		}
		printf("\n");
	}
	
	printf("输出4阶魔方阵\n");
	num = 1;
//	int cube4 = 4 * 4;
	int cube4Arr[4][4] = {0};
	
	for(i = 0; i < 4; i++) {
		for(j = 0; j < 4; j++) {
			if(!(i == j || i + j == 3)) {
				cube4Arr[i][j] = num;
			}
			num++;
		}
	}
	
	num = 16;
	for(i = 0; i < 4; i++) {
		for(j = 0; j < 4; j++) {
			if(i == j || i + j == 3) {
				cube4Arr[i][j] = num;
			}
			num--;
		}
	}
	
	printf("==============\n");
	for(i = 0; i < 4; i++) {
		for(j = 0; j < 4; j++) {
			printf("%4d",cube4Arr[i][j]);
		}
		printf("\n");
	}
	
	return 0;
}

八阶魔方阵

8. 找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。

#include<stdio.h>

int main()
{
	printf("输入一个5*5的矩阵\n");
	int arr[5][5];
	int i, j, k, max, pos, min;
	for(i = 0; i < 5; i++){
		for(j = 0; j < 5; j++){
			scanf("%d",&arr[i][j]);
		}
	}
	
	int flag;	//判断是否找到鞍点,1是找到了,0是没找到
	for(i = 0; i < 5; i++){
		max = arr[i][0];
		pos = 0;
		for(j = 0; j < 5; j++) {
			if(max < arr[i][j]) {
				max = arr[i][j];
				pos = j;
			}
		}
		flag = 1;	
		min = arr[i][pos];
		for(k = 0; k < 5; k++) {
			if(min > arr[k][pos])
				flag = 0;
		}
		
		if(flag == 1) {
			printf("找到鞍点 %d %d %d\n", i + 1, pos + 1, arr[i][pos]); break;
		}
	}
	if(flag == 0)	printf("没有找到鞍点\n");
	
	return 0;
}

9. 有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出"无此数"。

注:如何找出该数是数组中第几个元素?答:通过索引下标(i + 1)即可找到该元素是该数组中第几个元素的值。

#include<stdio.h>

int main()
{
	printf("请输入一个有15位数的数组,然后再输入一个数,查找该数在数组中第几位。\n");
	
	int intArr[15];
	int i, j, num;
	for(i = 0; i < 15; i++) {
		scanf("%d", &intArr[i]);
	}
	printf("数组内容输入完成\n");
	
	scanf("%d",&num);
	
	int low, high, mid;
	low = 0; high = 14;
	while(low <= high) {
		mid = low + high;
		if(num == intArr[mid]) {
			printf("该数在数组中第%d位,其值为%d\n", mid + 1, num);	break;
		}else if(num < intArr[mid]) {
			high = mid - 1;
		}else {
			low = mid + 1;
		}
	}
	
	if(low > high)	printf("未在数组中找到%d\n", num);
	
	return 0;
}

10. 有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。

11. 输出一下图案:

* * * *
  * * * *
    * * * *
      * * * *
        * * * *
#include<stdio.h>

int main()
{
	for (int i = 0; i < 5; ++i)
	{
		for (int j = 0; j < i; ++j)
			printf("  ");
			
		printf("* * * *\n");
	}
	
	return 0;
}

12. 有一行电文,以按下面规律译成密码:

A--->Z   a--->z
B--->Y   b--->Y
C--->X   c--->x
……

即第1个字母编程第26个字母,第i个字母编程第(26-i+1)个字母,非字母字符不变,要求编程序将密码译回原文,并输出密码和原文。

#include<stdio.h>
#include<ctype.h>
#include<string.h>

int main()
{
	
	char str[30];
	scanf("%s",str);
	
	int len = (int)strlen(str);
	int i;
	for(i=0;i<len;i++)
	{
		if(islower(str[i]))
		{
			str[i] = 26-(str[i]-'a')-1+'a';
		}
		if(isupper(str[i]))
		{
			str[i] = 26-(str[i]-'A')-1+'A';
		}
	}
	
	printf("%s",str);
	
	
	return 0;
}

13. 编一程序,将两个字符串连接起来,不要用strcat函数

#include<stdio.h>

int main()
{
	void winnieStrcat(char *,char *);
	
	char s1[50], s2[50];
	scanf("%s",s1);
	scanf("%s",s2);
	
	winnieStrcat(s1,s2);
	
	printf("%s\n",s1);
	
	return 0;
}

void winnieStrcat(char *s1,char *s2) {
	char *p1, *p2;
	p1 = s1; p2 = s2;
	while(*p1 != '\0') {
		p1 = p1 + 1;
	}
	
//	int i;
	for(;*p2 != '\0'; p2++) {
		*p1 = *p2;
		p1 = p1 + 1;
//		p2 = p2 + 1;
	}
	*p1 = '\0';
}

14.编写一个程序,将连个字符串s1和s2比较,如果s1 > s2,输出一个整数;若s1 = s2,输出0;若s1 < s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相对应字符的ASCII码的差值。例如,“A"和“C”相比,由于"A” < “C”,应输出负数,同时由于‘A’与‘C’的ASCII码差值为2,因此应输出"-2"。同理:“And”和"Aid"相比较,根据第2个字符比较结果,“n"比"i"大5,因此应输出"5”。

#include<stdio.h>

int main()
{
	int winnieStcmp(char *,char *);
	
	char s1[50], s2[50];
	gets(s1);
	gets(s2);
	
	int r = winnieStcmp(s1,s2);
	
	printf("%d\n",r);
	
	return 0;
}

int winnieStcmp(char *s1,char *s2) {
	char *p1, *p2;
	p1 = s1; p2 = s2;
	while(*p1 != '\0' && *p2 != '\0') {
		if(*p1 - *p2 != 0)	return (*p1 - *p2);
		p1 = p1 + 1;
		p2 = p2 + 1;
	}
	
	if(*p1 == '\0' && *p2 != '\0') {
		return -1*(*p2);
	}else if(*p1 != '\0' && *p2 == '\0') {
		return *p1;
	}else return 0;
	
//	return *p1;
}

15. 编写一个程序,将字符数组s2中的全部字符复制到字符数组s1中,不用strcpy函数。复制时,‘\0’也要赋值过去。’\0’之后的字符不复制。

#include<stdio.h>

int main()
{
	void winnieStcpy(char *,char *);
	
	char s1[50], s2[50];
	scanf("%s",s1);
	scanf("%s",s2);
	
	winnieStcpy(s1,s2);
	
	printf("%s\n",s1);
	
	return 0;
}

void winnieStcpy(char *s1,char *s2) {
	char *p1, *p2;
	p1 = s1; p2 = s2;
	
	while(*p2 != '\0') {
		*p1 = *p2;
		p1 = p1 + 1;
		p2 = p2 + 1;
	}
	*p1 = '\0';

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值