这是我在csdn的第一篇文章,以后就在此记录代码生活orz(本人是新手)
太 长 不 看 版
#强调#
-
一定要注意逻辑思考,别一上来就敲代码,脑子跟着bug出现跑,程序只为消除bug服务,最后通过测试,但你不清楚为啥是这样敲,耗时耗力收效甚微
-
可视化 :将重要步骤的最好在窗口中输出(如cout语句),方便debug,并且给你的代码添加注释,增加可读性
-
多测几个数字
意外收获:将除法化为乘法避免取整减少一些信息
以下是新版正文(2023.12.15更新)
代码题目要求:正确地找到字符串a和字符串b的公共子序列并输出结果,并输出最长子串长度。
测试输入:
123456789
234125679
错误代码如下
#include<iostream>
#include<cstring>
using namespace std ;
int main (){
string a ;
string b ;
cin >> a >> b ;
int L1= b.size ();
int maxlen =0;
for (int i=0;i<L1;i++)
{
for ( int j=L1-1; j>i+1; j--){
if (( a.find(b.substr(i,j)))!=string::npos){
maxlen = max(j-i+1, maxlen);
cout<< b.substr(i,j)<< endl ;
}
}
}
cout<<maxlen;
return 0;
}
如何修改呢?
1.加注释(弄清楚每一步干什么) 2.程序每一步执行可视化(添加cout语句)
以下为添加注释和cout语句的代码
就可以很清楚的看到运行结果
分析问题:根据例子给出自己的答案与程序对照。
而我们自行判断出现234结果的情况是i=0,j=2;出现567的情况是i=5,j=7。但是可以看到与程序执行结果不同?哪里出现问题了?只能是strcat函数的理解!使用函数一定要知道各参数的含义。
我们误以为是substr(i,j),是字符串从i到j,实际上,该函数要求从指定位置开始,并具有指定的长度。所以substr(i,j)的意思是从i开始,长度为j的字符串
以下是修改完成的代码(记得把辅助的cout语句注释掉噢~):
#include<iostream>
#include<cstring>
using namespace std;
int main() {
string a;
string b;
cin >> a >> b;//读入字符串
int L1 = b.size();//计算b的长度
int maxlen = 0;//最长子串长度
for (int i = 0; i < L1; i++) {
// cout<<"当i="<<i<<endl;
for (int j = L1-i; j>=1; j--) {
// cout<<"当j="<<j<<",输出为"<<endl;
//find函数在找不到指定值得情况下会返回string::npos,当不是string::npos的情况下执行
if ((a.find(b.substr(i, j))) != string::npos) {
maxlen = max(j, maxlen);//更新最长子串长度
cout << b.substr(i, j) << endl;//输出相同子串
}
}
}
cout << maxlen;//输出最长子串长度
return 0;
}
看看运行结果,nice!
标准输出:
234
23
2
34
3
4
12
1
2
567
56
5
67
6
7
9
3
以下是旧版正文(不用看)
以一道题为例谈谈最近的收获吧(虽然没有ac)
洛谷P1980
以下是我的代码(有错误,不用看)
#include<iostream>
#include<cmath>
using namespace std;
int main() {
int n,x,sum = 0;
cin >> n >> x;
for (int i = 1; i < n + 1; i++) {
int j = 0;
for (; j < 6; j++) {
int a = i % 10;
if (floor(i * 1.0 / (x * pow(10, j))) == 1) {
++sum;
}
}
if (i > 10) {
int a = i % 10;
if (a / x == 1) {
sum++;
}
}
}
cout << sum;
return 0;
}
你会发现你很难理解这代码是干嘛的,而且只有最后一个输出结果,debug无从下手,这时候可视化和注释的作用就发挥出来了,以下是新代码(修改过,还是不能ac)
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
int main() {
int n, x, sum = 0;
cin >> n >> x;
//对n个数进行判断
for (int i = 1; i <= n; i++) {
//因为最大不超过10的6次方
for (int j = 1; j <5 ; j++) {
//只执行一次,判断个位数上时候存在x
if (j == 1) {
if ((i % 10) / x == 1) {
//多添加的cout语句
cout << "i=" << i << " 的个位数成立" << endl;
sum++;
}
}
//判断其余位数上是否有x
if(j!=0) {
int a = n / (x * pow(10, j));
if (a== 1) {
//多添加的cout语句
cout << "i=" << i << " 10的" << j << "次方" << endl;
sum++; }
}
}
}
cout << sum;
system("pause");
return 0;
}
你会发现有些多添加的cout语句,让步骤可视化,还有一些注释,增强代码可读性
运行一下 发现非常清晰
多测试几个数字
如 12 2
审视我的代码
判断个位数时
if ((i % 10) / x == 1)
当i=3 x=2时 ,(3%10)/2 ,由于是整型运算,结果得到1,满足条件
修改方法 i%10==x
将除法化为乘法避免取整减少一些信息
再测120 0
这是因为我忘记考虑0的情况了 0的n次方都是0(n>0)
那我们就考虑10来代替0,再加代码
//判断其余位数上是否有x
if (x != 0) {
int a = i / (x * pow(10, j));
if (a == 1) {
cout << "i=" << i << " 10的" << j << "次方" << endl;
sum++;
}
}
else {
int a = i / pow(10, j);
if (a!=0&&a %10== 0) {
cout << "i=" << i << " 从右向左第" << j+1 << "位" << endl;
sum++;
}
再跑 : 520 1
跑出bug
再改,再测,直到ac
注:以上代码并未通过题目
只是为了证明步骤可视化对修改bug的好处,希望大家能有所收获