第3章 数组与字符串

3.1 数组

程序3.1 逆序输出(读入一些整数,不超过100个,逆序输出到一行中)
#include <stdio.h>
#define maxn 105   //常常难以精确计算出需要的数组大小,数组一般会比声明的稍大一点,会更保险
int buf[maxn];     //因为局部变量存放在堆栈段中,若放在函数体内可能会导致栈溢出,一般在全局部分声明较大的数组
int main()
{
	int x, n = 0;
	while(scanf("%d", &x) == 1)
		buf[n++] = x;
	for(int i = n-1; i >= 1; i--)
		printf("%d ", buf[i]);
	printf("%d\n", buf[0]);
	return 0;
}
在头文件<string.h>中定义了函数memcpy和memset
#include<stdio.h>
#include <string.h>
int main()
{
	int a[5], b[5] = {1, 2, 3, 4, 5};
	memset(a, 1, sizeof(a));   //memset是对每个字节赋值,而int有4字节(32位),则每个元素为00000001000000010000000100000001,即16843009
	memcpy(b, a, sizeof(int) * 4);  //是将a的前4个元素赋值给b;若需要全部赋值,则用memcpy(b, a, sizeof(a))
	for(int i = 0; i<5; i++)
		printf("%d ",a[i]);
	printf("\n");
	for(int i = 0; i<5; i++)
		printf("%d ",b[i]);
	return 0;
}
程序3.2 开灯问题(编号为1~n的n盏灯,刚开始灯全部关闭,第1个人将按下所有的灯,第2个人按下编号为2的倍数的灯,第3个人按下编号为3的倍数的灯……一共有k个人,问最后哪些灯是开着的)
算法分析:先用一个数组a[maxn],其中a[1],a[2],……a[n]分别表示1~n的灯是否开着,最初给数组全部初始化为0,之后当有人按下灯后,令a[i] = !a[i](之后a[i]为0或者1),最后根据if(a[i])来判断输出。
#include<stdio.h>
#include <string.h>
#define maxn 1010
int a[maxn];
int main()
{
	int n, k;
	memset(a, 0, sizeof(a));
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= k; i++){
		for(int j = i; j <= n; j+=i){  //for(int j = 1; j <= n; j++) if(j %i == 0) a[j] = !a[j];
			a[j] = !a[j];
		}
	}
	int first = 1;
	for(int i = 1; i <= n; i++){
		if(a[i]) 
		{ 
			if(first) { printf("%d", i); first = 0; }
			else printf(" %d", i);
		}
	}
	printf("\n");
	return 0;
}
蛇形填数:(在n*n方阵中填入1,2,……,n*n,要求填成蛇形,起点是在右上角(1, n)处)
算法分析:用一个int a[maxn][maxn]生成一个整型的二维数组并初始化为0,“笔”的轨迹是下,左,上,右的循环,朝一个方向走,直到遇到边界(大于n或者小于1或者已经被赋值的点)时停止走,走的同时给数组赋值。直至走到第n*n步。。。
#include <stdio.h>
#include <string.h>
#define maxn 20
int a[maxn][maxn];
int main()
{
	memset(a, 0, sizeof(a));
	int n;
	scanf("%d", &n);
	a[1][n] = 1;
	int x = 1, y = n, count = 1;
	while(count < n*n){
		while(x+1 <= n && !a[x+1][y]) a[++x][y] = ++count;  //不断往下走,并且填数,先判断,再移动,而不应该走完之后再退回来,对于a[x][y]而言往下走的元素为a[x+1][y],判断为0后再对a[++x][y]赋值
		while(y-1 >= 1 && !a[x][y-1]) a[x][--y] = ++count;
		while(x-1 >= 1 && !a[x-1][y]) a[--x][y] = ++count;
		while(y+1 <= n && !a[x][y+1]) a[x][++y] = ++count;
	}
	for(x = 1; x <= n; x++){
		for(y = 1; y <= n; y++){
			printf("%5d", a[x][y]);
		}
		printf("\n");
	}
	return 0;
}

3.2 字符数组

竖式问题(输入数字集合,找出所有形如abc*de的算式,使得其对应完整的竖式内,所有数字都属于此数字集合,输出所有竖式,要求竖式前带有序号,之后有个空行,并输出解的总数)
算法分析:用字符串形式输入数字集合方便后续查找,尝试所有的abc和de,判断是否满足条件,可先将abc,de,abc*d,abc*e以及abc*de用sprintf放入一个字符串中,再对此字符串的每个字符用strchr进行查找,看是否全部位于数字集合类。
#include <stdio.h>
#include <string.h>
char set[20], buf[100];
int main()
{
	int kase = 0;
	scanf("%s", set);
	for(int abc = 100; abc <= 999; abc++){
		for(int de = 10; de <= 99; de++){
			int tmp1 = abc * (de/10), tmp2 = abc * (de%10), sum = abc * de;
			sprintf(buf, "%d%d%d%d%d", abc, de, tmp1, tmp2, sum);
			int tag = 1;
			for(int i = 0; buf[i]; ++i)
				if(strchr(set, buf[i]) == NULL) tag = 0;
			if(tag){
				printf("<%d>\n", ++kase);
				printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc, de, tmp1, tmp2, sum);
			}
		}
	}
	printf("The number of solutions = %d\n", kase);
	return 0;
}
补充:在头文件<stdio.h>中,printf是输出到屏幕,sprintf是输出到字符串,fsprintf是输出到文件中,sprintf的用法如下:
#include <stdio.h>
int main()
{
	char *who = "I";
    char *whom = "CSDN";
	char s[99];
	sprintf(s, "%s love %s.", who, whom);
	printf("%s\n", s);                  //输出I love CSDN.
	sprintf(s, "%.3f", 3.141592654);
	printf("%s", s);                    //输出3.142
	return 0;
}
对于一维数组的scanf("%s", s);和二维数组中第i行的输入scanf("%s", s[i]);,和输入单个变量一样,遇到空白(空格,换行及退格)时读取输入,字符串本质是数组,可以用strcpy(a, b),strcmp(a, b),strcat(a, b)来进行操作。数组中需多预留1字节来保存字符串。”\"以及“"”都可以表示双引号。

3.3 竞赛题目选讲

例题3.1 Tex中的引号(将普通文本的双引号格式" "变为Tex格式的双引号格式`` ’’)
例题3.2 WERTYU (将手放在键盘上,稍不注意就会往右错一位,如想输入Q就会变成输入W等,要求将错误的输入还原成正确的输入)
例题3.3 回文词
例题3.4 猜数字游戏的提示

3.4 注解与习题





























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值