3.1数组
数组较大
比较大的数组尽量声明在main函数外,否则程序可能无法进行。
数组操作
如果要从数组a复制k个元素到数组b,可以这样做:memcpy(b,a,sizeof(int)*k)
。
如果数组a和b都是浮点型的,复制时要写成memcpy(b,a,sizeof(double)*k)
。
另外需要注意的是, 使用memcpy函数要包含头文件string.h
。
如果需要把数组a全部复制到数组b中,可以写得简单 一些:memcpy(b,a,sizeof(a))
。
开灯问题
有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号。k≤n≤1000。
样例输入:
7 3
样例输出:
1 5 6 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
蛇形填数
在n×n方阵里填入1,2,…,n×n,要求填成蛇形。例如,n=4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n≤8。
- 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
3.2字符数组
竖式问题
找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中, 所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。具体格式见样例输出 (为了便于观察,竖式中的空格改用小数点显示,但所写程序中应该输出空格,而非小数点)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 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
输入字符串
scanf("%s", s)
和scanf("%d", &n)
类似,它会读入一个不含空格、
TAB和回车符的字符串,存入字符数组s。注意,不是scanf("%s", &s)
,s前面没有“&”符 号。
在scanf("%s", s)
中,不要在s前面加上“&”符号。如果是字符串数组char
s[maxn] [maxl]
,可以用scanf("%s", s[i])
读取第i个字符串。注意,scanf("%s",
s)
遇到空白字符会停下来。
printf,fprintf,sprintf的区别
printf输出到屏幕
fprintf输出到文件
sprintf输出到字符串
可以用sprintf把信息输出到字符串,用法和printf、fprintf类似。但应当保 证字符串足够大,可以容纳输出信息。
多大才算足够大呢?答案是字符个数加1,因为C语言的字符串是以空字符“\0”结尾的。
字符串函数
C语言中的字符串是以“\0”结尾的字符数组,可以用strlen(s)返回字符串s中结束标记之前的字符个数。字符串中的各个字符是s[0], s[1],…,s[strlen(s)-1]
。
由于字符串的本质是数组,只能用strcpy(a, b), strcmp(a, b), strcat(a, b)来执行“赋值”、“比较”和“连接”操作,而不能用“=”、“==”、 “<=”、“+”等运算符。上述函数都在string.h
中声明。
如果输入是“2357”,那么实际上s只保存了5个字符(不 忘记了还有一个结束标记“\0”),后面15个字符是不确定的(还记得吗?变量在赋值之前是不确定的)。strlen(s)返回的就是结束标记之前的字符个数。因此这个字符串中的各个字符依次是s[0], s[1],…, s[strlen(s)-1]
,而s[strlen(s)]
正是结束标记\0
。
3.3竞赛题目选讲
例题3-1 TeX中的引号(Tex Quotes, UVa 272)
在TeX中,左双引号是““”,右双引号是“””。输入一篇包含双引号的文章,你的任务是把它转换成TeX的格式。
样例输入:
- 1
样例输出:
- 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
例题3-2 WERTYU(WERTYU, UVa10082)
把手放在键盘上时,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。
输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子。输入保证合法,即一定是错位之后的字符串。例如输入中不会出现大写字母A。
样例输入:
O S, GOMR YPFSU/
样例输出:
I AM FINE TODAY.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
例题3-3 回文词(Palindromes, UVa401)
输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。所谓回文串,就是反转以后和原串相同,如abba和madam。所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE。注意,并不是每个字符在镜像之后都能得到一个合法字符。在本题中,每个字符的镜像如图3-3所示(空白项表示该字符镜像后不能得到一个合法字符)。
输入的每行包含一个字符串(保证只有上述字符。不含空白字符),判断它是否为回文串和镜像串(共4种组合)。每组数据之后输出一个空行。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 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
头文件ctype.h
头文件ctype.h中定义的isalpha、isdigit、isprint等工具可以用来判断字符的属性,而toupper、tolower等工具可以用来转换大小写。如果ch是大写字母,则ch-‘A’就是它在字母表中的序号(A的序号是0,B的序号是1,依此类推);类似地,如果ch是数字, 则ch-‘0’就是这个数字的数值本身。
例题3-4 猜数字游戏的提示(Master-Mind Hints, UVa 340)
实现一个经典”猜数字”游戏。给定答案序列和用户猜的序列,统计有多少数字位置正确 (A),有多少数字在两个序列都出现过但位置不对(B)。
输入包含多组数据。每组输入第一行为序列长度n,第二行是答案序列,接下来是若干猜测序列。猜测序列全0时该组数据结束。n=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
- 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
- 36
- 37
- 38
- 39
- 40
- 41
- 42
例题3-5 生成元(Digit Generator, ACM/ICPC Seoul 2005, UVa1583)
如果x加上x的各个数字之和得到y,就说x是y的生成元。给出n(1≤n≤100000),求最小生成元。无解输出0。例如,n=3,输入216,121,2005时的解分别为198,0,1979。
- 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
例题3-6 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)
长度为n的环状串有n种表示法,分别为从某个位置开始顺时针得到。例如,图3-4的环状串有10种表示:
CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称 为”最小表示”。
输入一个长度为n(n≤100)的环状DNA串(只包含A、C、G、T这4种字符)的一种表示法,你的任务是输出该环状串的最小表示。例如,CTCC的最小表示是 CCCT,CGAGTCAGCT的最小表示为AGCTCGAGTC。
- 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
字典序
所谓字典序,就是字符串在字典中的顺序。一般地, 对于两个字符串,从第一个字符开始比较,当某一个位置的字符不同时,该位置字符较小的串,字典序较小(例如,abc比bcd小);如果其中一个字符串已经没有更多字符,但另一个字符串还没结束,则较短的字符串的字典序较小(例如,hi比history小)。字典序的概念可以推广到任意序列,例如,序列1, 2, 4, 7比1, 2, 5小。
3.4注解与习题
习题3-1 得分(Score, ACM/ICPC Seoul 2005, UVa1585)
给出一个由O和X组成的串(长度为1~80),统计得分。每个O的得分为目前连续出现的O的个数,X的得分为0。例如,OOXXOXXOOO的得分为1+2+0+0+1+0+0+1+2+3。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)
给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分 别为C, H, O, N,原子量分别为12.01, 1.008, 16.00, 14.01(单位:g/mol)。例如,C6H5OH的 分子量为94.108g/mol。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 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
- 36
- 37
- 38
习题3-3 数数字(Digit Counting , ACM/ICPC Danang 2007, UVa1225)
把前n(n≤10000)个整数顺次写在一起:123456789101112…数一数0~9各出现多少次 (输出10个整数,分别是0,1,…,9出现的次数)。
- 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
习题3-4 周期串(Periodic Strings, UVa455)
如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例 如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。
输入一个长度不超过80的字符串,输出其最小周期。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 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
习题3-5 谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)
有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This puzzle has no final configuration.”,例如,图3-5中执行ARRBBL0后,效果如图3-6所示。
- 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
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 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
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
C语言 gets()和scanf()函数的区别
scanf( )函数和gets( )函数都可用于输入字符串,但在功能上有区别。若想从键盘上输入字符串”hi hello”,则应该使用gets函数。
gets可以接收空格;而scanf遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格。
char string[15]; gets(string);
/遇到回车认为输入结束/
scanf("%s",string);
/遇到空格认为输入结束/
所以在输入的字符串中包含空格时,应该使用gets输入。
在C语言中,能构获取字符串的函数至少有两个:
1.scanf()
所在头文件:stdio.h
语法:scanf(“格式控制字符串”,变量地址列表);
接受字符串时:scanf(“%s”,字符数组名或指针);
2.gets()
所在头文件:stdio.h
语法:gets(字符数组名或指针);
两者在接受字符串时:
1.不同点:
scanf不能接受空格、制表符Tab、回车等;
而gets能够接受空格、制表符Tab和回车等;
2.相同点:
字符串接受结束后自动加’\0’。
例1:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
依次键入asd空格fg回车,asd空格fg回车,则ch1=”asd\0”,ch2=”asd fg\0”。
例2:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
依次键入asdfg回车,asdfg回车,则ch1=”asdfg\0”,c1=’\n’,ch2=”asdfg\0”,c2需输入。
- 1
- 2
- 3
- 4
C语言puts()函数:将一个字符串放入标准输出流(stdout)中
头文件:#include<stdio.h>
puts()函数用于将一字符串放到标准输出流(stdout)中,并在最后增加换行符 ‘\n’,其函数原型如下:
int puts(char *string);
【参数】string为要输出的字符串。
【返回值】输出成功返回非0值,否则返回0。
puts()从string的开头往stdout中输出字符,直到遇见结束标志 ‘\0’,’\0’不会被输出到stdout。
习题3-6 纵横字谜的答案(Crossword Answers, ACM/ICPC World Finals 1994, UVa232)
输入一个r行c列(1≤r,c≤10)的网格,黑格用“*”表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。
首先把所有起始格按照从上到下、从左到右的顺序编号为1, 2, 3,…,如图3-7所示。
接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,向右延伸到 一个黑格的左边或者整个网格的最右列。最后找出所有竖向单词(Down)。这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。