求一个整型变量二进制数中含有1的数目(经典)

本文介绍了一种使用C++位运算来计算整数中1的个数的方法。相较于传统循环计数方式,该方法更加高效简洁。通过不断将数字与其减一后的结果进行按位与操作直至为0,来实现快速计数。

//:(C++代码)

//:一般方法是利用循环计数,但每次都要32次(32位机),效率不是很高

#include<iostream>

using namespace std;

int main()

{

       int a;

       cin>>a;

       int count=0;

       while( a )

       {

            a&=a-1;

            ++count;

        }

       cout<<count<<endl;

}

///:~

简洁明了,比较精妙,自己多琢磨琢磨~

实验一 词法分析程序设计与实现 一、实验目的 通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进 行扫描的过程中,将字符流形式的源程序转化为一个由各类单词构成的序列 的词法分析方法。 二、基本实验内容与要 假定一种高级程序设计语言中的单词主要包括关键字 begin、end、if、then、 else、while、do;标识符;浮点常数;六种关系运算符;一个赋值符和四个 算术运算符,试构造能识别这些单词的词法分析程序(各类单词的分类码可 参见表 1)。 输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序 文件。 输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形 式输出,并将结果放到某个文件中。对于标识符和浮点常数,CLASS 字段为 相应的类别码的助记符;VALUE 字段则是该标识符、常数的具体值;对于关 键字和运算符,采用一词一类的编码形式,仅需在二元式的 CLASS 字段上 放置相应单词的类别码的助记符,VALUE 字段则为“空”。 表 1 语言中的各类单词符号及其分类码表 单词符号 类别编码 类别码的助记符 单词值 begin 1 BEGIN end 2 END if 3 IF then 4 THEN else 5 ELSE while 6 WHILE do 7 DO 标识符 8 ID 字母打头的字母数字串 浮点常数 9 UCON 机内二进制表示 < 10 LT <= 11 LE == 12 EQ <> 13 NE > 14 GT >= 15 GE = 16 IS + 17 PL - 18 MI * 19 MU / 20 DI 要1、上机前完成词法分析程序的程序流程设计,并选择好相应的数据结构。 2、用于测试扫描器的实例源文件中至少应包含两行以上的源代码。 3、对于输入的测试用例的源程序文件,词法正确的单词分析结果在输出 文件中以二元式形式输出,错误的字符串给出错误提示信息。 例如,若输入文件中的内容为:“if myid>=1.5 then x=y”,则输出文件 中的内容应为: (IF, ) (ID,’myid’) (GE, ) (UCON,1.5) (THEN, ) (ID,’x’) (IS, ) (ID,’y’) 三、参考实现方法 1、一般实现方法说明 词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法 分析程序。其一是根据对语言中各类单词的某种描述或定义(如 BNF),用手 工的方式(例如可用 C 语言)构造词法分析程序。一般地,可以根据文法或 状态转换图构造相应的状态矩阵,该状态矩阵连同控制程序一起便组成了编 译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。 构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首 先用正规式对语言中的各类单词符号进行词描述,并分别指出在识别单词 时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序 的构造程序对上述信息进行加工。如美国 BELL 实验室研制的 LEX 就是一个被 广泛使用的词法分析程序的自动生成工具。总的来说,开发一种新语言时, 由于它的单词符号在不停地修改,采用 LEX 等工具生成的词法分析程序比较 易于修改和维护。一旦一种语言确定了,则采用手工编写词法分析程序效率 更高。本实验建议使用手工编写的方法。 在一个程序设计语言中,一般都含有若干类单词符号,为此可首先为每 类单词建立一张状态转换图,然后将这些状态转换图合并成一张统一的状态 图,即得到了一个有限自动机,再进行必要的确定化和状态数最小化处理, 最后添加当进行状态转移时所需执行的语义动作,就可以据此构造词法分析 程序了。 2、单词分类与词法分析器的设计 为了使词法分析程序结构比较清晰,且尽量避免某些枝节问题的纠缠, 我们假定要编译的语言中,全部关键字都是保留字,程序员不得将它们作为 源程序中的标识符;在源程序的输入文本中,关键字、标识符、浮点常数之 间,若未出现关系和算术运算符以及赋值符,则至少须用一个空白字符加以 分隔。作了这些限制以后,就可以把关键字和标识符的识别统一进行处理。 即每当开始识别一个单词时,若扫视到的第一个字符为字母,则把后续输入 的字母或数字字符依次进行拼接,直至扫视到非字母、数字字符为止,以期 获得一个尽可能长的字母数字字符串,然后以此字符串查所谓保留字表(此 保留字表要事先造好),若查到此字符串,则取出相应的类别码;反之,则表 明该字符串应为一标识符。 采用上述策略后,针对表 1 中的部分单词可以参考图 1 和程序 1,用 C 语言编写出符合以上几项要的一个扫描器程序。 图 1 识别表 1 所列语言中的部分单词的 DFA 及相关的语义过程 图 1 中所出现的语义变量及语义函数的含义和功能说明如下: 函数 GETCHAR:每调用一次,就把扫描指示器当前所指示的源程序字符 送入字符变量 ch,然后把扫描指示器前推一个字符位置。 字符数组 TOKEN:用来依次存放一个单词词文中的各个字符。 函数 CAT:每调用一次,就把当前 ch 中的字符拼接于 TOKEN 中所存字符 串的右边。 函数 LOOKUP:每调用一次,就以 TOKEN 中的字符串查保留字表,若查到, 就将相应关键字的类别码赋给整变量 c;否则将 c 置为零。 函数 RETRACT:每调用一次,就把扫描指示器回退一个字符位置(即退 回多读的那个字符)。 函数 OUT:一般仅在进入终态时调用此函数,调用的形式为 OUT(c,VAL)。 其中,实参 c 为相应单词的类别码助记符;实参 VAL 为 TOKEN(即词文)或 为空串。函数 OUT 的功能是,在送出一个单词的内部表示之后,返回到调用 该词法分析程序的那个程序。 3、词法分析程序的实现 程序 1 根据图 1 编写的扫描器 # include <stdio.h> # include <ctype.h> # include <string.h> # define ID 6 # define INT 7 # define LT 8 # define LE 9 # define EQ 10 # define NE 11 # define GT 12 # define GE 13 char TOKEN[20]; extern int lookup (char*); extern void out (int, char*); extern report_error (void); void scanner_example (FILE *fp) { char ch; int i, c; ch=fgetc (fp); if (isalpha (ch)) /*it must be a identifer!*/ { TOKEN[0]=ch; ch=fgetc (fp); i=1; while (isalnum (ch)) { TOKEN[i]=ch; i++; ch=fgetc (fp); } TOKEN[i]= ′\0′ fseek(fp,-1,1); /* retract*/ c=lookup (TOKEN); if (c==0) out (ID,TOKEN); else out (c," "); } else if(isdigit(ch)) { TOKEN[0]=ch; ch=fgetc(fp); i=1; while(isdigit(ch)) { TOKEN[i]=ch; i++; ch=fgetc(fp); } TOKEN[i]= ′\0′; fseek(fp,-1,1); out(INT,TOKEN); } else switch(ch) { case ′<′: ch=fgetc(fp); if(ch==′=′)out(LE," "); else if(ch==′>′) out (NE," "); else { fseek (fp,-1,1); out (LT," "); } break; case ′=′: out(EQ, " "); break; case ′>′: ch=fgetc(fp); if(ch==′=′)out(GE," "); else { fseek(fp,-1,1); out(GT," "); } break; default: report_error( ); break; } return; } 程序 1 中所用的若干函数以及主程序有待于具体编写,并需事先建立好 保留字表,以备查询。例如: /* 建立保留字表 */ #define MAX_KEY_NUMBER 20 /*关键字的数量*/ #define KEY_WORD_END “waiting for your expanding” /*关键字结束标记*/ char *KeyWordTable[MAX_KEY_NUMBER]={“begin”,“end”, “if”, “then”, “else”, KEY_WORD_END}; /* 查保留字表,判断是否为关键字 */ int lookup (char *token) { int n=0; while (strcmp(KeyWordTable[n], KEY_WORD_END)) /*strcmp 比较两串是否相同,若相同返回 0*/ { if (!strcmp(KeyWordTable[n], token)) /*比较 token 所指向的关键字和保留字表中哪个关键字相符*/ { return n+1; /*根据单词分类码表 I,设置正确的关键字类别码,并返回此类别码的值*/ break; } n++; } return 0; /*单词不是关键字,而是标识符*/ } 四、扩展实验 1、扩充关键字的数目、增加逻辑运算符等单词类别、将常数再细分成字符串 常量、整常量和无符号数常量等;添加词法分析中单词出错的位置和错 误类,以及删除注释部分等。 2、对基本实验内容进行扩充,增加状态转换图显示、词法分析过程的显示等 可视化展现功能。 3、研读 GCC,CLANG 等开源编译器的词法分析部分,分析其程序结构、实现 方法、识别的单词分类等。 4、用 LEX 自动生成词法分析程序。
11-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值