自引用结构
任务:统计输入中所有出现单词的次数。
两种解决方法:
<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源代码之旅吧!