scanf的%c读取的是单个字符,是连续的,
如:scanf("%c%c",&ch1,&ch2),输入'ab'则接受'ab',但若输入'a b'则会接收'a '。
解决方案: scanf("%c %c",&ch1,&ch2),注意只是加了个空格

 

 

 

Num.2  switch语句的参数类型  (2021/8/6) 

 

switch语句的参数类型只能为int、char等,不能为实型(浮点数、实数等)或字符串!!!

 

 

 

Num.3  输入字符串(string)  (2021/8/6) 

 

1 scanf("%s %s",book[i].name,temptype);

 

运行时报错:

[Error] cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'

[Error] cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'

 

分析:

这里的book[i].name和temptype均为string类型。

语法:

  • const char *c_str();
  • c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同.
  • 为了与C兼容,在C中没有string类型,故必须通过string类对象的成员函数c_str()把string对象转换成C中的字符串样式。

解决方案:

在要打印的string后面加 .c_str()即可

 

更正后:

 

1 scanf("%s %s",book[i].name.c_str(),temptype.c_str());

 

 

然鹅,上面的分析都是错的!!!

虽然修改后编译可以通过,但运行结果仍然是错的-输入后根本没有为book[i].name和temptype赋值!

 

解决方案的解决方案:

 

1 cin>>book[i].name>>temptype;

 

总结:

输入字符串,千万不要用scanf!!!

用cin!!!

 

 

 

Num.4  字符串(string)赋值  (2021/8/6) 

 

 

1 string sort1[k+1]={0},sort2[k+1]={0};

 

运行时报错(编译已通过):

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
Aborted (core dumped)

分析:

我竟然给字符串赋值为0...

解决方案:

直接赋为空集。

更正后:

1 string sort1[k+1]={},sort2[k+1]={};

 

 

 

Num.5  C++精度修正问题  (2021/8/7) 

 

原题:求解一元二次方程

原代码:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 
 6 double a,b,c,x1,x2,delta;
 7 
 8 int main()
 9 {
10     cin>>a>>b>>c;
11     delta=b*b-4*a*c;
12     if(delta<0)cout<<"No answer!";
13     else if(delta>0) printf("x1=%.5lf;x2=%.5lf",min((-b-sqrt(delta))/(2*a),(-b+sqrt(delta))/(2*a)),max((-b-sqrt(delta))/(2*a),(-b+sqrt(delta))/(2*a)));
14     else printf("x1=x2=%.5lf",(-b)/(2*a));//x1+x2=-b/a,x1=x2时,x1=x2=-b/2a 
15     return 0;
16 }

 

测试信息:一个测试点WA了

 

分析:

C/C++中,浮点数的运算(和函数)有可能存在误差,
例如,在经过大量计算后,由于误差的影响,整数1变成了0.9999999999。
因此,浮点数只有完全一样才能使用==判断相等。

 

解决方案:

可以借助修正写法,fabs(a – b) < eps,可以自定义精度esp,esp一般取1e-8左右大小。

比如double类型的a和b,要判断a==b,在一定的精度范围内比较大小。

 

修正后:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #define eps1 1e-10//定义精度esp 10的-10次方
 5 #define eps2 1e-6//定义精度esp  10的-6次方
 6 using namespace std;
 7 
 8 double a,b,c,x1,x2,delta;
 9 
10 int main()
11 {
12     cin>>a>>b>>c;
13     delta=b*b-4*a*c;
14     if(delta<0&&abs(delta)>eps1)cout<<"No answer!";//(修正写法)
15     else if(abs(delta)<eps1)printf("x1=x2=%.5lf",(-b)/(2*a));//x1+x2=-b/a,x1=x2时,x1=x2=-b/2a   //(修正写法)
16     else
17     {
18         x1=(-b+sqrt(delta))/(2*a);
19         x2=(-b-sqrt(delta))/(2*a);
20         printf("x1=%.5lf;x2=%.5lf",min((-b-sqrt(delta))/(2*a),(-b+sqrt(delta))/(2*a)),max((-b-sqrt(delta))/(2*a),(-b+sqrt(delta))/(2*a)));
21     }
22     return 0;
23 }

 

总结:

细节决定成败!

 

 

 

Num.6  C++中的对数函数  (2021/8/9) 

 

知识点:

exp(x)----求e的x次方

log2(x)----返回以2为底数,以x为真数的对数的值

log10(x)----返回以10为底数,以x为真数的对数的值

 

注意:

C++没有自定义的对数函数!!!

就是说,无法提供loga(b)----以a为底数,以b为真数的对数!!!

但是,可以通过换底公式间接地来求。

代码如下:

 1 #include<iostream>
 2 #include<cmath>
 3 using namespace std;
 4 int main()
 5 {
 6     double a,b;//以a为底数,b为真数的对数函数
 7     cin>>a>>b;
 8     cout<<"loga(b)="<<log(b)/log(a)<<endl;//换底公式 
 9     return 0;
10 }

 

换底公式:

对于a,c∈(0,1)∪(1,+∞)且b∈(0,+∞),有

          Debug心得&笔记(持续更新)

推导过程:

若有对数 ax=b ,则

          x=logab  ---- ①

      Debug心得&笔记(持续更新)

因此,

      Debug心得&笔记(持续更新)

待会①式,得:

        Debug心得&笔记(持续更新)

证毕。

 

 

 

Num.7  floor/ceil取整问题  (2021/8/19) 

 

用floor/ceil取整时,得到的返回值是浮点数!!!

这就导致一些题不明不白就WA了...

解决方案: 强制类型转换,前面加个(int)或(long long)

 

 

 

Num.8  !右结合性问题  (2021/8/20) 

 

!右结合性非常强,用的时候一定不要忘了加括号!!!

运行结果错误:

 

1 while(!x%(int)pow(2,t)){t++;}

显然,这里的!与x结合到了一起,x是非0的数,!x就变成了0,这不是我们想要的结果。

 

更正后:

1 while(!(x%(int)pow(2,t))){t++;}

 

 

 

Num.9  数组&数据类型问题  (2021/8/29) 

 

数组不是基础数据类型,而是构造数据类型。

(基础数据类型有bool,char,int,float,double,void,wchar_t【宽字符型】)

注:

宽字符型wchar_t是这样来的:

 

1 typedef short int wchar_t;

 

所以 wchar_t 实际上的空间是和 short int 一样。

关于wchar_t,详见这篇博客

 

一些基本类型可以使用一个或多个类型修饰符进行修饰,如signed,unsigned,short和long。

 

关于typedef:

可以使用ta为一个已有的类型取一个新的名字。

e.g.

 

1 typedef long long ll;
2 ll a;  //声明变量

其实这就相当于

 

#define ll long long
ll a;

 

 

 

两者看上去很相似,但区别还是很大的,详见这篇文章那篇文章

 

回到正题。

正因为数组不是基础数据类型,所以在stack和queue中,像这样用就会报错:

 

 1 #include<iostream>
 2 #include<typeinfo>
 3 #include<cxxabi.h>
 4 #include<stack>
 5 #include<queue>
 6 
 7 using namespace std;
 8 
 9 template<typename type>
10 inline string type_of(type &x)
11 {
12     return abi::__cxa_demangle(typeid(x).name(),0,0,0);
13 }
14 
15 stack<char[200]>a;
16 queue<char[200]>b;
17 
18 signed main()
19 {
20     cout<<type_of(a)<<endl;
21     cout<<type_of(b)<<endl;
22     return 0;
23 }

 

Debug心得&笔记(持续更新)

 

 

 Debug心得&笔记(持续更新)

 

 

 

改成string就好了

 

 1 #include<iostream>
 2 #include<typeinfo>
 3 #include<cxxabi.h>
 4 #include<stack>
 5 #include<queue>
 6 
 7 using namespace std;
 8 
 9 template<typename type>
10 inline string type_of(type &x)
11 {
12     return abi::__cxa_demangle(typeid(x).name(),0,0,0);
13 }
14 
15 stack<string>a;
16 queue<string>b;
17 
18 signed main()
19 {
20     cout<<type_of(a)<<endl;
21     cout<<type_of(b)<<endl;
22     return 0;
23 }

 

Debug心得&笔记(持续更新)

 

 

 

 

不过玄学的是,用在vector好像就可以???

 

 1 #include<iostream>
 2 #include<typeinfo>
 3 #include<cxxabi.h>
 4 #include<vector>
 5 
 6 using namespace std;
 7 
 8 template<typename type>
 9 inline string type_of(type &x)
10 {
11     return abi::__cxa_demangle(typeid(x).name(),0,0,0);
12 }
13 
14 vector<char[200]>n;
15 
16 signed main()
17 {
18     cout<<type_of(n)<<endl;
19     return 0;
20 }

 

Debug心得&笔记(持续更新)

 

 

 

不知道什么原理。。。

但在实际用n数组的时候又会报错

Debug心得&笔记(持续更新)

 

 

 

 

如果改为vector<string>n就不会报错了,但这又是为什么?

求高手指教~

 

 

 

Num.10  关于static  (2021/9/1) 

 

听一个dalao说,static放快写里可以卡常(虽然他也不明白怎么回事)

然后我一听来精神了,一并将其写进了快读里……

第一天啥事没有,题目照常AC

但在第二天

我竟然被一个单调队列的黄题卡了一上午……

我百思不得其解,最后手动二分调试代码,才发现竟然是快读出问题了。。。

 

1 template<typename type>
2 inline void read(type &x)
3 {
4     x=0;static bool flag(0);char ch=getchar();
5     while(!isdigit(ch)) flag^=ch=='-',ch=getchar();
6     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
7     flag?x=-x:0;
8 }

 

第4行的flag是用来判断输入负号的,我顺手将其用static修饰,幻想它能卡一点常数,结果显然:

(听取WA声一片……)

这个快读读取正数是没有错误的,读取一个负数也可以,但读完一个负数继续正数就错了,后面的符号全变负

Debug心得&笔记(持续更新)

 

 

 

 

简单查了下static的用法,很快就找到了答案。

修饰局部变量时,表明该变量的值不会因为函数终止而丢失

 

显然,若读进的第一个数为负,则flag就变为1

快读结束时,flag由于static的作用,不会像普通变量一样退出函数就被销毁

因此再读第二个数时,已经存在的flag就不会被新的声明影响,仍保持1的值,所以同样会读成负数。。。

 

解决方案:

将static去掉就可以啦。

 

那么对于快写:

 

1 template<typename type>
2 inline void write(type x,bool mode)
3 {
4     x<0?x=-x,putchar('-'):0;static short Stack[50],top(0);
5     do Stack[++top]=x%10,x/=10; while(x);
6     while(top) putchar(Stack[top--]|48);
7     mode?puts(""):putchar(' ');
8 }

 

 

为什么这里用static就没事呢?

很简单,因为对于每次快写的调用,都能保证栈空和top为0,重复声明、赋值与否,都不会对结果造成影响。

这时,用static关键字就可以跳过无用的二次声明、赋值阶段,从而节省运行时间。

 

总结:

对于很多陌生的关键字,

不要乱用!

不要乱用!!

不要乱用!!!

 

相关文章: