本专栏主要基于北大郭炜老师的程序设计与算法系列课程进行整理,包括课程笔记和OJ作业。该系列课程有三部分: (一) C语言程序设计;(二) 算法基础;(三) C++面向对象程序设计
(一) C语言程序设计 课程链接
在printf和scanf中可以使用以"%"开头的控制符,指明要输入或输出的数据的类型以及格式。
int n = 3;
printf("I want to buy %d books for %f dollars",3,4.5); //也可以用%lf
double f;
scanf("%d%f",&n,&f); //也可以用%lf
用scanf可以一次读入多个类型不同的变量,只要输入的各项之间用空格分隔即可。
#include
#include
using namespace std;
int main()
{
int n; char c; float f;
scanf("%d%c%f",&n,&c,&f); //依次输入一个整数,一个字符, 再一个小数,则它们会被分别放入n,c,m; &n代表“取n的地址” ; %c表示等待输入一个字符;%f表示等待输入一个float小数
printf("%d %c %f",n,c,f); //%f用于输出double或float类型的值,默认保留小数点后面6位
return 0;
}
输入字符类型数据时(%c),不会跳过空格(空格也会被当作字符读入),输入其他类型的数据时,会跳过空格。
#include
#include
using namespace std;
int main()
{
int n; char c; float f;
scanf("%d%c%f",&n,&c,&f);
printf("%d %c %f",n,c,f);
return 0;
}
%c不会跳过空格,此时他会读入一个空格到c中,再读入f时,对应输入是’k’,导致出错。
如果在输入中有scanf中出现的非控制字符(可以自行设置格式字符串),则这些字符会被跳过。
#include
#include
using namespace std;
int main()
{
int n,m; char c; float f;
scanf("%d %c,%f:%d",&n,&c,&f,&m); //输入中对应位置的 空格 , :会被跳过
printf("%d,%c,%f,%d",n,c,f,m);
return 0;
}
int n = 123;
printf("%05d,%5d,%5d,%05d",n,n,123456,123456);
float a = 123.45;
double b = 22.37362723;
printf("%.5f %.2f %.12f",12.3,a,b);
printf("%x,%d,%u",0xffffffff, 0xffffffff,0xffffffff);
int n;
scanf("%x",&n); //读入一个十六进制数
printf("%d",n); //输出对应的十进制数
#include
using namespace std;
int main()
{
int n=5;
double f = 3.9;
char c = 'a';
cout << "n=" << n << ",f=" << f << endl; //endl换行
cout << 123 << ", c=" << c;
return 0;
}
#include
using namespace std;
int main()
{
int n1,n2;
double f;
char c;
cin >> n1 >> n2 >> c >> f;
cout << n1 << "," << n2 << "," << c << "," << f;
return 0;
}
cin会跳过空格,对于所有的类型包括字符类型,此时在输入的10,k之间加一个空格的话,该空格会被跳过,字符类型变量c读入的仍是k。
#include
using namespace std;
int main()
{
int c;
while((c = cin.get()) != EOF) {
cout << (char)c ;
}
return 0;
}
cin.get()会读入所有输入字符,不会跳过空格和回车等。他的返回值是int,即读入字符的ASCII码,由于字符是一个字节,而int是4个字节,因此返回的int类型值始终>=0(最高位/符号位是0)。当读取完毕(没有数据可读时),返回EOF(-1),注意EOF不是输入数据结束的标志,输入数据结尾没有这个符号。 由于返回的是ASCII码,输出时需要用(char)c转换为字符。
#include
#include
using namespace std;
int main()
{
char c;
while(scanf("%c",&c) != EOF) {
printf("%c",c);
}
return 0;
}
由于scanf中的字符类型%c,在输入时,不会跳过空格,因此可以读入所有输入的字符,包括空格,回车。没有数据可读时,返回EOF。
赋值运算符用于给变量赋值,常用有以下六种:=、+=、 -=、 *=、 /=、 %=
int a;
a = 1; // a的值变为1
a = a + 1; // a的值变为2
a = 4 + a; // a的值变为6
a += b ;//等效于 a = a + b,但是执行速度更快
-=, *= ,/= ,%= 用法与+=类似; 表达式 x = y 的值,就是y的值
七种算术运算符用于数值运算 运算符+操作数构成表达式:
加+、减-、 乘* 、除/ 、求余数 % 、自增 ++ 、自减 –
加、减、乘运算符
a+b、a-b、a*b这三个表达式的值,就是操作数a和b做算术运算的结果 。表达式的值的类型,以操作数中精度高的类型为准。
精度:
加、减、乘运算的溢出
1)两个整数类型进行加、减、乘都可能导致计算结果超出了结果类型所能表示的范围,这种情况就叫做溢出。
2)计算结果的溢出部分直接被丢弃。
3)实数(浮点数)运算也可能溢出,结果不易预测。
#include
using namespace std;
int main()
{
unsigned int n1 = 0xffffffff;
cout << n1 << endl; //输出4294967295,无符号int最大表示结果
unsigned int n2 = n1 + 3; //导致溢出
cout << n2 << endl; //输出2 0xffffffff + 3 的结果,应该是 0x100000002,9个十六进制位,超出的一位十六进制位直接丢弃,结果就是0x00000002=2
return 0;
}
4)有时计算的最终结果似乎不会溢出,但中间结果可能溢出,这也会导致程序出错,例如:(a+b)/2 未必等于 a/2+b/2:
printf("%d",(2147483646 + 6)/2); //2147483646是int最大能表示的数字 先加6中间结果会溢出 导致最终结果出错 -1073741822
printf("%d",2147483646/2 + 6/2); // 如果先除以2,中间结果不会溢出,最终结果是正确的 1073741826
5)解决溢出的办法是尽量使用更高精度的数据类型(两个int进行运算会溢出, 用两个 long long 进行运算可能就不会溢出)。如果是几百位的数,就涉及到高精度计算,此时需要用到数组。
int main()
{
int a = 10;
int b = 3;
double d = a/b; // a/b 的值也是整型,其值是3
cout << d << endl; //输出 3
d = 5/2; //d的值变为2.0
cout << d << endl; //输出 2
d = 5/2.0; //结果是操作数中精度较高的那一个 即double
cout << d << endl; //输出 2.5
d = (double)a/b; //为得到更精确的值 可以把操作数强制转换为double
cout << d << endl; //输出 3.33333
return 0;
}
求余数的运算符“%”也称为模运算符。它是双目运算符,两个操作数都是整数类型的。a % b 的值就是a除以b的余数。
除法运算和模运算的除数都不能为0,否则程序会崩溃!!!
#include
using namespace std;
int main()
{
int n1, n2=5;
n2 ++; // n2变成6
++n2; //n2变成7
n1 = n2 ++; // n2变成8,n1变成7
cout << n1 << "," << n2 << endl; //输出 7,8
n1 = ++ n2; //n1和n2都变成9
cout << n1 << "," << n1 << endl; //输出 9,9
return 0;
}
单目运算符 “-”,用于取整型或实数型变量的值的相反数:
int a = 4;
int b = -a;
int c = -5*3;
int n = true,m = false;
printf("%d,%d",n,m); // 1,0
int main()
{
int n1 = 4, n2 = 5,n3;
n3 = ( n1 > n2 ); // n3 的值变为 0 ()可以使表达式关系更清晰 可以不加;
cout<<n3<<","; //输出0,
n3 = ( n1 < n2); // n3 的值变为非0值
cout << n3 << ","; // 输出 1,
n3 = (n1 == 4); // n3 的值变为非 0 值
cout << n3 << ","; // 输出 1,
n3 = (n1 != 4); // n3 的值变为0
cout << n3 << ","; // 输出 0,
n3 = (n1 == 5);// n3 的值变为0
cout << n3 ; // 输出 0,
return 0;
}
逻辑运算符用于表达式的逻辑操作,有 &&, || , ! 三种, 操作的结果是true或false。
表达式由操作数和运算符(关系运算符、算术运算符等)组成
int n = 4;
n > 4 && n < 5 //false
n >= 2 && n < 5 //true
5 && 0 //false C++中非0整数为真,0为假
4 && 1 //true
int n = 4;
n > 4 || n < 5 // true
n <= 2 || n > 5 //false
!(4 < 5 ) // false
!5 //false
!0 // true
逻辑表达式是短路计算的,即对逻辑表达式的计算,在整个表达式的值已经能够断定的时候即会停止。
#include
using namespace std;
int main()
{
int a = 0,b = 1;
bool n= (a++)&&(b++); //b++不被计算
cout << a << "," << b << endl; //输出 1,1
n= a++&&b++; //a++和b++都要计算
cout << a << "," << b << endl; //输出 2,2
n = a ++ || b ++ ; //b++不被计算
cout << a << "," << b << endl; //输出 3,2
return 0;
}
double f = 9.14;
int n = (int) f; //n=9
f = n / 2; //f=4.0
f = double(n) / 2; //f=4.5
printf("%d,%d",a+++b,a); //a+++b 等价于(a++)+b