【学习小感】
因为每次做完一个习惯性直接删,但是感觉又有点可惜,留着又不想建一堆文件,故贴一个。(2020/7)
7月份开始断断续续学这本书,作为一个非cs科班同学,本科C语言基础大多来自计算机二级的刷题。八月份主要在准备图论期末考试,九月份过了大众校企班的笔试面试。十月份第一次参加IEEEEXTREME极限编程大赛,试着加快了啃书速度,但是发现还是自己静下心来做过的那些题有用,在比赛的时候能感觉到有不少做过的题的影子。最开始还是按照自己的写码思路写书上的题目,不会的时候就敲一敲书上的代码,后来逐渐迁移学习模仿书上的代码风格,确实比自己的高级很多。感谢我刚开始写代码时师父的辅导,没有师父我真的可能开始都坚持不下来。也感谢师父现在也会陪我改bug,最后感谢学妹陪我一起打比赛写C++,持续24小时的编程,最终进了top10%,真的太不容易了。(2020/10)
第一章
例题1-4 鸡兔同笼
#include <stdio.h>
#include <math.h>
int main()
{
int m,n,x,y;
scanf("%d%d",&n,&m);
y = (m - 2*n)/2;
x = n - y;
if (x >= 0 && y >=0 && x % 2 == 0 && y % 2 == 0) {
printf("chicken is %d rabbit is %d",x,y);
}
else {
printf("no answer");
}
}
for循环
#include <stdio.h>
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
printf("%d\n",i);
}
return 0;
}
第二章
例题2-1 输出所有aabb形完全平方数
#include <stdio.h>
#include <math.h>
int main(){
// float n;
// int m;
for (int a = 1; a <= 9; a++){
for (int b = 1; b <= 9; b++){
int n = a*1100 + b*11; //构成aabb
//printf("%d\n",n);
float m = sqrt(n);
m = floor(m+0.5);
if (m*m == n){
printf("Yes,%d",n);
}
}
}
return 0;
}
输出真是7744
例题2-2 3n+1
#include <stdio.h>
#include <math.h>
int main(){
// float n;
// int m;
int m,n;
m = 0;
scanf("%d",&n);
while (n>1){
m++;
if (n % 2 == 1){
n = 3*n + 1;
}
else{
n = n/2;
}
}
printf("%d\n",m);
return 0;
}
例题2-3 近似计算
#include <stdio.h>
#include <math.h>
int main(){
double sum = 0;
for(int i = 0; ; i++){
double term = 1.0/(2*i + 1);
if (i % 2 == 0){ //double
sum = sum + term;
}
else sum = sum - term;
if (term<1e-6) break;
}
printf("%.4f",sum);
return 0;
}
用于查看代码运行时间
#include <time.h>
printf("%.2f\n",(double)clock()/CLOCKS_PER_SEC);
例题2-4 阶乘之和 保留后六位
int main(){
int n,sum=0,term=1;
scanf("%d",&n);
for (int i = 1; i <= n; i++){
for (int j = 1; j <= i; j++){
term = term * j;
}
sum = sum + term;
term = 1;
}
printf("%d",sum % 100000);
return 0;
}
例题2-5 数据统计
在这里插入代码片#include <stdio.h>
#include <math.h>
//数据统计
int main(){
int x, n = 0,s = 0; //n为j计数器
long min = 10000, max = - 10000;
while (scanf("%d", &x) == 1){
s += x;
if (x>=max){
max = x;
}
else if (x<=min){
min = x;
n++;
}
}
printf("%d %d %.3f\n", min, max, (double)s/n);
}
习题2
1 水仙花数
2 韩信点兵
#include <iostream>
#include <string>
using namespace std;
int main(){
int a,b,c;
int flag = 0;
cin>>a;
cin>>b;
cin>>c;
for (int i=1; i<100; i++){
if((i%3==a)&&(i%5==b)&&(i%7==c)){
cout<<i<<endl;
flag = 1;
}
}
if (flag ==0){
cout<<"no answer"<<endl;
}
system("pause");
}
3 倒三角形
【这道题用反向计数(递减)会方便很多】
#include <iostream>
#include <string>
using namespace std;
int main(){
int n;
cin>>n>>endl;
for (int i=1;i<=n;i++){ //行数
if (i==1){
for (int t=1;t<=2*n-1;t++){
cout<<"#";
}
cout<<endl;
}
else{
for (int x=1;x<i;x++){
cout<<" ";
}
for (int y=i;y<2*n-i;y++){
cout<<"#";
}
for (int z=2*n-i;z<2*n;z++){
cout<<" ";
}
cout<<endl;
}
}
system("pause");
}
这个报错了我不知道为什么【更新:cin不能写endl】
我过会去试一试
更新:这里报错是输入的问题 参考了其他的用c重新写了一下是对的
这个方法更加的简洁
#include <stdio.h>
#include <stdlib.h>
int main(){
int i,j,k,n;
scanf("%d",&n);
for (i=n;i>0;i--){
for (j=0;j<n-i;j++){
printf(" ");
}
for (k=0;k<2*i-1;k++){
printf("#");
}
printf("\n");
}
//return 0;
system("pause");
}
4 子序列的和
【这道题因为涉及到了平方,所以样例输入中有一个655360太大了会溢出】
【解决方法有两个,一个是用longlong int(亲测long不够),还有一个是用1/n/n(这个好聪明啊)】
#include <stdio.h>
#include <stdlib.h>
int main(){
int m,n;
double sum=0.0;
int a[100],b[100];
int flag=0;
while(1){
scanf("%d",&n);
scanf("%d",&m);
a[flag]=n;
b[flag]=m;
if (m==0&&n==0){
break;
}
flag++;
}
printf("%d\n",flag);
for (int j=0;j<flag;j++){
for (long long i=a[j]; i<=b[j]; i++){
sum += 1.0/double(i*i);
//printf("in");
}
printf("Case %d ",j+1);
printf("%.5f\n",sum);
sum =0.0;
}
system("pause");
}
这个数组实际上是有问题的,我还不知道怎么处理这个问题qwq
5 分数化小数
【1.我在调代码的过程中发现,如果使用%f对一个int型输出,会输出0.0000,并不如想象中的会输出带小数的这个数。
正确方法:对(float)a进行%f输出。】
【2.这种000结束输入的时候,做flag或者是count在000判断以后再计数会更好理解。
000读入以后直接break,不进入计数。】
【3.printf的特殊用法—*控制输出宽度和精度
控制输出精度
正常是eg %.2f
小数点后.的数字表示输出精度位数
(同样的方法也可用于输出字符串)
printf格式字符串、数,与宽度控制和精度控制有关的常量都可以换成变量
在格式输出的"%.*f\n",1(用于替代当中的星号),变量。
#include <stdio.h>
#include <stdlib.h>
int x,y,z;
int a[10];
int b[10];
int c[10];
int flag = 0;
int main(){
//输入
while(1){
scanf("%d",&x);
scanf("%d",&y);
scanf("%d",&z);
a[flag]=x;
b[flag]=y;
c[flag]=z;
//printf("a flag is %d\n",a[flag]); //测试是不是读入
if (x==0&&y==0&&z==0){
break;
}
flag++;
}
//printf("%d\n",flag); //多少组数据
for (int i = 0;i<flag;i++){
printf("Case %d : %.*f\n",i+1,c[i],(float)a[i]/b[i]);
}
system("pause");
}
6 排列
用1~9组成三个三位数,每个数字恰好用一次,要求1:2:3
#include <stdio.h>
#include <stdlib.h>
int a[9]={0,0,0,0,0,0,0,0,0};
int real_flag=0;
int c =0;
int judge(int num1, int num2, int num3){
a[0]=num1/100; //bai
a[1]=num1%100/10; //shi
a[2]=num1%10; //ge
a[3]=num2/100; //bai
a[4]=num2%100/10; //shi
a[5]=num2%10; //ge
a[6]=num3/100; //bai
a[7]=num3%100/10; //shi
a[8]=num3%10; //ge
int flag=0;
for (int j=0;j<9;j++){
for(int k =j+1;k<9;k++){
if(a[j]==a[k]){
flag++;
}
if(a[j]==0){
flag++;
}
}
}
if (flag==0){
real_flag++;
}
return real_flag;
}
int main(){
for (int i = 100; i<334; i++){ //abc
int def = 2*i, ghi = 3*i;
int b = judge(i, def, ghi);
if (b>c){
printf("%d %d %d\n",i,def, ghi);
}
c=b;
}
system("pause");
}
第三章 数组和字符串
3.1 数组
例题1 逆序输出
#include <stdio.h>
#include <stdlib.h>
//读入一些整数,逆序输出
#define maxn 105
int a[maxn];
int main()
{
int x,n=0;
while(scanf("%d",&x)==1){
a[n++]=x;
}
for (int i=n-1;i>=0;i--){
printf("%d ",a[i]);
}
printf("%d\n",a[0]);
system("pause");
}
例题2 开灯问题
#include <stdio.h>
#include <stdlib.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=1;j<=n;j++){
if (j%k==0){
a[j]++;
}
}
}
for (int k=1;k<=n;k++){
if (a[k]%2==0){
printf("%d is off", k);
}
else printf("%d is on",k);
}
system("pause");
}
例题3 蛇形数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//蛇形填数
#define maxn 10
int a[maxn][maxn];
int main(){
int x,y,n; //输入n*n大小的正方型
int max,min; //用于记录每次的循环的最大最小值
scanf("%d",&n);
memset(a, 0, sizeof(a)); //清零数组a
max = n-1;
min = n-1-max;//默认为0
//每一次循环填数都是下左上右的一个过程
for (int i=0;i<n*n;){
//if(min>=max){break;}
//考虑开始的最大值的【数组】坐标 a[0][max-1]
//下
for (int j=min; j<=max; j++){
if (i>=n*n) break;
a[j][max]=++i;
}
//左
for (int k=max-1; k>=min; k--){
if (i>=n*n) break;
a[max][k]=++i;
}
//上
for (int l=max-1; l>=min; l--){
if (i>=n*n) break;
a[l][min]=++i;
}
//右
for (int m=min;m<max-1;m++){
if (i>=n*n) break;
a[min][m+1]=++i;
}
if (i>=n*n) break;
max--;
min = n-1-max;
}
//输出数组
for (int x=0;x<n;x++){
for (int y=0;y<n;y++){
printf("%3d",a[x][y]);
}
printf("\n");
}
system("pause");
}
例题4 竖式问题
//竖式问题
//找出形如abc*de的
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char s[20],buf[99];
int num = 0;
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=x+10*y; //分别定义后个位相乘结果,十位相乘结果,总乘积
sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z);
int flag = 1;
//检测buff中每个字符是不是都与s中重合
for(int i=0; i<strlen(buf); i++){
if (strchr(s,buf[i])==NULL){
flag = 0;
}
//如果重合,说明这一组里的数字是可以用的,进行一次样例输出
}
if (flag){
printf("<%d>\n",++num);
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", num);
system("pause");
}
【例题3-1 TEX中的引号】
这个是书上写的
#include <stdio.h>
#include <stdlib.h>
int main(){
int c,q =1;
while((c = getchar())!=EOF){
if (c == '"'){
printf("%s",q ? "``" : "''");
q = !q;
}
else printf("%c",c);
}
system("pause");
}
然后这个是我写的
#include <stdio.h>
#include <stdlib.h>
int main(){
int c, flag = 0;
while((c = getchar())!=EOF){
if (c == '"'){
if (flag == 0){
printf("%s", "``");
}
else{
printf("%s", "''");
}
flag = !flag;
}
else printf("%c",c);
}
}
⚠️注意点
1.注意输出双引号
’ ’ 引起的一个字符代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值;
” ”引起的字符串代表的是一个指向无名数组起始字符的指针。
C语言中的单引号用来表示字符字面量
C语言中的双引号用来表示字符串字面量(指针)
2.getchar返回值类型为int ASCII码
以及char型变量其实也是数字。
如果要定义字符串:
char s[] = “abcde”;
但是这个字符数组中每个字符也是按ASCII码存储的,如果不是按c输出的话应该也是一个int整数。
【例题3-2 WERTYU】
【注意点】
- 因为\是转义字符,所以字符串里面要输出\就必须写成\
- 思路是用getchar()先输入字符,输入字符再数组中寻找是否有相同/对应的字符。
- c语言中的读取数组长度:用sizeof(数组)
我有看到说要除以数据类型长度的,但是我尝试了字符串数组就是sizeof(字符串数组)
· 字符串数组好像是可以不写大小直接写
但是数字数组好像不行
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char s[] = "`1234567890-=QWERTYUIOP[]ASDFGHJKL;'\\ZXCVBNM,./";
int main(){
int c;
printf("%d\n",sizeof(s));
while((c=getchar())!=EOF){ //输入
for (int i=0; i<sizeof(s); i++){
if (s[i]==c){
printf("%c\n",s[i-1]);
}
}
}
system("pause");
}
例题3-4 猜数字游戏的提示
题目要求读入一组答案 一组猜测
猜测中,A为答案和猜测中数字相同且位置相同的个数
B为数字相同但位置不同的个数
题目答案给了一个方法求解B:统计答案和猜测中1-9中数字的出现频次,取最小值,再减去A就是数字相同但位置不同的个数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int maxn = 100;
int a[maxn],b[maxn];
int main(){
int n;
int count = 0;
while(scanf("%d",&n)&&n!=0){ //n!=0
//读入正确答案
printf("Game %d:\n",++count);
for (int i = 0;i < n; i++){
scanf("%d",&a[i]);
}
//读入猜测
for (; ;){
int flag = 0;
int A=0, B=0;
for (int i = 0;i < n; i++){
scanf("%d",&b[i]);
if(b[i]==0) flag++;
if(b[i]==a[i]) A++;
}
if (flag == n) break;
//统计a和b中1-9出现的频次 按最小的计数
for (int i = 1; i < 10; i++){
int c1=0,c2=0;
for (int j = 0; j < n; j++){
if(a[j]==i) c1++;
if(b[j]==i) c2++;
}
//比较当前数字中c1和c2的大小,取小
if (c1>c2) B = B + c2;
else B = B + c1;
}
//统计完后B需要减掉A
printf("(%d,%d)\n",A,B-A);
}
}
system("pause");
}
第四章 函数和递归
第五章 STL入门
例题5-1 大理石在哪儿
本题主要难度在于搞清楚输入。在这些练习下对于输入已经有了一定的理解,所以不是很难。然后就是stl中的两个函数,sort和lower_bound
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100;
int main(){
int n,q,a[maxn],count=0,x; //n:n个石头,q:q个问题
while(scanf("%d%d",&n,&q)==2&&n){
printf("Case# %d\n",++count);
for (int i = 0; i < n ; i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
printf("sorted result is:");
for (int i = 0; i < n; i++){
printf("%d",a[i]);
}
printf("\n");
while(q--){
scanf("%d",&x);
if(binary_search(a,a+n,x)){
int *t = lower_bound(a,a+n,x);
printf("%d found at %d", x, t-a+1);
}
else printf("%d not found", x);
}
}
system("pause");
}
c++:结构体与排序
#include <iostream>
#include <algorithm>
#include "cstring"
#include <stdlib.h>
using namespace std;
struct Student
{
char name[20];
int math;
int english;
};
bool cmp(Student a, Student b);
int main(){
Student a[4] = {{"apple",67,89},{"banana",90,56},{"apple",90,99}};
sort(a,a+3,cmp);
for (int i = 0;i < 3; i++ ){
cout << a[i].name <<" "<<a[i].math<<" "<<a[i].english << endl;
}
system("pause");
}
bool cmp(Student a, Student b){
if (a.math != b.math){
return a.math>b.math;
}
else return a.english > b.english;
}
例题5-2 木块问题
用vector表示每个高度 定长数组表示木块堆
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
const int maxn= 30;
int n;
vector<int> pile[maxn]; //声明pile数组,数组每个元素都是一个vector
//堆:0~n-1共n堆
//pile:堆号 height:堆的高度
//寻找出木块a在的pile和height
void find_block(int a, int &p, int &h){
for (p=0; p<n; p++)
for (h=0; h<pile[p].size();h++)
if(pile[p][h]==a) return;
}
//删除第p堆高度为h以上的所有木块【移回原来的堆】
void clear_above(int p,int h){
for (int i=h+1; i<pile[p].size(); i++){
int b=pile[p][i];
pile[b].push_back(b);
}
pile[p].resize(h+1);
}
void pile_onto(int p, int h, int p2){
for (int i=h; i<pile[p].size();i++){
pile[p2].push_back(pile[p][i]);
}
pile[p].resize(h); //只保留0~h-1
}
void print(){
for (int i=0; i<n; i++){
printf("%d",i);
for (int j=0; j<pile[i].size();j++) printf(" %d", pile[i][j]);
printf("\n");
}
}
int main(){
int a,b;
cin >> n;
string s1, s2;
for (int i = 0; i<n; i++) pile[i].push_back(i); //堆的初始化
while(cin >> s1 >> a >> s2 >> b){
// cin >> a;
// cout << a << endl;
int pa, pb, ha, hb;
find_block(a, pa, ha);
find_block(b, pb, hb);
if (pa ==pb) continue;
if (s2 == "onto") clear_above(pb, hb);
if (s1 == "move") clear_above(pa, ha);
pile_onto(pa, ha, pb);
//print();
}
print();
system("pause");
}
例题5-3 字典集合set
#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <sstream>
#include <stdlib.h>
using namespace std;
set<string> dict;
int main(){
string s, buf;
while(cin >> s){
for (int i = 0; i <s.length(); i++)
if (isalpha(s[i])) s[i]=tolower(s[i]); else s[i] = ' ';
stringstream ss(s);
while(ss >> buf) dict.insert(buf);
}
for (set<string>::iterator it = dict.begin(); it != dict.end(); ++it)
cout << *it << "\n";
system("pause");
}
第六章 数据结构基础
例题6-2 铁轨
#include <stdio.h>
#include <stack>
#include <stdlib.h>
using namespace std;
const int maxn = 100;
int n, target[maxn];
int main(){
while(scanf("%d",&n)==1){
stack<int> s;
int A = 1, B = 1;
for (int i=1; i<=n; i++){
scanf("%d", &target[i]);
}
//输入n节车厢,出栈顺序结果用target数组描述
int ok = 1;
while(B <= n){
// if(A == target[B])
// {
// A++;
// B++;
// }
//这段没有也可以运行,但是有会提高速度
if(!s.empty()&&s.top()==target[B])
{
s.pop();
B++;
}
else if(A <= n) s.push(A++);
else {ok = 0; break;}
}
printf("%s\n",ok?"Yes":"No");
}
system("pause");
}
例题6-3 矩阵链乘
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <string>
using namespace std;
/*
计算矩阵链乘表达式的乘法次数
如果乘法无法进行,输出error
矩阵名:A-Z 矩阵结构:axb
*/
//矩阵结构体,26是26个字母,对应矩阵A-Z
struct Matrix{
int a,b;
Matrix(int a=0, int b=0):a(a),b(b){}
}m[26];
stack<Matrix> s; //记录矩阵计算过程
int main(){
int n;
cin >> n; //有n组输入,即输入n个矩阵
for(int i = 0; i<n; i++){
string name;
cin >> name;
int k = name[0] - 'A';
cin >> m[k].a >> m[k].b;
}
for (int i =0; i<26; i++){
cout << "a" << m[i].a << "b" <<m[i].b << endl;
}
string expr;
while (cin >> expr){
int len = expr.length();
bool error = false;
int ans = 0;
for (int i = 0; i < len; i++){
if(isalpha(expr[i])) s.push(m[expr[i]-'A']);
else if(expr[i] == ')'){
Matrix m2 = s.top(); s.pop();
Matrix m1 = s.top(); s.pop();
if(m1.b != m2.a) { error = true; break; }
ans += m1.a * m1.b * m2.b;
s.push(Matrix(m1.a, m2.b));
}
}
if(error) printf("error\n"); else printf("%d\n", ans);
}
system("pause");
}