篇一:C语言位运算符:与、或、异或、取反、左移和右移
C语言位运算符:与、或、异或、取反、左移和右移
语言位运算符:与、或、异或、取反、左移和右移
位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型。
C语言提供的位运算符列表:
运算符 含义 描述
& 按位与 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0 | 按位或 两个相应的二进制位中只要有一个为1,该位的结果值为1 ^ 按位异或 若参加运算的两个二进制位值相同则为0,否则为1
~ 取反 ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0 << 左移 用来将一个数的各二进制位全部左移N位,右补0
>> 右移 将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0
1、“按位与”运算符(&)
按位与是指:参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。这里的1可以理解为逻辑中的true,0可以理解为逻辑中的false。按位与其实与逻辑上“与”的运算规则一致。逻辑上的“与”,要求运算数全真,结果才为真。若,A=true,B=true,则A∩B=true 例如:3&5 3的二进制编码是11(2)。(为了区分十进制和其他进制,本文规定,凡是非十进制的数据均在数据后面加上括号,括号中注明其进制,二进制则标记为2)内存储存数据的基本单位是字节(Byte),一个字节由8个位(bit)所组成。位是用以描述电脑数据量的最小单位。二进制系统中,每个0或1就是一个位。将11(2)补足成一个字节,则是00000011(2)。5的二进制编码是101(2),将其补足成一个字节,则是00000101(2)
按位与运算:
00000011(2)
&00000101(2)
00000001(2)
由此可知3&5=1
c语言代码:
#include <stdio.h>
main()
{
int a=3;
int b = 5;
printf("%d",a&b);
}
按位与的用途:
(1)清零
若想对一个存储单元清零,即使其全部二进制位为0,只要找一个二进制数,其中各个位符合一下条件:
原来的数中为1的位,新数中相应位为0。然后使二者进行&运算,即可达到清零目的。
例:原数为43,即00101011(2),另找一个数,设它为148,即10010100
(2),将两者按位与运算:
00101011(2)
&10010100(2)
00000000(2)
c语言源代码:
#include <stdio.h>
main()
{
int a=43;
int b = 148;
printf("%d",a&b);
}
(2)取一个数中某些指定位
若有一个整数a(2byte),想要取其中的低字节,只需要将a与8个1按位与即可。 a 00101100 10101100
b 00000000 11111111
c 00000000 10101100
(3)保留指定位:
与一个数进行“按位与”运算,此数在该位取1.
例如:有一数84,即01010100(2),想把其中从左边算起的第3,4,5,7,8位保留下来,运算如下:
01010100(2)
&00111011(2)
00010000(2)
即:a=84,b=59
c=a&b=16
c语言源代码:
#include <stdio.h>
main()
{
int a=84;
int b = 59;
printf("%d",a&b);
}
2、“按位或”运算符(|)
两个相应的二进制位中只要有一个为1,该位的结果值为1。借用逻辑学中或运算的话来说就是,一真为真
。
例如:60(8)|17(8),将八进制60与八进制17进行按位或运算。
00110000
|00001111
00111111
c语言源代码:
#include <stdio.h>
main()
{
int a=060;
int b = 017;
printf("%d",a|b);
}
应用:按位或运算常用来对一个数据的某些位定值为1。例如:如果想使一个数a的低4位改为1,则只需要将a与17(8)进行按位或运算即可。
3、交换两个值,不用临时变量
例如:a=3,即11(2);b=4,即100(2)。
想将a和b的值互换,可以用以下赋值语句实现:
a=a∧b;
b=b∧a;
a=a∧b;
a=011(2)
(∧)b=100(2)
a=111(2)(a∧b的结果,a已变成7)
(∧)b=100(2)
b=011(2)(b∧a的结果,b已变成3)
(∧)a=111(2)
a=100(2)(a∧b的结果,a已变成4)
等效于以下两步:
① 执行前两个赋值语句:“a=a∧b;”和“b=b∧a;”相当于b=b∧(a∧b)。 ② 再执行第三个赋值语句: a=a∧b。由于a的值等于(a∧b),b的值等于(b∧a∧b),
因此,相当于a=a∧b∧b∧a∧b,即a的值等于a∧a∧b∧b∧b,等于b。 很神奇吧!
c语言源代码:
#include <stdio.h>
main()
{
int a=3;
int b = 4;
a=a^b;
b=b^a;
a=a^b;
printf("a=%d b=%d",a,b);
}
4、“取反”运算符(~)
他是一元运算符,用于求整数的二进制反码,即分别将操作数各二进制位上的1变为0,0变为1。
例如:~77(8)
源代码:
#include <stdio.h>
main()
{
int a=077;
printf("%d",~a);
}
篇二:C语言中extern的用法
C语言中extern的用法
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
1. extern修饰变量的声明。举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。
2. extern修饰函数声明。从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。
3. 此外,extern修饰符可用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。
用C语言编写程序的时候,我们经常会遇到这样一种情况:希望在头文件中定义一个全局变量,然后包含到两个不同的c文件中,希望这个全局变量能在两个文件中共用。
举例说明:项目文件夹project下有main.c、common.c和common.h三个文件,其中
common.h文件分别#include在main.c和common.c文件中。现在希望声明一个字符型变量key,在main.c和common.c中公用。如下图所示:
有人想,既然是想两个文件都用,那就在common.h中声明一个unsigned char key,然后由于包含关系,在main.c和common.c中都是可见的,所以就能共用了。
这种想法其实是很多初学者都会想到的,想起来确实有道理,但是实际写出来,我们发现编译的时候编译器提示出错,一般提示大概都类似于:Error: L6200E: Symbol key multiply defined (by common.o and main.o). 也就是说编译器认为我们重复定义了key这个变量。这是因为#include命令就是原封不同的把头文件中的内容搬到#include的位置,所以相当于main.c和common.c中都执行了一次unsigned char key,而C语言中全局变量是项目内(或者叫工程内)可见的,这样就造成了一个项目中两个变量key,编译器就认为是重复定义。
正确的解决办法:使用extern关键字来声明变量为外部变量。具体说就是在其中一个c文件中定义一个全局变量key,然后在另一个要使用key这个变量的c文件中使用extern关键字声明一次,说明这个变量为外部变量,是在其他的c文件中定义的全局变量。请注意我这里的用词:定义和声明。例如在main.c文件中定义变量key,在common.c文件中声明key变量为外部变量,这样这两个文件中就能共享这个变量key了,如下图所示。
代码如下(只写跟我们所说问题有关的部分):
(1)main.c文件
#include "common.h"
unsigned char key;
(2)common.c文件:
#include "common.h"
extern unsigned char key;
很多人看了可能糊涂,这里稍微说一下,其实就是变量定义和变量声明的区别,变量定义使用“数据类型+变量名称”的形式,编译器需要给他分配内存单元的;而变量声明使用“extern 变量类型+变量名称”
的形式,是告诉编译器我这个变量将在其他外部c文件中定义,我这里只是在外部用它。编译器就不给他分配内存空间,而等到真正遇到变量定义的时候再给他分配内存空间。
由于很多人从开始学C语言就一直把定义变量叫声明变量,一开始就叫错了,所以导致现在分不清定义和声明的区别。要是还理解不了就想想函数的定义和声明,函数定义是编写函数功能实体,编译器要编译这个函数并且要分配内存空间,而函数声明并不生成函数功能实体,只是告诉编译器这是个函数,这个函数在后面将会定义实体,我这里只是提前用,编译器就会接着继续往下编译,如果子函数写在main函数之后,那么声明是必须的,如果不声明函数编译器都不知道这是个函数,编译就会报错。
篇三:北京理工大学2013级C程序设计非信息类答案part2
北京理工大学2013级C程序设计非信息类答案part 2
49. 【小学递归】杀鸡用牛刀——要用递归啊! 成绩
5
开启时间
2014年05月10日 星期六 14:00
折扣 0.8 折扣时间 2014年05月24日 星期六 23:55
允许迟交 否 关闭时间 2014年06月1日 星期日 23:55
背景: 哈哈!我们终于学了递归了,现在大家一定感到非常有意思吧,那个典型的―汉诺塔‖问题,一个非常短的程序居然可以完成如此复杂的工作,真是神奇啊!来吧,让我们也动手编写一个递归程序,当然,我们要编写的不可能太复杂。 功能: 求整数 n 到 m 区间的累加和,其中n<=m。输入: 区间的起始点n区间的终止点m 输出: 累加和 要求: 使用递归算法完成。如此简单的题目当然要有隐含的测试用例啦,就3个,看看谁能猜出来。
测试输入
期待的输出
时间限制
内存限制
额外进程
测试用例 1 1. 1 10? 1. The sum from 1 to 10 is 55.? 1秒 64M 0
测试用例 2 1. 2. 3. 4. 5.
1. 10 15? 1. The sum from 10 to 15 is 75.? 1秒 64M 0
int sum(int m,int n)
{if(m==n) return m;int i;for(i=n;i>=m;i--) return i+sum(m,i-1);}#include <stdio.h>
int main(){int m,n,s=0;scanf("%d%d",&m,&n);s=sum(m,n); printf("The sum from %d to %d is %d.\n",m,n,s);return 0;}
50. 【中学】求最大公约数——递归 成绩
5
开启时间
2014年05月10日 星期六 14:00
折扣 0.8 折扣时间 2014年05月24日 星期六 23:55
允许迟交 否 关闭时间 2014年06月1日 星期日 23:55
请使用递归算法计算正整数n和m的最大公约数GCD(n,m)。 = m 当 m<=n 且 n mod m =0 GCD(N,M) = GCD(m,n)当n<m时 = GCD(m, n mod m) 其他
输入: n和m输出: n和m的最大公约数
测试输入 期待的输出 时间限制 内存限制 额外进程
测试用例 1 1. 24 48? 1. 24? 1秒 64M 0
测试用例 2 1. 2. 3. 4. 5. 6. 7. 8.
1. 13 15? 1. 1? 1秒 64M 0
#include <stdio.h> int f(int x,int y) {int s,t;t=x%y;
if(t==0) s=y;else s=f(y,t); return s;} int main()
{int m,n;scanf("%d%d",&m,&n); printf("%d\n",f(m,n));return 0;}
51. 【数列递归】求序列之和——递归 成绩
5
开启时间
2014年05月10日 星期六 14:00
折扣 0.8 折扣时间 2014年05月24日 星期六 23:55
允许迟交 否 关闭时间 2014年06月1日 星期日 23:55
请使用递归算法求序列1 + 1/2 - 1/3 + 1/4 -1/5 ......的前n项之和。 输入:n 输出:序列的前n项和(精确到小数点之后第6位)
测试输入
期待的输出
时间限制
内存限制
额外进程
测试用例 1 1. 1? 1. 1? 1秒 64M 0
测试用例 2 1. 2? 1. 1.500000? 1秒 64M 0
测试用例 3 1. 2. 3. 4. 5. 6. 7. 8.
1. 3? 1. 1.166667? 1秒 64M 0
#include<stdio.h> float sum(int n)
{float s;if(n==1) s=1.0;
else if(n%2==0) s=sum(n-1)+1.0/n; else s=sum(n-1)-1.0/n;return s;} int main()
{int n;float s;scanf("%d",&n); if(n==1) printf("1\n");
9. else {s=sum(n);printf("%.6f\n",s);}}
52. 【大学】函数递归* 成绩
5
开启时间
2014年05月10日 星期六 14:00
折扣 0.8 折扣时间 2014年05月24日 星期六 23:55
允许迟交 否 关闭时间 2014年06月1日 星期日 23:55
编写一个函数,使用递归算法求满足下述定义的整数序列的第n项。 f( n ) =
1
f(n-1) + f(n-3) f(n-2) + f(n-4) -1
当 n >= 0 且 n <= 4 时 当 n > 4 且n为偶数 时 当 n > 4 且n为奇数 时 其他
函数原型如下:int findf(int n);参数说明:n 项数;返回值是第n项值。例如输入:10,输出:8
预设代码 前置代码 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
/* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */ #include <stdio.h> int main()
{ int n,s, findf( int ); scanf("%d", &n); s = findf(n);
printf("%d\n", s); return 0; }
/* PRESET CODE END - NEVER TOUCH CODE ABOVE */
测试输入
期待的输出
时间限制
内存限制
额外进程
测试用例 1 1. 2. 3. 4.
1. 10? 1. 8? 1秒 64M 0
int findf(int n)
{if(n>=0&&n<=4) return 1;if(n<0) return -1; if(n>4&&n%2==0) return findf(n-1)+findf(n-3); if(n>4&&n%2==1) return findf(n-2)+findf(n-4);}
53.【大学递归】求解平方根
成绩 5 开启时间 2014年05月10日 星期六 11:35
折扣 0.8 折扣时间 2014年05月24日 星期六 11:35
允许迟交 否 关闭时间 2014年06月1日 星期日 11:35
?p,p2?x?e??
小明上了大学,学习了用求解平方根的迭代公式。Sqrt?x,p,e??? ?1?x??2
?sqrt?x,?p??,e?,p?x?e
p????2??
其中:p 为 x 的近似平方根,e 是结果允许的误差。 输入:x, e 输出:p 保留小数点后 8 位。
1.
2. 3. 4. 5.
#include<stdio.h> #include<math.h>
float f(float x,float p,float e)
{if(fabs(p*p-x)<e) return p; else return f(x,(p+x/p)/2,e);}
int main() {float p,e,x;scanf("%f%f",&x,&e); p=f(x,x,e);printf("%.8f\n",p);return 0;}
H12:安全的密码(选做) 成绩
5
开启时间
2014年05月10日 星期六 14:00
折扣 0.8 折扣时间 2014年05月24日 星期六 23:55
允许迟交 否 关闭时间 2014年06月1日 星期日 23:55
随着电子设备的广泛运用,密码也渐渐融入每个人的生活。保护好密码,不仅关系到个人隐私,更关系到个人的财产和安全。一个安全的密码,最好由大小写字母、数字或符号组成。包含越多种类的字符,其安全性就越高。同时密码还需要有一定的长度,通常至少要由六个以上的字符组成。
并不是每个人都喜欢这样复杂的密码,很多人在设置密码的时候,喜欢使用自己的名字或者生日,但这是很大的安全隐患。
任务 林晓炜正在设计一个网络交易系统,为了保证用户的密码安全,他需要一个程序,判断用户自己设置的密码是否安全,如果不安全,则给出提示。现在他向你求助,请你帮忙设计一个程序来解决这个问题。
应当按照以下的规则来判断密码是否安全:如果密码长度小于 6 位,则不安全;如果组成密码的字符只有一类,则不安全;如果组成密码的字符有两类,则为中度安全;如果组成密码的字符有三类或以上,则为安全 通常,可以认为数字、大写字母、小写字母和其它符号为四类不同的字符。
输入 输入的第一行是一个整数 N,表明后面有多少组密码。随后的 N 行输入包括 N 个密码,每个密码的长度均小于 20 个字符。
输出 针对每一个密码判断并输出它是否安全。对于不安全的密码输出 "Not Safe",对于中度安全的密码输出 "Medium Safe",对于安全的密码输出 "Safe" 输入样例
输出样例
测试输入
期待的输出
时间限制
内存限制
额外进程
测试用例 1 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
10?
abcDEF? ABC? qw? `?
ABCDEFGHIJKLMNOPQRST? 12345678901234567890? 1aB? 1 B? a X?
qwe123%^&ABC?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Medium Safe? Not Safe? Not Safe? Not Safe? Not Safe? Not Safe? Safe? Not Safe? Safe? Safe?
1秒 64M 0
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. #include <stdio.h>#include <string.h> int main(void)
{int n,i,j,x,m,b[4];char a[100];scanf("%d",&n);
for (i=1;i<=n;i++){gets(a);if (i==1) gets(a);x=strlen(a); if (x<6) {printf("Not Safe\n");continue;}
b[0]=0;b[1]=0;b[2]=0;b[3]=0;for (j=0;j<=x-1;j++) {if (48<=a[j]&&a[j]<=57) b[0]=1; else if (65<=a[j]&&a[j]<=91) b[1]=1; else if (97<=a[j]&&a[j]<=123) b[2]=1; else b[3]=1;
if (a[0]+a[1]+a[2]+a[3]==4) break;}m=b[0]+b[1]+b[2]+b[3]; switch (m)
{case 1:printf("Not Safe\n");break;case 2:printf("Medium Safe\n");break;
《c》
由:创业小项目互联网用户整理提供,链接地址:
http://m.csmayi.cn/duwu/4514.html
转载请保留,谢谢!
- 上一篇:小学依法治校总结
- 下一篇:感动中国张丽莉