自引用结构
任务:统计输入中所有出现单词的次数。
两种解决方法:
<1>、在读取输入中任意单词的同时,就将它放置到正确的位置,从而始终保证所有单词是按顺序排列的。
<2>、采用一种二叉树的数据结构
每个不同的单词在树中都是一个节点,每个节点包括:
一个指向该单词内容的指针
一个统计出现次数的计数值
一个指向左子树的指针
一个指向右子树的指针
任何节点最多拥有两个子树,也可能只有一个子树或一个都没有。
要点:对节点的所有操作都要保证,任何节点的左子树只包含按字典序小于该节点中单词的那些单词,右子树只包含按字典序大于该节点中单词的那些单词。
标准库函数malloc能满足对齐要求
#include <stdio.h> #include<string.h> #include<ctype.h> #define MAXWORD 100 struct tnode { char *word; int count; struct tnode *left; struct tnode *right; }; struct tnode *addtree(struct tnode *, char *); void treeprint(struct tnode *); int getword(char *, int ); int main(void) { struct tnode *root; char word[MAXWORD]; root = NULL; while (getword(word,MAXWORD) != EOF) if (isalpha(word[0])) root = addtree(root, word); treeprint(root); return 0; } struct tnode *talloc(void); char *strdup1(char *); /* *addtree函数:在p的位置或p的下方增加一个w节点 */ struct tnode *addtree(struct tnode *p, char *w) { int cond; if (p == NULL) { p = talloc(); p->word = strdup1(w); p->count = 1; p->left = p->right = NULL; } else if ((cond = strcmp(w, p->word)) == 0) p->count++; else if (cond < 0) p->left = addtree(p->left, w); else p->right = addtree(p->right, w); return p; } /* *treeprint函数:按序打印树p */ void treeprint(struct tnode *p) { if (p != NULL) { treeprint(p->left); printf("%4d %s\n",p->count, p->word); treeprint(p->right); } } /* *talloc函数:创建一个tnode */ #include <stdlib.h> struct tnode *talloc(void) { return (struct tnode *)malloc(sizeof(struct tnode)); } /* *strdup函数:把传入的参数字符串复制到某个安全的位置 */ char *strdup1(char *s) { char *p; p = (char *)malloc(strlen(s) + 1); if (p != NULL) strcpy(p, s); return p; } int getch1(void); void ungetch1(int); /* *getword函数:从输入中读取下一个单词或字符 */ int getword(char* word, int lim) { int c; char *w = word; while (isspace( c = getch1())) ; if (c != EOF) *w++ = c; if (!isalpha(c)) { *w = '\0'; return c; } for (; --lim > 0; w++) if ( !isalnum( *w = getch1())) { // printf("in the getword()"); ungetch1(*w); break; } *w = '\0'; return word[0]; } #define BUFSIZE 1000 char buf[BUFSIZE]; int bufp = 0; int getch1(void) { return (bufp > 0) ?buf[--bufp] : getchar(); } void ungetch1(int c) { if (bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }
首先找到Eclipse中的WindowàPreferencesàAndroid-àBuild—>Default debug keystore: C:\Users\**\.android\debug.keystore
使用JDK的keytool.exe工具生成认证指纹:
方法如下:
C:\Users\**>keytool -list -keystore C:\Users\to.to\.android\debug.keystore
输入keystore密码: (此处默认是android)
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 1 输入
androiddebugkey, 2012-9-3, PrivateKeyEntry,
认证指纹 (MD5): 3A:40:C8:5D:14:03:4C:9F:33:9E:2A:55:87:E6:B0:6E
C:\Users\**>
链接网址:https://developers.google.com/android/maps-api-signup
如果想自己获得一个需要自己注册一个Google账号。
在下面的文本框中输入认证指纹即可。
而下面会给出地图的xml布局文件。
使用哪个xml即可。
上一节的最后,我们讲到了GPIO 初始化中用到了SIM模块的SIM_SCGC5寄存器:System Clock Gating Control Register 5(SIM_SCGC5),主要是对GPIO 模块进行时钟门控制。而且我猜测,该时钟门就是控制GPIO的高低电平变化的基准频率。那么到底是不是呢,今天我们分析一下GPIO的硬件特性。
打开文件:K60P100M100SF2RM.pdf 章节:Chapter 54 General purpose input/output (GPIO)页数:P1747
为了最大化引脚性能(响应速度),GPIO模块通过一个零等待状态接口与处理器内核进行连接,GPIO寄存器支持任何数据大小的操作。
为了使每个端口的输出更有效快速,输出口增加了设置、清除和翻转三个只写的寄存器。
分析:
零等待状态接口(zero wait state interface):指的是在IO口状态变化的时候,对变化的响应是近乎于“零等待的”,强调的是响应速度。
零等待是如何实现的,注意看下图及相关注释:
微观的角度讲,当我们给某一个io口设置高低电平时,电平变化并不是立即生效的,而是当该引脚内部参考时钟到来时,才能生效;同理对于输入口也是一样的,当内部参考时钟到来时,才会采集io口电压。
继续分析,会看到GPIOx_PDORd,GPIOx_PSOR,GPIOx_PCOR,GPIOx_PTOR,GPIOx_PDIR,GPIOx_PDDR.这一组寄存器,而且与传统的单片机寄存器配置不同,设置和清除配置都有单独的寄存器,进行对应操作。为什么没有放在一起?或者说根本不需要,想设置引脚状态,直接给数据寄存器赋值?
这一切的目的就是实现“零等待操作”,芯片内部特殊电路可以让“赋值”等操作在1个周期内完成,而如果用寄存器直接赋值的方法,则汇编指令进行对应“与、或”才能改变状态,这增加了赋值周期。进一步分析,配合该芯片,在汇编语言的设计上,应该有对应该操作的单周期指令。
到此,我们就彻底了解了mqx在初始化io端口时,配置sim模块的含义了,继续享受mqx源代码之旅吧!