#include<stdio.h>
#define maxn 105
int a[maxn];//数组一般会声明得稍大一些,防止越界
int main(){
int x, n = 0;
while(scanf("%d",&x) ==1){
//当输入不为int型数字时停止
a[n++] = x;
//n++先用n计算表达式,再将n加1;++n先将n加1,再计算表达式。
}
for(int i = n-1; i >= 1; i--){
printf("%d ", a[i]);
}
printf("%d\n",a[0]);
return 0;
}
用语句“int a[maxn]”声明一个包含maxn个整型变量的数组,即a[0],a[1],…,a[maxn-1],但不包含a[maxn]。maxn必须是常数,不能是变量。只有“int a[maxn]”在放外面时,数组a才可以开得很大。
数组不能够进行赋值操作,如果要从数组a复制k个元素到数组b,可以用:memcpy(b,a,sizeof(int)*k)(需要包含头文件string.h),如果要把数组a全部复制到数组b中,可以用:memcpy(b,a,sizeof(a)).
开灯问题: 有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号。k≤n≤1000。
#include <stdio.h>
#include <string.h>
#define maxn 1005
int a[maxn];
int main() {
int n,k,first = 1;
memset(a,0, sizeof(a));//把数组a清零
scanf("%d%d", &n, &k);
for(int i = 1; i<=k; i++){
for (int j = i; j <=n ; j+=i) {
a[j] = (a[j]+1)%2;//0变1,1变0,这样省去了用if判断
}
}
for (int j = 1; j <=n ; j++) {
if(a[j]==1){
if(first == 1)
//标志变量first表示当前要输出的变量是否为第一个。第一个变量前不应有空格,但其他变量都有。
first =0;
else
printf(" ");
printf("%d",j);
}
}
return 0;
}
在很多情况下,最好是在做一件事之前检查是不是可以做,而不要做完再后悔。因为“悔棋”往往比较麻烦。
C语言中的字符型用关键字char表示,它实际存储的是字符的ASCII码。字符常量可以用单引号法表示。在语法上可以把字符当作int型使用。
“scanf("%s", s)”会读入一个不含空格、TAB和回车符的字符串,存入字符数组s。注意s前面没有“&”符号。如果是字符串数组chars[maxn] [maxl],可以用“scanf("%s", s[i])”读取第i个字符串。
可以用sprintf把信息输出到字符串,用法和printf、fprintf类似。但应当保证字符串足够大,可以容纳输出信息。
C语言中的字符串是以“\0”结尾的字符数组,可以用strlen(s)返回字符串s中结束标记之前的字符个数。
竖式问题: 找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中,所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。
#include<stdio.h>
#include<string.h>
int main()
{
int count = 0;
char s[20], buf[99];
scanf("%s", s);
for(int abc = 111; abc <= 999; abc++)
for(int de = 11; de <= 99; de++)
{
int x = abc*(de%10), y = abc*(de/10), z = abc*de;
sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z);
int ok = 1;
for(int i = 0; i < strlen(buf); i++)
if(strchr(s, buf[i]) == NULL)
ok = 0;//strchr的作用是在一个字符串中查找单个字符
if(ok)
{
printf("<%d>\n", ++count);
printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc, de, x, y, z);
}
}
printf("The number of solutions = %d\n", count);
return 0;
}
“scanf("%s")”可以输入字符串,但它碰到空格或者TAB就会停下来。虽然下次调用时会输入下一个字符串,可是不知道两次输入的字符串中间有多少个空格、TAB甚至换行符。
两种方法读取带空格、TAB或换行符的字符串:
1. “fgetc(fin)”读取一个打开的文件fin,读取一个字符,然后返回一个int值。如果文件结束,fgetc将返回一个特殊标记EOF。从标准输入读取一个字符可以用getchar,它等价于fgetc(stdin)。
不同操作系统的回车换行符是不一致的,在使用fgetc和getchar时,应该避免写出和操作系统相关的程序。
2. 使用“fgets(buf, maxn, fin)”读取完整的一行,其中buf的声明为char buf[maxn]。这个函数读取不超过maxn-1个字符,然后在末尾添上结束符“\0”,因此不会出现越界的情况。一旦读到回车符“\n”,读取工作将会停止,而这个“\n”也会是buf字符串中最后一个有效字符(再往后就是字符串结束符“\0”了)。
表达式式"a?b:c"的含义是:当a为真时值为b,否则为c
常量数组并不需要指明大小,编译器可以完成计算。
#include<ctype.h>
if(isalpha(ch))//判断字符ch是否为字母,函数isalpha()包含在库ctype.h中
例题3-4 猜数字游戏的提示
实现一个经典"猜数字"游戏。给定答案序列和用户猜的序列,统计有多少数字位置正确(A),有多少数字在两个序列都出现过但位置不对(B)。
输入包含多组数据。每组输入第一行为序列长度n,第二行是答案序列,接下来是若干猜测序列。猜测序列全0时该组数据结束。n=0时输入结束。
#include <stdio.h>
#include <cstring>
#define maxn 100005
int ans[maxn];
int ges[maxn];
int A[maxn];
int B[maxn];
int main() {
int n,game=0;
memset(ans,0, sizeof(ans));//初始化数组
memset(ges,0, sizeof(ges));
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
while(scanf("%d",&n)&& n != 0){
//当输入n==0时停止
game++;
int tag1[15] = {
0},tag2[15] = {
0};
for(int i =0; i<n; i++){
scanf("%d",&ans[i]);//输入答案
tag1[ans[i]]++;//记录答案中每个数字出现的次数
}
int flag = 0,tot = 0;
while(flag != n){
//当输入全0时一组结束
flag =0;
for(int i =0; i<n; i++){
scanf("%d",&ges[i]);
tag2[ges[i]]++;//记录每次猜测中每个数字出现的次数
if(ges[i]==0)
flag++;
}
for(int i =0; i<n; i++){
if(ges[i]==ans[i])
A[tot]++;//记录每组猜测中位置正确的数量
}
for(int i =1; i<10; i++){
B[tot] +=((tag1[i]>tag2[i])? tag2[i] :tag1[i]);
//记录在两个序列都出现过但位置不对的数量
tag2[i] = 0;//用完归零
}
B[tot] -= A[tot];
tot++;
}
printf("Game %d:\n",game);
for (int i = 0; i < tot-1; ++i) {
printf("(%d,%d)\n",A[i],B[i]);//输出每组结果
}
memset(tag1,0, sizeof(tag1));//重置数组
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
}
return 0;
}
/*
4
1 3 5 5
1 1 2 3
4 3 3 5
6 5 5 1
6 1 3 5
1 3 5 5
0 0 0 0
10
1 2 2 2 4 5 6 6 6 9
1 2 3 4 5 6 7 8 9 1
1 1 2 2 3 3 4