点击在新窗口中浏览此图片

一、扩展你的Smarty
1、准备功夫

PHP代码:--------------------------------------------------------------------------------
function Smarty_function_page ( $params, &$Smarty )
{
$href = '#';
$space = ' ';

$frist = NULL;
$last = NULL;

$page = 5;

extract($params);

if ( !$row || $row <= 1 ) return ' ';

$pages = $row;
$curr_page = $now ? $now : 1;
$offset = 2;
$from = $curr_page - $offset;
$to = $curr_page + $page - $offset - 1;

if ( $page > $pages )
{
$from = 1;
$to = $pages;
}
else
{
if ( $from < 1)
{
$to = $curr_page + 1 - $from;
$from = 1;
if ( ( $to - $from ) < $page && ( $to - $from ) < $pages )
{
$to = $page;
}
}
elseif ( $to > $pages )
{
$from = $curr_page - $pages + $to;
$to = $pages;
if ( ( $to - $from ) < $page && ( $to - $from) < $pages )
{
$from = $pages - $page + 1;
}
}
}

if ( $frist && ( $curr_page - 1 ) >= 1 ) $p['frist'] = '' . $frist . '';
if ( $prev && ( $i = $curr_page - 1 ) >= 1 ) $p['prev'] = '' . $prev . '';
for( $i = $from; $i <= $to; $i ++ )
{
if ( $i == $curr_page )
{
$p[$i] = '[' . $i . ']';
}
else
{
$p[$i] = '' . $i . '';
}
}
if ( $next && ( $i = $curr_page + 1 ) <= $pages ) $p['next'] = '' . $next . '';
if ( $last && ( $curr_page + 1 ) <= $pages ) $p['last'] = '' . $last . '';

return implode( $space, $p );
} // end func

--------------------------------------------------------------------------------


将上面的代码命名为"function.page.php"保存到Smarty的plugins目录里


代码:--------------------------------------------------------------------------------



New Document







{page row=10}
{page row=10 now=5}
{page row=10 now=5 href="plugins.php?a=1&b=2&page=" frist="第一页" prev="上一页" next="下一页" last="最后页"}
{page row=10 now=5 href="plugins.php?a=1&b=2&page=" frist="第一页" prev="上一页" next="下一页" last="最后页"}
{page row=10 now=1 href="plugins.php?a=1&b=2&page=" frist="第一页" prev="上一页" next="下一页" last="最后页"}
{page row=10 now=10 href="plugins.php?a=1&b=2&page=" frist="第一页" prev="上一页" next="下一页" last="最后页"}


--------------------------------------------------------------------------------


将上面的代码命名为"plugins.html"保存到Smarty的template目录里

2、测试程序

PHP代码:--------------------------------------------------------------------------------
$Smarty->display( 'plugins.html' );

--------------------------------------------------------------------------------


3、使用说明
我懒得打了,对比一下"plugins.html"的5个{page}用法,以及看看显示出来的效果就明白是什么了

4、插件说明
“《Smarty手册》第十六章.以插件扩展Smarty ”的应用。像中文字符截取之类的都可以以plugins扩展Smarty,Smarty自带的截取不支持中文。


__________________

二、Smarty自动生成静态页面
如果你的文件扩展名为".html"~~~~~嘿嘿,这不就是静态页面了吗?-_-!

至于怎么取得静态的文件名呢?


PHP代码:--------------------------------------------------------------------------------
/**
*
*/
class template extends Smarty
{

/**
*
*/
function template ()
{
$this->Smarty();
} // end func

/**
*
*/
function name ( $tpl_file, $cache_id = null, $compile_id = null )
{

if (!isset($compile_id)) $compile_id = $this->compile_id;

$_auto_id = $this->_get_auto_id( $cache_id, $compile_id );
$_cache_file = $this->_get_auto_filename( $this->cache_dir, $tpl_file, $_auto_id );

return basename( $_cache_file );
} // end func
} // end class

$Smarty = new template;
$file_name = $Smarty->name( 'plugins.html', 'cache_name' );#html文件的名字(不包含路径)

$Smarty->cache_lifetime = -1;#静态文件永不过期
$Smarty->fetch( 'plugins.html', 'cache_name' );#生成静态html文件
这是村里翻译的,实际上Smarty的应用还远不止于此。

One of the unique aspects about Smarty is the template compling. This means Smarty reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request, and each template can take full advantage of PHP compiler cache solutions such as Zend Accelerator (http://www.zend.com) or PHP Accelerator (http://www.php-accelerator.co.uk).

Smarty的特点之一是"模板编译"。意思是Smarty读取模板文件然后用他们创建php脚本。这些脚本创建以后将被执行。因此并没有花费模板文件的语法解析,同时每个模板可以享受到诸如Zend加速器(http://www.zend.com) 或者PHP加速器(http://www.php-accelerator.co.uk)。这样的php编译器高速缓存解决方案。

Some of Smarty's features:
Smaty的一些特点:

It is extremely fast.
非常非常的快!

It is efficient since the PHP parser does the dirty work.
用php分析器干这个苦差事是有效的

No template parsing overhead, only compiles once.
不需要多余的模板语法解析,仅仅是编译一次

It is smart about recompiling only the template files that have changed.
仅对修改过的模板文件进行重新编译

You can make custom functions and custom variable modifiers, so the template language is extremely extensible.
可以编辑'自定义函数'和自定义'变量',因此这种模板语言完全可以扩展

Configurable template delimiter tag syntax, so you can use {}, {{}}, , etc.
可以自行设置模板定界符,所以你可以使用{}, {{}}, , 等等


The if/elseif/else/endif constructs are passed to the PHP parser, so the {if ...} expression syntax can be as simple or as complex as you like.
诸如 if/elseif/else/endif 语句可以被传递到php语法解析器,所以 {if ...} 表达式是简单的或者是复合的,随你喜欢啦

Unlimited nesting of sections, ifs, etc. allowed.
如果允许的话,section之间可以无限嵌套

It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.
引擎是可以定制的.可以内嵌php代码到你的模板文件中,虽然这可能并不需要(不推荐)

Built-in caching support
内建缓存支持

Arbitrary template sources
独立模板文件

Custom cache handling functions
可自定义缓存处理函数

Plugin architecture
插件体系结构

键盘的驱动


    键盘在所有的驱动之中最为简单的一种,但它却包含了驱动的基本框架,对以后继续深入学习其他复杂的驱动大有裨益,以下便为你逐步剖析驱动的开发。采用的是查询方式。
一.内核模块的注册和撤销
   在加载模块的时候,首先运行的是内核模块的注册函数。它的功能包括内核注册设备以及变量的初始化。
static int head,tail;
int  _init Keypad_init(void)
{
  int result;
  result=register_chrdev(KEY_LED_MAJOR,KEY_LED_NAME,&Keypad_fops);
 Keypad_clear();
 init_waitqueue_head(&queue);
 prink("%s %s initialized.\n",KEY_LED_NAME,KEY_LED_VERSION);//不能用prinf
return 0;
}
module_init(Keypad_init);//加载模块
void _exit Keypad_cleanup(void)
{
  del_timer(&timer);
  unregister_chrdev(KEY_LED_MAJOR,KEY_LED_NAME);
  prink("Keypad driver removed \n");
}
module_exit(Keypad_cleanup);//卸载该模块
二.虚拟文件系统与硬件驱动的接口
static struct file_operations Keypad_fops={
 open:Keypad_open,
 read:Keypad_read,
 poll:Keypad_poll,
 fasync:Keypad_fasync,
release:Keypad_release,
};
该接口定义完之后一些便是对这几个具体函数的实现了!现在我们一起进入下一步吧,是不是觉得其实没什么难度的呢?别那么早开心着呢?这几个函数的实现时候,涉及到很多技术,包括内核定时器,等待队列的具体实现(阻塞方式),异步方式的具体实现技巧,循环队列。看到这么多技术你是否感到很兴奋呢?以下本人将以通俗的方式为你讲解,希望你能理解。
三.设备的打开操作接口函数具体实现(Keypad_open)
设备打开一般包括两大操作,一是完成设备的初始化,二是设备引用计数器加1
static int Keypad_open(struct inode *inode,struct file *filp)
{
 read_xy();
 try_module_get(THIS_MODULE);//此函数为linux 2.6内核增加的,不同于2.4内核,功能是计数器的值加1
 return 0;
}
static void read_xy(void)
{
 new_data();//获取键值函数
 keypad_starttimer();//开启内核定时器,在固定周期时间内获取键盘新的变化
}
以下实现键盘键值获取函数read_xy()
主要是从KEY_CS(对应的读入地址,之前可以根据具体的硬件设备定义,比如#define kEY_CS(*

(volatile unsigned short *)(0xf820000))此处应该根据具体的不同而不同!
将读入的键值存入buf[]缓存中,环形缓冲的写指针是head,读指针是tail,前面已经定义过了
////////////////////////////////键盘事件的数据结构定义/////////////////////////////////
typedef struct{
 ulong status;//按键的值
 ulong click;//是否有按键按下,1表示有,0表示没有
}KEY_EVENT
static KEY_EVENT cur_data,buf[BUFSIZE];//BUFSIZE为宏定义,用于定义环形缓冲的大小
static void new_data(void)
{
 if((KEY_CS & 0xff)!=0xff)  //从KEY_CS地址读入数据,若有一个为0则表示有一个按键被按下了(此处硬件电路为低电平有效)
 {
       switch(KEY_CS & 0xff){
            case ~KEY0 & 0xff:
                     cur_data.status=1;///////1被按下
                     break;
         
             case ~KEY1 & 0xff:
                     cur_data.status=2;//2被按下
                     break;
             /////////其他一样添加,懂吗??
        }
         cur_data.click=1;
    }
    else if(KEY_CS & 0xff==0xff){
        cur_data.click=0;
       cur_data.status=0;
    }
    if(head!=tail){////////循环队列缓冲区的应用在此开始了^_^
        int last=head--;
        if(last<0)////////若已经到了对首之前,则跳到队尾,以实现循环队列
           last=BUFSIZE-1;
    }
    //////按键信息存入循环队列缓冲区中
    buf[head]=cur_data;
   if(++head==BUFSIZE)
      head=0;
   if(head==tail && tail++=BUFSIZE)
     tail=0;
   if(fasync)
     kill_fasync(&fasyc,SIGIO,POLL_IN);
   wake_up_interruptible(&queue);
}

接下来我们介绍其他几个文件接口函数的实现
四.先介绍关闭函数keypad_release(),为什么先介绍它呢?道理很简单,应该它比较简单,先让大家做下热身运动,在介绍完这个之后,继续会介绍一个比较复杂的函数.
   关闭操作主要实现的是:关闭设备异步通知,设备计数器减1,删除定时器信号中断
static int Keypad_release(struct inode *inode,struct)
{
  Keypad_fasync(-1,filp,0);
 module_put(THIS_MODULE);
del_timer(&timer);
return 0;
}
五.设备读取操作接口函数实现Keypad_read()
  主要作用是从缓冲区读取键值,通过调用get_data()实现,通过copy_to_user()函数将键值复制到用户的数据区中
static ssize_t Keypad_read(struct file *filp,char *buf,ssize_t count,loff_t *l)
{
  DECLEARE_WAITQUEUE(wait,current);//声明等待队列,将当前进程加入到等待队列中
  KEY_EVENT t;
  ulong out_buf[2];
  if(head==tail)//当前循环队列中没有数据可以读取
  {
       if(filp->f_flags & O_NONBLOCK)//假如用户采用的是非堵塞方式读取
            return _EAGAIN;
      add_wait_queue(&queue,&wait);//将当前进程加入等待队列
      current->state=TASK_INTERRUPTIBLE;//设置当前进程的状态
      while((head==tail)&&!signal_pending(current))//假若还没有数据到循环队列并且当前进程没有受到信号
       {
             shedule();//进程调度
             current->state=TASK_INTERRUPTIBLE;
       }
       current->state=TASK_RUNNING;
       remove_wait_queue(&queue,&wait);
       if(head==tail)
          return count;
       t=get_data();//调用get_data()函数,得到缓冲区中的数据,下面将给予详细的 介绍
       out_buf[0]=t.status;
       out_buf[1]=t.click;
       copy_to_user(buf,&out_buf,sizeof(out_buf));//将得到的键值拷贝到用户数据区
       return count;
     
  }
}
很自然我们就应该要介绍get_data()函数的实现了,该函数的功能就是从我们定义的循环队列缓冲区中读出我们要的键值,所以其实很简单的如果理解循环队列的原理,在此不多加解释,大家应该具备一般的数据结构相关的知识吧
static KEY_EVENT get_data(void)
{
    int last=tail
    if(++tail==BUFSIZE)
       tail=0;
    return buf[last];
}
上面如果你看得懂得话,那么可以进入下面的学习了,主要介绍的是内核定时器的使用,利用等待队列实现阻塞型I/O,poll系统调用,异步通知方式,介绍完之后,我将给出一个应用实例,对于有使用过文件操作系统调用的来说,对我们所写的键盘驱动来说,他们基本上是一样的。废话少说,我们马上开始我们精彩的驱动开发!
六.内核定时器的使用
   在该驱动中,我们假设对键盘的获取是以0.2s为周期执行。源代码如下
static struct timer_list timer;///////我们定义的定时器,也许你会问timer_list是什么来的,其实一看名称就应该就知道了,而为什么要用到list那么多定时器呢?其实在linux中还有很多相同的定义,比如说信号,我们定义的也是信号集,你可以定义该list是一个元素的,也可以是多个的。所以对于 timer_list就可以这样描述:在未来某一个特定时刻执行某一系列特定任务的功能。下面我们还会给出内核中timer_list的具体描述,
static int Keypad_starttimer(void)
{
    init_timer(&timer);//初始化定时器结构
    timer.function=Keypad_timer;//超时服务程序
    timer.expires=jiffies+20;//当前时刻加0.2s
    add_timer(&timer);
    return 0;
}
///超时服务程序
static void Keypad_timer(unsigned long data)
{
   read_xy();
}
/////////接下来说下timer-list这个数据结构,如果你不感兴趣的话可以跳过,该结构在

include\linux\timer.h中定义
struct timer_list
{
    struct list_head entry;
    unsigned long expries;
   spinlock_t lock;
   unsigned long magic;
   void (*function)(unsigned long);
   unsigner long data;
   struct tvec_t_base_s *base;
}
七.利用等待队列实现阻塞型I\O
    在用户程序执行读操作的时候有可能尚且没有数据可以读取,为此需要让read操作等待,直到有数据可以读取,这就是阻塞型i\o,阻塞型io可以通过使用进程休眠方法实现。在无数据可以读取的时候,采用等待队列让进程休眠,直到有数据到达的时候才唤醒进程完成数据的读操作。
   在本驱动中的read,若循环队列缓冲区中没有数据,则进程进入休眠态,定时器函数每隔0.2s读取键值一次,将按键状态放入缓冲并且适时唤醒进程读取数据。
  等待队列的使用流程如下:
  1.声明一个等待队列
  2.把当前进程加入到等待队列中
  3.把进程的状态设置为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE;
  4.调用schedule,以让出cpu
 5.检测所需要的资源是否可用,若是,把当前进程从等待队列中删除,否则转3循环
接下来我们在对read中有关等待队列阻塞实现做具体的解释
static ssize_t Keypad_read(struct file *filp,char *buf,ssize_t count,loff_t *l)
{
  DECLEARE_WAITQUEUE(wait,current);//声明等待队列,将当前进程加入到等待队列中
  KEY_EVENT t;
  ulong out_buf[2];
  if(head==tail)//当前循环队列中没有数据可以读取
  {
       if(filp->f_flags & O_NONBLOCK)//假如用户采用的是非堵塞方式读取
            return _EAGAIN;
      add_wait_queue(&queue,&wait);//将当前进程加入等待队列
      current->state=TASK_INTERRUPTIBLE;//设置当前进程的状态
      while((head==tail)&&!signal_pending(current))//假若还没有数据到循环队列并且当前进程没有受到信号(该类信号具体来说是未决的休眠)
       {
             shedule();//进程调度
             current->state=TASK_INTERRUPTIBLE;
       }
       current->state=TASK_RUNNING;//该进程恢复执行
       remove_wait_queue(&queue,&wait);//移出等待队列
       if(head==tail)
          return count;
       t=get_data();//调用get_data()函数,得到缓冲区中的数据,下面将给予详细的 介绍
       out_buf[0]=t.status;
       out_buf[1]=t.click;
       copy_to_user(buf,&out_buf,sizeof(out_buf));//将得到的键值拷贝到用户数据区
       return count;
     
  }
}
八.poll系统调用操作接口函数
  当程序需要进行对多个文件读写时,如果某个文件没有准备好,则系统就会处于读写阻塞的状态,这影响了其他文件的读写,为了避免读写阻塞,一般可以在应用程序中使用poll或者select函数。当poll函数返回时,会给出一个文件是否可读写的标志,应用程序根据不同的标志读写相应的文件,实现非阻塞的读写,poll()函数通过poll系统调用,调用对应设备驱动的poll()接口函数,poll返回不同的标志,告诉主进程文件是否可以读写,这些返回标志存放在include\asm\poll.h中

标志  含义
POLLIN  如果设备无阻塞的读,就返回该值
POLLRDNORM  通常的数据已经准备好,可以读了,就返回
该值。通常的做法是会返回(POLLLIN|POLLRDNORA)
POLLRDBAND  如果可以从设备读出带外数据,就返回该值,它只可在linux内核的某些网络代码中使用,通常不用在设备驱动程序中
POLLPRI  如果可以无阻塞的读取高优先级(带外)数据,就返回该值,返回该值会导致select

报告文件发生异常,以为select八带外数据当作异常处理POLLHUP  当读设备的进程到达文件尾时,驱动程序必须返回该值,依照select的功能描述,调用select的进程被告知进程时可读的。
POLLERR  如果设备发生错误,就返回该值。
POLLOUT  如果设备可以无阻塞地些,就返回该值
POLLWRNORM  设备已经准备好,可以写了,就返回该值。通常地做法是(POLLOUT|POLLNORM)
POLLWRBAND  于POLLRDBAND类似
在本章地驱动程序中,Keypad_poll()函数在缓冲区有新数据时(当head!=tail),返回一个

POLLIN|POLLRDNORM,告诉主进程有新的

九.在设备驱动中实现异步通知
  虽然大多数时候阻塞型和非阻塞型操作的组合及poll方法可以有效查询设备是否可以读写,但是如果驱动程序能避免主动的查询,改主动为被动的信号通知触发,则可以提高程序的效率,这也就是异步通知的目的。异步通知向进程发送SIGIO信号,通知访问设备的进程,表示该设备已经准备好IO读写了。
 之后就是如何实现异步通知的问题了,要启动异步通知,必须执行两个步骤:首先,须要制定某个作为文件的“属主”。文件属主的进程ID保存在filp- >f_owner中,这可以通过fcntl()系统调用执行F_SETOWN命令设置。此外,用户程序还必须曙色之设备的FASYNC标志,以真正启动异步通知机制。这里的FASYNC标志也使用fcntl()设置。
 在完成这两个步骤之后,当新数据到达时就会产生一个SIGNO信号,此信号发送到存放在filp->owner中的进程。
 从驱动的角度看,则主要时通过调用两个内核提供的函数来实现就是了。他们分别是:int

fasync_helper()和void kill_fasync();这两个函数定义在:include\linux\fs\fcntl.h
   要实现异步,驱动中只要如下编写即可
static struct fasync_struct *fasync;//首先是定义一个结构体
static int Keypad_release(struct inode *inode,struct file *filp)
{
  Keypad_fasync(-1,filp,0);//这是一个异步通知
。。。。。。。
}
static int Keypad_fasync(int fd,struct file *filp,int on)
{
  int retval;
 retval=fasync_helper(fd,filp,on,&fasync);
 if(retval<0)
    return retval;
 return 0;
}
到此为止,键盘驱动已经介绍完了,接下来就介绍下一个利用使用驱动的应用实例了。
以下程序的主体是一个条件循环,每次循环执行一次,就读取一次键值。
1。打开Keypad设备
#define DEV_NAME "/dev/Keypad"
int fb=0;
fb=open(DEV_NAME,O_RNONLY);
if(!fb){
   printf("Error:cannot open Keypad device.\n");
  exit(1);
}
printf("The Keypad device was opened successfully.\n");
}
2.读取键值
unsigned long keydata[2];
int input=1;
while(input!=0)
{
   if(read(fd,(char*)keydata,sizeof(keydata))==-1){
      printf("Error reading the keypad data");
      close(fb);
      exit(2);
    }
    if(keydata[0]){
     switch(keydata[1]){
         case 1:printf("KEYPUSED 1");//1键被按下
                     input=0;////下此循环退出
                     break;
         。。。。。。。。。。。。。。。。。。
     }
   }
}
3。关闭Keypad设备
close(fb);
printf("Good bye Keypad");

键盘驱动到此介绍完毕!!
            今天,同学也是玩得好得听说是给录取入民航大学了,开飞机,哈哈,我可是有点好处,我都说能得啊,最后,果然能够了,嘻嘻,打造和东哥混的人都是NIU人的大好局面。。。。smoke

C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语
言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带
来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误
。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错
误,写给各位学员以供参考。  

1.书写标识符时,忽略了大小写字母的区别。
main()
{
int a=5;
printf("%d",A);
}
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是
两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。

2.忽略了变量的类型,进行了不合法的运算。
main()
{
float a,b;
printf("%d",a%b);
}
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许
进行“求余”运算。

3.将字符常量与字符串常量混淆。
char c;
c="a";
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字
符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统
自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变
量是不行的。

4.忽略了“=”与“==”的区别。
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中
可以写
if (a=3) then …
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
if (a==3) a=b;
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,
初学者往往会犯这样的错误。

5.忘记加分号。
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
a=1
b=2
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一
部分,这就会出现语法错误。改错时,有时在被指出有错的一行中\未发现错误,就需要看
一下上一行是否漏掉了分号。
{ z=x+y;
t=z/100;
printf("%f",t);
}
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL
不同的)。

6.多加分号。
对于一个复合语句,如:
{ z=x+y;
t=z/100;
printf("%f",t);
};
复合语句的花括号后不应再加分号,否则将会画蛇添足。
又如:
if (a%3==0);
I++;
本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将
执行I++语句,不论3是否整除a,I都将自动加1。
再如:
for (I=0;I<5;I++);
{scanf("%d",&x);
printf("%d",x);}
本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循
环体变为空语句,此时只能输入一个数并输出它。

7.输入变量时忘记加地址运算符“&”。
int a,b;
scanf("%d%d",a,b);
这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指
a在内存中的地址。

8.输入数据的方式与要求不符。
①scanf("%d%d",&a,&b);
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
3,4
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
②scanf("%d,%d",&a,&b);
C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应
输入与这些字符相同的字符。下面输入是合法的:
3,4
此时不用逗号而用空格或其它字符是不对的。
3 4 3:4
又如:
scanf("a=%d,b=%d",&a,&b);
输入应如以下形式:
a=3,b=4

9.输入字符的格式与要求不一致。
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
scanf("%c%c%c",&c1,&c2,&c3);
如输入a b c
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后
面不需要用空格作为两个字符的间隔。

10.输入输出的数据类型与所用格式说明符不一致。
例如,a已定义为整型,b定义为实型
a=3;b=4.5;
printf("%f%d\n",a,b);
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。

11.输入数据时,企图规定精度。
scanf("%7.2f",&a);
这样做是不合法的,输入数据时不能规定精度。

12.switch语句中漏写break语句。
例如:根据考试成绩的等级打印出百分制数段。
switch(grade)
{ case 'A':printf("85~100\n");
case 'B':printf("70~84\n");
case 'C':printf("60~69\n");
case 'D':printf("<60\n");
default:printf("error\n");
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,
printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写
法应在每个分支后再加上“break;”。例如
case 'A':printf("85~100\n");break;

13.忽视了while和do-while语句在细节上的区别。
(1)main()
{int a=0,I;
scanf("%d",&I);
while(I<=10)
{a=a+I;
I++;
}
printf("%d",a);
}
(2)main()
{int a=0,I;
scanf("%d",&I);
do
{a=a+I;
I++;
}while(I<=10);
printf("%d",a);
}
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就
不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的
数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。

14.定义数组时误用变量。
int n;
scanf("%d",&n);
int a[n];
数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的
大小作动态定义。

15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
main()
{static int a[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d",a[10]);
}
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[
10]是不存在的。


16.在不应加地址运算符&的位置加了地址运算符。
scanf("%s",&str);
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入
项是字符数组名,不必要再加地址符&。应改为:scanf("%s",str);

17.同时定义了形参和函数中的局部变量。
int max(x,y)
int x,y,z;
{z=x>y?x:y;
return(z);
}
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
int max(x,y)
int x,y;
{int z;
z=x>y?x:y;
return(z);
}

深入理解C语言指针的奥秘

    指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。 要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。
  先声明几个指针放着做例子:
  例一:
  (1)int*ptr;
  (2)char*ptr;
  (3)int**ptr;
  (4)int(*ptr)[3];
  (5)int*(*ptr)[4];
  
  指针的类型
  从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:

  (1)int*ptr;//指针的类型是int*
  (2)char*ptr;//指针的类型是char*
  (3)int**ptr;//指针的类型是int**
  (4)int(*ptr)[3];//指针的类型是int(*)[3]
  (5)int*(*ptr)[4];//指针的类型是int*(*)[4]
  怎么样?找出指针的类型的方法是不是很简单?
  指针所指向的类型
  当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。
  从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:
  (1)int*ptr;//指针所指向的类型是int
  (2)char*ptr;//指针所指向的的类型是char
  (3)int**ptr;//指针所指向的的类型是int*
  (4)int(*ptr)[3];//指针所指向的的类型是int()[3]
  (5)int*(*ptr)[4];//指针所指向的的类型是int*()[4]
  在指针的算术运算中,指针所指向的类型有很大的作用。
  指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的"类型"这个概念分成"指针的类型"和"指针所指向的类型"两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。
指针的值,或者叫指针所指向的内存区或地址
  指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为si zeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。
  指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。
  以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指的类型是什么?该指针指向了哪里?
  指针本身所占据的内存区
  指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。
  指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。
  指针的算术运算
指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:
  例二:
  1、chara[20];
  2、int*ptr=a;
  ...
 ...
  3、ptr++;
  在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。
由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。
  我们可以用一个指针和一个循环来遍历一个数组,看例子:
  例三:
intarray[20];
int*ptr=array;
...
//此处略去为整型数组赋值的代码。
...
for(i=0;i<20;i++)
{
 (*ptr)++;
 ptr++;
}
  这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1,所以每次循环都能访问数组的下一个单元。

  再看例子:

  例四:

  1、chara[20];
  2、int*ptr=a;
  ...
  ...
  3、ptr+=5;
  在这个例子中,ptr被加上了5,编译器是这样处理的:将指针ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的单位是字节,故现在的ptr所指向的地址比起加5后的ptr所指向的地址来说,向高地址方向移动了20个字节。在这个例子中,没加5前的ptr指向数组a的第0号单元开始的四个字节,加5后,ptr已经指向了数组a的合法范围之外了。虽然这种情况在应用上会出问题,但在语法上却是可以的。这也体现出了指针的灵活性。

  如果上例中,ptr是被减去5,那么处理过程大同小异,只不过ptr的值是被减去5乘sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20个字节。
  总结一下,一个指针ptrold加上一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值增加了n乘sizeof(ptrold所指向的类型)个字节。就是说, ptrnew所指向的内存区将比ptrold所指向的内存区向高地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。
  一个指针ptrold减去一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和 ptrold所指向的类型也相同。ptrnew的值将比ptrold的值减少了n乘sizeof(ptrold所指向的类型)个字节,就是说, ptrnew所指向的内存区将比ptrold所指向的内存区向低地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。
运算符&和*
这里&是取地址运算符,*是...书上叫做"间接运算符"。
  &a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。
  *p的运算结果就五花八门了。总之*p的结果是p所指向的东西,这个东西有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。
  例五:
inta=12;
intb;
int*p;
int**ptr;
p=&a;
//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。
*p=24;
//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。
ptr=&p;
//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int **。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。
*ptr=&b;
//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以用&b来给*ptr赋值就是毫无问题的了。
**ptr=34;
//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。
  指针表达式
一个表达式的最后结果如果是一个指针,那么这个表达式就叫指针表式。
  下面是一些指针表达式的例子:
  例六:
inta,b;
intarray[10];
int*pa;
pa=&a;//&a是一个指针表达式。
int**ptr=&pa;//&pa也是一个指针表达式。
*ptr=&b;//*ptr和&b都是指针表达式。
pa=array;
pa++;//这也是指针表达式。
例七:
char*arr[20];
char**parr=arr;//如果把arr看作指针的话,arr也是指针表达式
char*str;
str=*parr;//*parr是指针表达式
str=*(parr+1);//*(parr+1)是指针表达式
str=*(parr+2);//*(parr+2)是指针表达式
  由于指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。

  好了,当一个指针表达式的结果指针已经明确地具有了指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。
  在例七中,&a不是一个左值,因为它还没有占据明确的内存。*ptr是一个左值,因为*ptr这个指针已经占据了内存,其实*ptr就是指针pa,既然pa已经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。
  数组和指针的关系
  数组的数组名其实可以看作一个指针。看下例:
  例八:
intarray[10]={0,1,2,3,4,5,6,7,8,9},value;
...
...
value=array[0];//也可写成:value=*array;
value=array[3];//也可写成:value=*(array+3);
value=array[4];//也可写成:value=*(array+4);
上例中,一般而言数组名array代表数组本身,类型是int[10],但如果把array看做指针的话,它指向数组的第0个单元,类型是int*,所指向的类型是数组单元的类型即int。因此*array等于0就一点也不奇怪了。同理,array+3是一个指向数组第3个单元的指针,所以*(array+ 3)等于3。其它依此类推。

  例九:
char*str[3]={
 "Hello,thisisasample!",
 "Hi,goodmorning.",
 "Helloworld"
};
chars[80];
strcpy(s,str[0]);//也可写成strcpy(s,*str);
strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));
strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));
上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char*。
*str 也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串"Hello,thisisasample!"的第一个字符的地址,即'H'的地址。 str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char*。

  *(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向 "Hi,goodmorning."的第一个字符'H',等等。

  下面总结一下数组的数组名的问题。声明了一个数组TYPEarray[n],则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPE[n];第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。
  在不同的表达式中数组名array可以扮演不同的角色。
  在表达式sizeof(array)中,数组名array代表数组本身,故这时sizeof函数测出的是整个数组的大小。
在表达式*array中,array扮演的是指针,因此这个表达式的结果就是数组第0号单元的值。sizeof(*array)测出的是数组单元的大小。
  表达式array+n(其中n=0,1,2,....。)中,array扮演的是指针,故array+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。故sizeof(array+n)测出的是指针类型的大小。
例十
intarray[10];
int(*ptr)[10];
ptr=&array;:
上例中ptr是一个指针,它的类型是int(*)[10],他指向的类型是int[10] ,我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。

  本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:
int(*ptr)[10];
  则在32位程序中,有:
sizeof(int(*)[10])==4
sizeof(int[10])==40
sizeof(ptr)==4
实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。
指针和结构类型的关系
可以声明一个指向结构类型对象的指针。
  例十一:
structMyStruct
{
 inta;
 intb;
 intc;
}
MyStructss={20,30,40};
//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。
MyStruct*ptr=&ss;
//声明了一个指向结构对象ss的指针。它的类型是MyStruct*,它指向的类型是MyStruct。
int*pstr=(int*)&ss;
//声明了一个指向结构对象ss的指针。但是它的类型和它指向的类型和ptr是不同的。
  请问怎样通过指针ptr来访问ss的三个成员变量?
  答案:
ptr->a;
ptr->b;
ptr->c;
  又请问怎样通过指针pstr来访问ss的三个成员变量?
  答案:
*pstr;//访问了ss的成员a。
*(pstr+1);//访问了ss的成员b。
*(pstr+2)//访问了ss的成员c。
  虽然我在我的MSVC++6.0上调式过上述代码,但是要知道,这样使用pstr来访问结构成员是不正规的,为了说明为什么不正规,让我们看看怎样通过指针来访问数组的各个单元:
  例十二:
intarray[3]={35,56,37};
int*pa=array;
  通过指针pa访问数组array的三个单元的方法是:
*pa;//访问了第0号单元
*(pa+1);//访问了第1号单元
*(pa+2);//访问了第2号单元
  从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。
  所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个"填充字节",这就导致各个成员之间可能会有若干个字节的空隙。
  所以,在例十二中,即使*pstr访问到了结构对象ss的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员 b。因为成员a和成员b之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。这也证明了指针的灵活性。要是你的目的就是想看看各个结构成员之间到底有没有填充字节,嘿,这倒是个不错的方法。
过指针访问结构成员的正确方法应该是象例十二中使用指针ptr的方法。
  指针和函数的关系
  可以把一个指针声明成为一个指向函数的指针。intfun1(char*,int);
int(*pfun1)(char*,int);
pfun1=fun1;
....
....
inta=(*pfun1)("abcdefg",7);//通过函数指针调用函数。
可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为实参。
  例十三:
intfun(char*);
inta;
charstr[]="abcdefghijklmn";
a=fun(str);
...
...
intfun(char*s)
{
intnum=0;
for(inti=0;i{
num+=*s;s++;
}
returnnum;
}
  这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。前面说了,数组的名字也是一个指针。在函数调用中,当把str作为实参传递给形参s后,实际是把str的值传递给了s,s所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的存储空间。在函数体内对s进行自加1运算,并不意味着同时对str进行了自加1运算。
指针类型转换
当我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式。在我们前面所举的例子中,绝大多数情况下,指针的类型和指针表达式的类型是一样的,指针所指向的类型和指针表达式所指向的类型是一样的。
  例十四:
  1、floatf=12.3;
  2、float*fptr=&f;
  3、int*p;
   在上面的例子中,假如我们想让指针p指向实数f,应该怎么搞?是用下面的语句吗?

  p=&f;

  不对。因为指针p的类型是int*,它指向的类型是int。表达式&f的结果是一个指针,指针的类型是 float*,它指向的类型是float。两者不一致,直接赋值的方法是不行的。至少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两边的类型一致,所指向的类型也一致,其它的编译器上我没试过,大家可以试试。为了实现我们的目的,需要进行"强制类型转换":
p=(int*)&f;
如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*TYPE, 那么语法格式是:
  (TYPE*)p;
  这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。而原来的指针p的一切属性都没有被修改。
  一个函数如果使用了指针作为形参,那么在函数调用语句的实参和形参的结合过程中,也会发生指针类型的转换。
  例十五:
voidfun(char*);
inta=125,b;
fun((char*)&a);
...
...
voidfun(char*s)
{
charc;
c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;
c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;
}
}
注意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。函数fun的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?在函数调用语句中,实参&a的结果是一个指针,它的类型是int*,它指向的类型是int。形参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过程中,我们必须进行一次从int*类型到char*类型的转换。结合这个例子,我们可以这样来想象编译器进行转换的过程:编译器先构造一个临时指针char*temp,然后执行temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的首地址。

  我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是一个32位整数。那可不可以把一个整数当作指针的值直接赋给指针呢?就象下面的语句:
unsignedinta;
TYPE*ptr;//TYPE是int,char或结构类型等等类型。
...
...
a=20345686;
ptr=20345686;//我们的目的是要使指针ptr指向地址20345686(十进制

ptr=a;//我们的目的是要使指针ptr指向地址20345686(十进制)
编译一下吧。结果发现后面两条语句全是错的。那么我们的目的就不能达到了吗?不,还有办法:
unsignedinta;
TYPE*ptr;//TYPE是int,char或结构类型等等类型。
...
...
a=某个数,这个数必须代表一个合法的地址;
ptr=(TYPE*)a;//呵呵,这就可以了。
严格说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。这里的(TYPE*)的意思是把无符号整数a的值当作一个地址来看待。上面强调了a的值必须代表一个合法的地址,否则的话,在你使用ptr的时候,就会出现非法操作错误。

  想想能不能反过来,把指针指向的地址即指针的值当作一个整数取出来。完 全可以。下面的例子演示了把一个指针的值当作一个整数取出来,然后再把这个整数当作一个地址赋给一个指针:
  例十六:
inta=123,b;
int*ptr=&a;
char*str;
b=(int)ptr;//把指针ptr的值当作一个整数取出来。
str=(char*)b;//把这个整数的值当作一个地址赋给指针str。
  现在我们已经知道了,可以把指针的值当作一个整数取出来,也可以把一个整数值当作地址赋给一个指针。
  指针的安全问题
看下面的例子:
  例十七:
chars='a';
int*ptr;
ptr=(int*)&s;
*ptr=1298;
  指针ptr是一个int*类型的指针,它指向的类型是int。它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s所占的一个字节,还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。
  让我们再来看一例:
  例十八:
  1、chara;
  2、int*ptr=&a;
  ...
  ...
  3、ptr++;
  4、*ptr=115;
  该例子完全可以通过编译,并能执行。但是看到没有?第3句对指针ptr进行自加1运算后,ptr指向了和整形变量a相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。而第4句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。
  在指针的强制类型转换:ptr1=(TYPE*)ptr2中,如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针 ptr1来访问ptr2所指向的存储区时是不安全的。至于为什么,读者结合例十七来想一想,应该会明白的。

Smarty是一款PHP官方支持的模板,有点小复杂。

重要的是LIBS这个目录,以及在数据文件中,对“templates”,“templates_c”,“configs”以及“cashe”四个目录的设定;什么地方可以放模板,什么地方可以放数据,确实让开始学习的我头痛了一番。


比如,我要写一个 HelloWorld 程序,步骤如下:

   1. 到 SMARTY 下载稳定的SMARTY包。
   2. 在APACHE相应目录下面,新建一个文件夹:“helloworld”。
   3. 将下载下来的smarty包内的“libs”文件夹完完全全的拷贝到“helloworld”文件夹。
   4. 接下来就是最最恶心的一步了,你需要在“helloworld”手工新建四个文件夹:“cashe”、“configs”、“templates”,“templates_c”(不要修改文件夹名称),这四个文件将与“libs”文件夹并行。
   5. 我们接着写一个模板文件,是的,它必须安放在“templates”文件夹下面(不要问我为什么,其实我也不知道~),你可以将它命名为index.tpl,或者index.html,推荐前者(smarty的模板格式,虽然我觉得其内容和html没有什么区别),输入如下代码:

         1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
         2. <html>
         3. <head>
         4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
         5. <title>Smarty</title>
         6. </head>
         7. <body >
         8. {$hello_templates}
         9. </body>
        10. </html>

   6. 接着,我们需要写一个数据文件,这个才是重头。在“helloworld”根目录下面,新建一个index.php文件,写入如下代码:

         1. <?php
         2. //引用类文件
         3. require '/libs/Smarty.class.php';
         4.  
         5. $smarty = new Smarty;
         6.  
         7. //设置各个目录的路径,这里是安装的重点
         8.  
         9. $smarty->template_dir = "templates";
        10.  
        11. $smarty->compile_dir = "templates_c";
        12. $smarty->config_dir = "config";
        13. $smarty->cache_dir = "cache";
        14.  
        15. //smarty模板有高速缓存的功能,如果这里是true的话即打开caching,但是会造成网页不立即更新的问题,当然也可以通过其他的办法解决
        16. $smarty->caching = false;
        17.  
        18. //赋值
        19. $smarty->assign("hello_templates","Hello World!");
        20.  
        21. //引用模板文件,注意这里的index.tpl路径,不是真实的路径,不用写成/templates/index.tpl样式
        22. $smarty->display('index.tpl');
        23.  
        24. ?>


如果出现找不到文件:可能是如下变量设置或者默认设置有问题:

$tpl->template_dir = "./aaa";//修改到aaa目录,默认是templates,这个aaa和templates是一个层级的,然后放入模板文件即可!
echo $tpl->template_dir;
echo $tpl->config_dir ;
echo $tpl->compile_dir;
echo $tpl->cache_dir;

作曲/編曲 天 門
作詞    新海 誠
補編曲   岡澤敏夫

逐渐凝入晚霞下的蓝空中白云 遥远的那天的颜色
色あせた青ににじむ 白い雲 遠いあの曰のいろ
心中隐藏着任何人都不知道的痛
心の奥の誰にも 隠してる痛み

我用尽一切的言语 也已远去
僕のすべてかけた 言葉もう遠く
寄托着心情的每一天 现在你依然 温暖着我
なくす曰々の中で今も きみは 僕をあたためてる

你的声音 你的身影 照耀的光
きみのこえ きみのかたち 照らした光
若能实现 我的声音 希望能传给在某处的你
かなうなら 僕のこえ どこかのきみ とどくように
我活下去
僕は生きてく

阳光照射下灼热的铁轨 声音渐远 那天的声音
曰差しに灼けたレールから 響くおと遠く あの曰のこえ
那云的彼岸 现在依然是约定的地方
あの雲のむこう今でも 約束の場所ある

不知何时起 孤独纠缠着我 不平静的心
いつからか孤独 僕を囲み きしむ心
在过去的时光中 一定是我已渐渐失去你
過ぎる時の中できっと 僕はきみをなくしていく

你的头发 天空和云 溶化的世界 充满神秘地
きみの髪 空と雲 とかした世界 秘密に満ちて
你的声音 温柔的手指 和风般的肌肤
きみのこえ やさしい指 風うける肌
心变得坚强
こころ強くする

いつまでも こころ震わす きみの背中
希望 我的歌 能传达给某处的你
願いいただ 僕の歌 どこかのきみ とどきますよう
我活下去
僕は生きてく

你的声音 你的身影 照耀的光
きみのこえ きみのかたち 照らした光
若能实现 纵然分隔两地 我也要 温柔地坚强
かなうなら 生きる場所 違うけれど 優しく強く
活下去
僕は生きたい

全国计算机等级二级 Java 考试前的一些复习题:

  1.  Java 中,常量 true、false、null 都是小写。
  2. 多线程是 Java 程序的并发机制,它能同步共享数据、处理不同事件。
  3. 算法基本特征是可行性、确定性、有穷性、拥有足够的情报。
  4. 数据库管理系统提供了数据的定义、操纵、运行控制功能。
  5. 计算机软件由两部分组成,一部分是机器可执行的程序和数据,另一部分是机器不可执行的,与软件开发、运行、维护、使用有关的文档。
  6. 转义字符以反斜杠(/)开头。
  7. Java 原文件中最多只能有一个Public类,其他类的个数不限。
  8. 在 Java 程序中,通过类的定义只能实现单重继承,但用过接口的定义可以实现多重继承关系。
  9. 如果一个 Java 源程序文件中定义了4个类,则使用 Sun 公司的 JDK 编译器 javac 编译该源程序文件,将生成4个文件,扩展名为 class 的字节码文件。
 10. 位运算符用来对二进制位进行操作,操作只能为 整数 和字符型数据。
 11. 字符类型变量已 char 类型表示,它在内存中占 16 位 bit。
 12. Java 虚拟机(JVM)的执行过程有 3 个特点:多线程、动态连接、异常处理。
 13. 在 AWT 包中,创建一个具有10行、45列的多行文本区域对象 ta 的语句为 TextArea ta = new TextArea(10, 45);
 14. 根据程序的结构和运行环境不同,Java 源程序分为两类,即 JavaApplicAtion 程序和 JavaApplic 程序。
 15. Java 语言中的浮点类型数据根据数据储存长度和数值精度的不同,进一步分为 float 和 double 两种类型。
 16. 按照变量用域分类,变量有 局部变量、类变量 和 方法参数、异常处理参数。
 17. 1991 年,Sun 公司的 Jame Gosling、Bill Joe 等人,为电视、调制烤面包机等家用电器的交互操作开发了一个 Oak 软件,它是 Java 的前身。
 18. 设 x = 2 则表达式 (x++)*3 的值是 6 。
 19. 在 Java 的基本数据类型中,char 类型数据占 2 字节内存空间,int 型占用 4 字节内存空间。
 20. catch 字句都带一个参数,该参数是某个异常的类及其变量名,chtch 用该参数去抛出异常对象的类进行 匹配。
 21. 整型常量在计算中默认占 32 位。
 22. Java 语言中,为将源代码翻译成字节码文件时产生的错误称为编译错误。而将程序在运行中产生的错误称为运行错误。
 23. J2SDK 中 path 环境变量指定了 JDK 命令搜索路径,classpath 指定了 java 类路径。
 24. Java 语言的各种数据类型之间提供了自动转换,如第一种操作数是 byte 类型,第二种操作数是 float 类型,结果是 float 类型。
 25. 在线程中普通优先级的线程,其优先级默认值为 5 。
 26. Java 程序包括原代码(.java 文件)、由便宜器生成的类(.class 文件)、由归档工具生成的jar(.jar 文件)、对象状态序列化(.ser)文件。
 27. Socket 是用来实现客户与服务器之间的用心,Java 在 Socket 中,提供多线程机制,对实现大量客户通信提供了很好的基础。
 28. Java 语言的各种数据类型之间提供了两种转换:自动转换、强制转换。
 29. 在长度为 n 的有序线性表中进行二分查找。最坏的情况下,需要的比较次数为 log2n 。
 30. Java 语言通过接口支持多重继承,使类具有更灵活的扩展性。
 31. 软件概要设计的主要任务就是软件结构设计。
 32. Java 是一个地方落程序语言,简单易学、利用了面向对象的技术基础,但又独立于硬件结构,具有移植性、健壮性、安全性、高性能。
 33. 整型数分整型常量和整型变量。
 34. 阻塞状态根据产生的原因可分为对象锁阻塞、等待阻塞和其他阻塞。
 35. 每个 Java 应用程序可以包含许多方法,但是必须只能有一个 main 方法。
 36. 线程是一个用户级的实体,线程结果驻留在用户空间中,能够被普通的相应级别方法直接访问。
 37. 过滤字节流输出都是 FilterOutputStream 抽象类的子类。
 38. 系统运行时,通过垃圾回收机制周期性地释放无用对象所使用的内存,完成对象的清除。
 39. 继承性主要情调子类在父类的基础上取长补短,而多态性主要强调的是类与类之间的传输。
 40. 在Java 语言中,所有的变量、常量、类、对象都是用标识符命名的。
 41. 在面向对象的程序设计中,类描述的是具有相似性质的一组对象。
 42. 在编执行 Java 的程序过程中需要用到一些工具,SUN 公司为我们提供了 JDK 工具,它主要包括:javac.exe、java.exe、javadoc.exe、javap.exe、jbd.exe。
 43. RaradomAccessFile 所实现的接口是 DataInput 和 DatOatput 接口。
 44. fina 属性是专门定义常值变量的保留字。
 45. Java 的类库具有跨平台的特点,保证了软件的可移植性。
 46. 模式/内模式映射为数据提供了物理数据独立性。
 47. 变量作用域是整个类。
 48. 对话框(Dialog)是 Windows 类的子类。
 49. Java 语言中,后缀名为 .java 的源代码文件编译后形成后缀名为 .class 的字节码软件。
 50. 设计报表时,将各种类型的文本和字段控件放在报表“设计”窗体中的各个区域内。
 51. 通常,将软件的产品从提出、实现、使用、维护到停止使用退役的过程称为软件的生命周期。
 52. Java 语言中 Ojbect 是所有类的根。
 53. 在 32 位计算机中,一个字长等于 4 个字节。
 54. 程序风格是只编写程序时所标写出的特点、习惯和逻辑思路等,遵循清晰第一、效率第二的原则。
 55. Java 语言使用 Unicode 字符集,它的字母包含:'A'-'Z','a'-'z'以及序号大于 0XC0 的所有符号。
 56. 字符串分为两大类,一类是字符串常量,使用 String 类的对象表示;另一类是字符串变量,使用 StringBuffer 类的对象表示。
 57. Java 可以跨平台的原因是因为有 Java 虚拟机。
 58. Java 中的字符串输出流都是抽象类外部命令的子类。
 59. 变量是程序中的基本储存单元之一,由变量名、变量类型、变量属性、变量初始值组成。
 60. 浮点型数据属于实型数据,分 float 和 double 两种类型。
 61. Java 语言的执行模式是半编译和半解释型。
 62. 抽象方法是一种有方法头、没有具体方法体和操作实现的方法,该方法必须在抽象类中定义。
 63. 定义初始值为 10 的 10 次方的长整形变量 var 的语句是 long var (long)le10;
 64. 计算机软件分为系统软件和应用软件,操作系统属于系统软件。
 65. 程序设计的表示方法可以分为图形、表格和语言三类。
 66. 类库主要包括核心 java 包、javax 包 和 org 扩展包。
 67. 数据库管理系统常见的数据模型有层次模型、网状模型和关系模型三种。
 68. E-mail 地址由用户名和域名两部分组成,这两部分的分隔符为 @。
 69. 关系代表数主要运算有并、交、差、选择、投影、笛卡儿积、自然连接、0连接和改名。
 70. Java 的产品主流操作系统平台是 Solaris、Windows 和 Macintosh 。
 71. Swing 的事件处理机制包括事件源、事件和事件处理者。
 72. 对于一个长度为 n 的线性表,用数组表示,假定删除表中任一元素的概率相同,则删除一个元素平均需要移动元素的个数是 (n-1)/2 。
 73. URL 是 Unform Resource Locator 的缩写。
 74. Java 程序的安全性体现在多个层次上,在编译层有语法检查;在解释层,有字节码校验器、测试代码段格式和规则检查,操作数堆栈的上溢或下溢,代码参数类型和法性等;在平台上,通过配置策略,可设定访问资源域,而无需区分本地或远程。
 75. 接口是一种只包含抽象方法或常量的一种特出抽象类。
 76. 在数据库设计中,把数据需求写成文档,它是各类数据描述的集合,包括数据项、数据结构、数据流、数据存储和数据加工过程等的描述,这通常称为数据字典。
 77. Java 有两类应用程序,Java Application 和 Java Applic。
 78. 数据结构分为逻辑结构与储存结构,线性链表属于存储结构。
 79. Java 解释器采用生成与体系结构无关的字节代码指令的技术,只需安装 Java 运行系统,就可保证 Java 程序 在网络的任何地方运行。
 80. 程序设计基本结构有顺序结构、选择结构、循环结构三种。
 81. 耦合和内聚是评价模块独立性的两个主要标准,其中内聚反映了模块内各成分之间的联系。
 82. Java 的体系结构中,最下层是移植接口、配置器、Java OS 组成,保证了 Java 体系结构可以跨平台。
 83. 设有整形数组的定义 int[] a = new int[8]; 则 a.lenglh 的值为 8 。
 84. 凡生成 StringBuffer 一个对象后,还可以用 setLenglh() 方法和 ensureCapaciy() 方法来设定缓存大小。
 85. Java Application 应用程序的编写和执行分三步进行:编写源代码、编译源代码、解释执行。
 86. 计算机硬件由运算器、控制器、储存器、输入设备、输出设备五大部件组成。
 87. 通常把用户的要求传变成软件产品的过程叫做软件开发过程。
 88. Java 的数据类型必须实例化后才能使用,他们通过变量或常量来实例化。
 89. 在面向对象方法中,类之间共享属性和操作的机制称为继承。
 90. 在 Windows 环境下,当进行复制操作时,其复制的内容将存放在剪贴板中。
 91. 变量类型有两大类,基本类型和复合类型。
 92. 一个项目具有一个项目主管,一个项目主管可管理多个项目,则实体“项目主管”与实体“项目”的关系属于一对多(1:N) 的联系。
 93. Java 语言提供了 byte、short、int、long 四种类型的整型变量。
 94. 异常对象异常和被传递提交给 Java 运行系统的过程称为抛出异常。
 95. J2ME 是为嵌入式和移动设备提供的 Java 平台,它的体系结构由 profiles、Configueation 和OpionalPachages 组成。
 96. 变量作用域是制访问变量的范围,局部变量在方法中声明,作用域是方法代码段。
 97. 若 x=5, y=10 则 x > y && x++ == y-- 的逻辑值为 False 。
 98. 关系代数中,运算的三要素是指运算对象、运算符和运算结果。
 99. 数据库设计分为以下六个设计阶段:需求分析阶段、数据库概念设计阶段、逻辑设计阶段、物理设计阶段、实施阶段、运行和维护阶段。
100. 从 Windows 环境进入 MS-DOS 方式后,返回 Windows 环境的 DOS 命令为 exit 。
101. 重复结构分为当型循环和直到型循环。
102. Java 语言没有无符号整数类型、指针类型、结构类型、枚举类型,这使得 Java 变成简单易学。
103. Java 语言用字节码进行解释执行。
104. log 类整型常量书写表示时,在数字的后面加 L 或 l 。
105. 当用户在 TextField 中输入一行文字后,按回车,实现 ActionListener 接口可实现对事件的响应。
106. Java 中任何数据类型的数据(包括基本类型和组合类型)都可以通过 == 或 != 运算符来比较是否相等。
107. 符点类型数据中,flat 类型具有占内存小、运算快的优点。
108. GregorianCalendar 日历类提供日期和时间的表示,它可以格里历(即阳历)来计算。
109. 自动类型转换允许在赋值和计算时由编译系统按照指定的优先次序自动完成。它门能将数位少的数据类型向数位多的数据类型转换。
110. 在 Java 语言中,如数字后没有字母,计算机默认为 deulde 类型。
111. 算术运算符的优先级按照下面次序排列 ++ 和 -- 的级别最高,然后是 * 和 / 以及 % 而 + 和 - 的级别最底。
112. 数组、堆栈、队列和链表都是线形数据结构。
113. Java 语言是 1995 年 5 月由 Sun World 大会上发布的。从此,这一新一代的网络计算机语言受到了广泛的青睐,很快就起了 Java 的热潮。
114. Java 是一种网络编程语言,它避免了许多其他编程语言的缺点,更好地利用了当前软件新技术,是一种新概念。
115. 数据的逻辑结构有线性结构和非线性结构两大类。
116. Java 语言中,boolean 型常量只有 true 和 false 两个值。
117. 如果子类中覆盖了父类中的同名方法,则在子类中调用父类中的同名方法时用关键字 super 在一个类的内部可以直接调用本类的对象,也可以通过关键字 this 来调用。
118. 如果子类中的某个方法名、返回值类型和参数表与它的父类中的某个方法完全一样,则称子类的这个方法覆盖了父类的同名方法。
119. Java Applet 应用程序的编写和执行共分为编写代码、编写 HTML 文件调用该小程序、编译过程和解释过程四步进行。
120. System 是一个特出类,他类似一个 final 类,所有的方法都用类变量来调用。
121. 构造方法是类中的一个特殊方法,用它来定义对象的初始状态。
122. 字符变量以 char 类型表示,它在内存中占用 16 位 Bit 。
123. 捕获异常的统一出口通过 finally 从句,因此对 catch 而言,无论由那个捕获异常,最后一定执行该句。
124. 每一个 applet 必须定义为 Applet 的字类。
125. CRC 技术的全称是 CyclicRedundancyCheck 。
126. 按照线程模型,一个具体的线程也是由虚拟的 CPU、代码与数据组成,其中代码与数据构成了线程体,线程的行为由它决定。
127. Java 类库提供的 Applet 类是所有 Applet 程序根。
128. 顺序存储方法是把逻辑上相邻的结点储存到物理位置相邻的单元中。
129. 国际化命令只包含一个命令 native2ascii 该命令将包含有本地编码符的文件转换为 Unicode 编码符的文件。
130. 若 a, b 为 int 型变量且以分别赋值为 2,6 则表达式 (a++) + (++b) + a * b 的值是 (2 + 7) + 3 * 7 = 30。
131. Java 提供的类库支持 TCP/IP 协议,应用程序通过 URL 地址,在访问网络上任何地方的对象时,如同访问本地文件一样简单。
132. 在 Java 语言中提供的四种整形变量中,Byte 类型表示的数字范围最小。
133. Java 中新建的线程调用 start() 方法,如 mythread.start() 将使线程的状态从“新建状态”(new)转换为“可运行状态”。
134. Java 是区分大小写的。源文件名与程序文件名必须相同,其中扩展名为 .java 源文件中最多只有一个 public 类,其他类的个数不限。
135. 在一个类的内部,潜套定义的类称为内部类。
136. Java 的符合数据类型有:类、数组、变量。
137. E/R 图可以直接转换关系,其每个属性都对应于关系中的一个属性;E/R 图的联系转换为关系时,其属性由两部分组成:关于联系有关的键码属性(集):该联系本身的属性。。
138. 设 a = 8 则表达式 a>>>2 的值是 2 。
139. 标识符是以英文、下划线(_)、美圆符($)作为首字母的字符序列。
140. 软件可维护性度量的七个质量特征性是可理解性、可测试性、可修改性、可靠性、可移植性、可使用性和效率。
141. Java 设计有自动回收垃圾功能,这不仅防止了内存地址计算错误的问题,也省去了变成时对内存进行分配的烦恼。
142. Java 中访问限定符有 public、protected、private、default 等。
143. 数据型包括简单的数据类型和复合数据类型。简单数据类型有包含数值类型、字符类型、布尔类型三大类。
144. 创建一个名为 MyPackage 的包的语句是 Package MyPackage;
145. Java 本身的编译器与 Java 语言编写,运行系统的虚拟机用 C 语言实现,这样系统本身也具有可移植性。
146. 一个类可以直接过间接的祖先中继承所有属性和方法。采用这个方法提高了软件的可重用性。
147. 给 float 型的变量赋值时,要在数字后面填加 F 或 f 。
148. 我们在Java 程序中把关键字 super 加到方法名称的面前,来实现子类调用父类的方法。
149. 数据库管理的常见数据模型有层壮、网状、和关系三种。
150. class 类是由编译器自动生成对象的一个特出类,它伴随每个类。
151. 关系操作的特点是集合操作。
152. 变量属性是描述变量的作用域,按作用域分类,变量有局部变量、类变量、方法参数和异常处理参数。
153. Java 语言通过接口支持多重继承,使类继承具有更灵活的扩展性。
154. Java 源文程序文件编译后产生的文件被称为字节码文件,其扩展名为 .class 。
155. 软件工程研究的内容主要包含:软件开发技术和软件工程管理。
156. 抽象类不能实例化。
157. 字符常量是用单引号括起来的一个字符,用双引号括起来的是字符串。
158. 在 Java 的基本数据类型中,char 型采用 Unicode 编码方案,每个 Unicode 码占用 2 自己的内存空间。
159. Applet 是 Java 的一类特殊应用程序,它嵌入 HTML 中,随主页发布到因特网上。
160. Java 源代码文件夹中,可以有 0 或 N 个 import 语句。
161. JDBO 的类都被汇集在 Java.SQL 包中,在安装 JavaJDK1.1 或更高版本时会自动安装。
162. Java 语言不允许使用指针访问内存,更不允许使用指针数组访问内存。
163. setLayout() 方法是所有容器的父类 Container 的方法。
164. 定义布尔型变量的的关键字是 nicode 。
165. Thread 类是提供线程操作管理的类。
166. 字符变量以 char 类型表示,它在内存中占 16 个 bit 。
167. 计算机网络分为局域网、城域网和广域网,因特网属于广域网。
168. 程序中使用了字符串函数(如strlen),则必须包含头文件名为 String.h 。
169. 对象是一组相关变量和相关方法的封装体,是类的一个实体例。
170. Java 编写好的程序首先由编译器转换为标准字节代码,然后由 Java 虚拟机去解释执行。
171. 布尔数据一般用于逻辑判断在流程中常用。[sub][/sub]
172. 微机中 ROM 的中文意义是只读存储器。
173. 在 Java 语言中,将后缀名为 .java 的源代码文件编译后形成后缀名为 .class 的字节码文件。
174. 如果容器采用 BorderLayout 进行布局管理,在 add() 方法添加构件的时候,必须注明添加到那个位置。
175. Java 的体系结构中,最下层是移植接口,最上层是 Java 应用程序 和 Applet 小程序。
176. 八进制整数 012 表示十进制 10 。
177. Java 程序中定义接口所使用的关键字是 interface 。
178. 字符常量中,\' 表示单撇号字符,\t 表示横向跳格。
179. 下面的语句生命一个常量并被赋值:
     Boolean b1=5!=8
     B1 的值是 True 。




  1.  下面分别用 while、do-while 和 for 语句时间 1 至 10 累计求和。请在横线处填入适当的内容完成程序。
     public class Sun {
         public stasic void main(String[] args[]) {
             System.out.println("\\n**** while 循环 ****");
             int n = 10, sum = 0;
             while(n > 0) {
                 sun += n;
                 n--;
             }
             System.out.println("sum is" + sum);
             System.out.println("\\n**** do-while 循环 ****");
             n = 0; sum = 0;
             do {
                 sum += n;
                 n++;
             } while(0 >= n);
             System.out.println("sum is" + sum);
             System.out.println("\\n**** for 循环 ****");
             n = 1; sum = 0;
             for(; 10 >= n; n++) {
                 sum += i;
             }
             System.out.println("sum is" + sum);
         }
     }
  2. 执行以下程序段后:a = 6,b=8 。
     int a = 5, b;
     b = ++a *3;
  3. 下面是一个类定义,请将程序补充完整。
     import java.awt.*;
     impott java.applet.*;
     public class myprogram extends Apple }//定义小程序的主类
         Label p1;
         TextField in;
         public void init() {
             p1 = new label("请输入一个整数");
             add(p1);
             in = new TextField(8);
             add(in)
         }
     }
  4. 下列程序输出的结果是 m = 0 。
     class Test {
         public static void main(String args[]) {
             int m = 6;
             do {
                 m--;
             } while (m > 0);
             System.out.println("m=" + m);
         }
     }
  5. 下面是用户程序对 Applet 类中方法 paint() 的重新定义。根据程序功能,在指定的空白处填上适当的语句或语法成分。
     public void paint(Graphics g) {
         g.DrawString("你好!", 10, 20);
     }
  6. 请在下划线处编写适当的语句,完成此程序使它能正确的执行。
     import java.io.*;
     public class LeapYear {
         public staic void main(Strng arge[]) throws IOException {
             InputStreamReader ir;
             BufferedReader in;
             System.out.pringln("输入年份是:");
             Sting s = in.readLine();
             int year = Integer.parseInt(s);
             if (year % 4 == 0 && year % 100 != 0 ||year % 400 == 0) {
                 System.out.println("" + year + "年是闰年");
             } else {
                 System.out.println("" + year + "年不是闰年");
             }
         }
     }
  7. 下面是用:
         RandomAccessFile oureFile;
         String s = "information to Append\n mon!\n";
         oureFile = new RandomAccessFile oureFile("phone.number.numbers", "rw");
     模式打开访问 oureFile 文件,并将在文件末尾加信息 s 的 addFile 的源程序。请在下划线添上合适的语句程序补充完整。
     import java.io.*
     class addFile {
         public staic void main(String args[]) throws IOException {
             RandomAccessFile oureFile;
             String s = "information to Append\n mon!\n";
             oureFile = new RandomAccessFile oureFile("phone.number.numbers", "rw");
             oureFile.writebytes(s);
             oureFile.close();
         }
     }
  8. 以下程序的输出结果为 Message four 。
     int x=0, y=4, z=5;
     if (x > 2) {
         if (5 > y) {
             System.out.println("Message one");
         } else {
             System.out.println("Message tow");
         }
     } else if(z > 5) {
         System.out.println("Message three");
     } else {
         System.out.println("Message four");
     }
  9. 下面是一个类的定义,根据程序功能,在指定的空白处填上适当的语句或语法成分,使程序完整。
     Class myclass {//定义名为 myclass 的类
         static int var = 666;
         static int get var() {
             return var;
         }
     }
 10. 下出下面程序的运算结果 Hollo!World! 。
     impor java.io.*
     public class abc {
         public static void main(String args[]) {
             String s1 = "Hello!";
             String s2 = new String("World!");
             System.out.pringln(s1.concat(s2));
         }
     }
 11. 下列程序运行的结果是 HELLO! 。
     import java.io.*;
     public class UpperCase {
         public static void main(String[] args) {
             String s1 = "Hello!";
             System.out.println(s1.toUpperCase());
         }
     }
 12. 阅读以下程序,输出结果为 21 。
     class D {
         public static void main(System args[]) {
             int d = 21;
             Dec dec = new Dec();
             dec.decrement(d);
             System.out.println(d);
         }
     }
     class Dec {
         public void decrement(int b) {
             b = b - 1;
         }
     }
 13. 下面是拥护程序对 Applet 类中的方法 action() 的重新定义,功能为从单行文本编辑区 input 中输入数据赋给 k。TextField 类的对象 input 和 int 型 变量 K 已在类体中正确说明。
     public nicode action(Event e, Object o) {
         if (e.target == input) {
             k = Integer.parseInt(input.getText());
         }
         repaint();
         return true;
     }
 14. 下面是一个 Java 应用程序(Application),它的功能是在屏幕上输出26个英文字母,其中每个字母间隔一个制表符,请完成该程序。
     public class Calss1 {
         public static void main(String args[]) {
             char c = 'a';
             for (int i = 1; i <= 26; i++) {
                 System.out.print("\t" + (C++));
             }
         }
     }
 15. 下列程序实现从控制台输入并读取输出字符串。请将程序补充完整。
     import java.io.*;
     public class CharInput {
         public static void main(String[] args) throws java.io.IOException {
             String s;
             InputStreamReader ir;
             BufferedReader in;
             ir = new InputStreamReader(System.in);
             in = new BufferedReader(ir);
             while((s = in.readLine()) != null) {
                 System.out.println("Read:" + s);
             }
         }
     }
 16. 下面程序的运行结果是 110 110 110 110 110 。
     import java.io.*;
     public class ABC {
     public static void main(String[] args) {
         int i;
         int[] a = {11, 22, 33, 44, 55, 66, 77, 88, 99};
         for(i = 0; i<=a.length / 2; i++)
             System.out.print(a[i] + a[a.length - i - 1] + " ");
             System.out.println();
         }
     }
 17. 下面是打印出所有和为 1000 的连续整数(如:298,299,300,301,302 等)的程序,请在下划线处编写适当 的语句,完成此程序使他能正确运行。
     public class Exercise42 {
         public static void main(String[] arges) {
             int i;//连续整数起点
             int j;//连续整数终点
             int k;//循环记数用
             int sum;//计算连续整数集合
             for(i = 1; i <= 1000; i++) {
                 j = sum = i;
                 while(sum <= 1000) {
                     sum += ++j;//Sum 为若干个连续整数之和
                     if(sum == 1000) {
                         for(k = i; k <= j; k++)
                             System.out.print(k + ",");
                         System.out.println();
                     }
                 }
             }
         }
     }
 18. 阅读以下程序,请写出结果 True 。
     public class EqualsMethod{
         public static void main(System args[]) {
             Integer n1 = new Integer(47);
             Integer n2 = new Integer(47);
             System.out.println(n1.equals(n2));
         }
     }
 19. 设有数组定义:int MyIntArray[] = {10, 20, 30, 40, 50, 60, 70}; 则执行以下语句后输出的记过是 280 。
     int s = 0;
     for(int i = 0; s.length > i; i++) {
         s += MyIntArray[i];
     }
     System.out.println(s);
 20. 设有数组定义:int a[] = {11, 22, 33, 44, 55, 66, 77, 88, 99}; 则执行下列几个语句后输出的结果是 33 66 99 。
     for(int i=0; a.length > i; i++) {
     if (a[i] % 3 == 0) {
         System.out.println(a[i] + " ");
     }
 21. 阅读下列程序,输出结果为 Hello!I lik Java! 。
     import java.io.*
     public class abc {
         public ststic void main(String args[]) {
             String s1 = "Hello!";
             String s2 = new String("I like Java!");
             System.out.println(s1 + "" + s2);
         }
     }
 22. 以下程序输出 结果为:Boy 。
     public class Short{
         Public static void main(String[] args) {
             String Buffer s = new StringBuffer("Boy");
             if ((s.length()<3) && (s.appeng("男孩").equals("False")));
                 System.out.println("结果为:"+s)
         }
     }
 23. 下列程序段输出的结果为 Value is 2.Velue is 3. 。
     int a = 2;
     switch(a) {
         case 2:
             System.out.print("Value is 2.");
         case 3:
             System.out.println("Value is 3.");
             break;
         default:
             System.out.plintln("end");
     }


               好久以前感觉房东儿子的表哥开的落伍者论坛好像很不好的感觉,好像很落后似的,直到欧有一天在谈到关于PHP技术的时候,流年他说还没有入伍,何来落伍,才发现原来落伍也是高手的必经之地啊,我们还没有落伍,永远也没有落伍,因为我们还没有入伍,^_^。。。。

毛泽东语录 绝对经典

毛泽东语录 绝对经典

1★上学太累★  
 
要允许学生上课看小说,要允许学生上课打磕睡,要爱护学生身体。教员要少讲,要让学生多看。我看你讲的这个学生,将来可能有所做为。他就敢星期六不参加会议,也敢星期日不按时返校。回去以後,你就告诉这学生,八、九点钟回校还太早,可以十一点、十二点再回去。【和王海蓉同志的谈话 1964、6、4)】 
  
2★不要考试★   

不要考试,考试干什么?一样不考才好呢!对于考试一概废除,搞个绝对化。【招见首都红代会负责人的谈话 (1968年7月28日)】


 
3★要考试就这样考★   
考试可以交头接耳,甚至冒名顶替。冒名顶替的也不过是照人家的抄一遍,我不会,你写了,我抄一遍,也可以有些心得。可以试点,要搞得活一些,不要搞得太死。【春节谈话纪要(1964年2月13日),《...思想万岁》一九六九年八月版第 460页。】
  
4★没办法就交白卷★   

从前我在学校里是不守规榘的,只是以不开除为原则的。考试嘛,五、六十分以上,八十分以下,七十分为准。好几门学科我是不搞的,要搞有时没办法,有的考试我就交白卷,考几何我就画一个鸡蛋,这不是几何吗?因为是一笔,交卷最快。【召见首都红代会负责人的谈话(1968年7月28日)】
 
5★武斗好★   

武斗有两个好处,第一是打了仗有作战经验,第二个好处是暴露了坏人。┅┅再斗十年,地球照样转动,天也不会掉下来。【召见首都红代会负责人的谈话(1968年7月28日)】
    
6★打起来我就高兴★ 
  
我才不怕打,一听打仗我就高兴,北京算什么打?无非冷兵器,开了几枪。四川才算打,双方都有几万人,有枪有炮,听说还有无线电。【召见首都红代会负责人的谈话(1968年7月2日)】
     
7★打仗靠流氓★ 
  
勇敢分子也要利用一下嘛!我们开始打仗,靠那些流氓分子,他们不怕死。有一个时期军队要清洗流氓分子,我就不赞成。【中央工作座谈会纪要(1964年12月2日)】
    
8★绿林大学毕业★   
去搞阶级斗争,那是大学,可以学到很多东西。什么“北大”“人大”,还是那个大学好!我就是绿林大学的,在那里学了点东西。【关于哲学问题的讲话(1964年8月18日),《...思想万岁》一九六九年八月版第549页。】
  
9★没有就去抢★   

有一回哥老会抢了我家,我说,抢得好,人家没有嘛【关于哲学问题的讲话 1964.8.18】
       
10★阶级斗争★   

《红楼梦》我看了五遍,也没有受影响,我是把它当历史读的┅ ┅《红楼梦》里阶级斗争很激烈,有好几十条人命。【关于哲学问题的讲话1964、8、18】
  
11★登报我就走★   
假如办十件事,九件是坏的,都登在报上,一定灭亡。那我就走,到农村去,率领农民推翻政府,你解放军不跟我走,我就找红军去。【在庐山会议上的讲话(1959年7月23日)】
 
12★超过秦始皇★   

秦始皇算什么?他只坑了四百六十个儒,我们坑了四万六千个儒。我们镇反,还没有杀掉一些反革命的知识分子吗?我与民主人士辨论过,你骂我们秦始皇,不对,我们超过秦始皇一百倍。骂我们是秦始皇,是獨裁者,我们一贯承认;可惜的是,你们说得不够,往往要我们加以补充(大笑)。【在八大二次会议上的讲话 1958、5、8】
  
13★学文科的最差★   

中国知识分子有几种。工程技术人员接受社会主义要好一些。学理科的其次。学文科的最差。【关于板田文章的谈话 1964、8、24】

14★操娘★    
 
一九五九年第一次庐山会议本来是搞工作的,后来出了彭德怀,说你操了我四十天娘, 让我***x二十天行不行?这一操,就被搅乱了,工作受到影响。【在八届十中全会上的讲(1962年9月24日),《...思想万岁》 一九六九年?月版,第435页。】

15★皇军★   

我曾经跟日本朋友谈过。他们说,很对不起,日本皇军侵略了中国。我说∶不!没有你们皇军侵略大半个中国,中国人民就不能团结起来对付你们,中国共产党就夺取不了政权!【接见日本社会党人士佐佐木更三、黑田寿男、细迫兼光等的谈话1964、7、10】
16★屁股★   

国民经济的两个拳头,一个屁股。基础工业是一个拳头,国防工业是一个拳头,农业是屁股┅┅稳产高产是相对的,去年河北大雨是老天爷下的,没有办法。天老爷真难当,下多了不是,下少了也不是。【在计委领导小组汇报时的一些插话1964、5、11】
    
17★屁有香臭★    
  
屁有香臭,不能说苏联的屁都是香的。现在人家说臭,我们也跟着说臭。凡是适用的都要学,资本主义好的也应该学。【在中央政治局扩大会议上的讲话(一九五***月),《毛泽东思想万岁》1969 年8月版,第三十七页。】    
事前要有准备,小会他神气大,大会他没办法。你要大民主,我就照你的办,有屁让他放,不放对我不利,放出来大家鉴别香臭。【在省、市委书记会议上的插话--汇集(1957年1月),《...思想万岁》一九六九年八月版,第75页。】   
上边放的屁不全是香的,这里也有对立,有香也有臭,一定要嗅一嗅。【在省、市委书记会议上的插话(1957年1月)【...思想万岁】一九六九年八月版)
     
18★拉屎拉尿★   

人同自然界作斗争,也有交换。如人吃东西,吸空气,但要拉屎拉尿,新陈代谢。┅┅大鱼吃小鱼,小鱼吃大鱼的屎。重工业各部门之间也要等价换,远陆造机器要原料,就是粮食,机器就是他拉的屎。【在郑州会议上的讲话(1959年3月五日),《毛泽东思想万岁》1967年版, 第42页。】
     同志们,自己的责任都要分析一下,有屎拉出来,有屁放出来,肚子就舒服了。【在庐山会议上的讲话(1959年7月23日),《...思想万岁》一九六九年八月版,第305页。】

1、如何混合使用Jsp和SSI #include?
在JSP中可以使用如下方式包含纯HTML:

但是如果data.inc中包含JSP CODE ,我们可以使用:
<%@include file="data.inc"%>


2、如何执行一个线程安全的JSP?
只需增加如下指令
<%@ page isThreadSafe="false" %>


3、JSP如何处理HTML FORM中的数据?
通过内置的request对象即可,如下:
<%
String item = request.getParameter("item");
int howMany = new Integer(request.getParameter("units")).intValue();
%>


4、在JSP如何包含一个静态文件?
静态包含如下:<%@ include file="copyright.html" %>
动态包含如下:


5、在JSP中如何使用注释?
主要有四中方法:
1。<%-- 与 --%>
2。//
3。/**与**/
4。


6、在JSP中如何执行浏览重定向?
使用如下方式即可:response.sendRedirect("http://ybwen.home.chinaren.com/index.html");
也能物理地改变HTTP HEADER属性,如下:
<%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
String newLocn="/newpath/index.html";
response.setHeader("Location",newLocn);
%>


7、如何防止在JSP或SERVLET中的输出不被BROWSER保存在CACHE中?
把如下脚本加入到JSP文件的开始即可:
<%
response.setHeader("Cache-Control","no-store"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>


8、在JSP中如何设置COOKIE?
COOKIE是作为HTTP HEADER的一部分被发送的,如下方法即可设置:
<%
Cookie mycookie = new Cookie("aName","aValue");
response.addCookie(mycookie);
%>


9、在JSP中如何删除一个COOKIE?
<%
Cookie killMyCookie = new Cookie("mycookie", null);
killMyCookie.setMaxAge(0);
killMyCookie.setPath("/");
response.addCookie(killMyCookie);
%>


10、在一个JSP的请求处理中如何停止JSP的执行
如下例:
<%
if (request.getParameter("wen") != null) {
// do something
} else {
return;
}
%>


11、在JSP中如何定义方法
你可以定义方法,但是你不能直接访问JSP的内置对象,而是通过参数的方法传递。如下:
<%!
public String howBadFrom(HttpServletRequest req) {
HttpSession ses = req.getSession();
...
return req.getRemoteHost();
}
%>
<%
out.print("in general,lao lee is not baddie ");
%>
<%= howBadFrom(request) %>


12、如果BROWSER已关闭了COOKIES,在JSP中我如何打开SESSION来跟踪
使用URL重写即可,如下:
hello1.jsp
<%@ page session="true" %>
<%
Integer num = new Integer(100);
session.putValue("num",num);
String url =response.encodeURL("hello2.jsp");
%>
>hello2.jsp

hello2.jsp
<%@ page session="true" %>
<%
Integer i= (Integer )session.getValue("num");
out.println("Num value in session is "+i.intValue());
%>


13、在JSP中能发送EMAIL吗
可以使用SUN的专用包:sun.net.smtp包。如下脚本使用SmtpClient类发送EMAIL。
<%@ page import="sun.net.smtp.SmtpClient, java.io.*" %>
<%
String from="ybwen@sina.com";
String to="hewenjun@yeah.net, lei@who.com.cn";
try{
SmtpClient client = new SmtpClient("mail.xxxxx.xxx");
client.from(from);
client.to(to);
PrintStream message = client.startMessage();
message.println("To: " + to);
message.println("Subject: Sending email from JSP!");
message.println("This was sent from a JSP page!");
message.println();
message.println("Cool! :-)");
message.println();
message.println("Good Boy");
message.println("Im in genius.com");
message.println();
client.closeServer();
}
catch (IOException e){
System.out.println("ERROR SENDING EMAIL:"+e);
}
%>


14、在SERVLET中我能调用一个JSP错误页吗
当然没问题,如下展示了如何在一个SERVLET控制逻辑单元内调用一个JSP错误页面。
protected void sendErrorRedirect(HttpServletRequest request,
HttpServletResponse response, String errorPageURL,
Throwable e)
throws ServletException, IOException {
request.setAttribute ("javax.servlet.jsp.jspException", e);
getServletConfig().getServletContext().
getRequestDispatcher(errorPageURL).forward(request,
response);
}

public void doPost(HttpServletRequest request,HttpServletResponse response) {
try {
// do something
} catch (Exception ex) {
try {
sendErrorRedirect(request,response,"/jsp/MyErrorPage.jsp",ex);
} catch (Exception e) {
e.printStackTrace();
}
}
}


15、JSP和APPLET如何通讯
JSP如何与EJB SessionBean通讯
下面的代码段作了很好的示范
<%@ page import="javax.naming.*, javax.rmi.PortableRemoteObject,
foo.AccountHome, foo.Account" %>
<%!
//定义一个对SessionBeanHome接口实例的全局引用
AccountHome accHome=null;

public void jspInit() {
//获得Home接口实例
InitialContext cntxt = new InitialContext( );
Object ref= cntxt.lookup("java:comp/env/ejb/AccountEJB");
accHome = (AccountHome)PortableRemoteObject.narrow(ref,AccountHome.class);
}
%>
<%
//实例化SessionBean
Account acct = accHome.create();
//调用远程方法
acct.doWhatever(...);
// 如此等等
%>


16、当我使用一个结果集时,如何防止字段为"null"的字域显示在我的HTML输入文本域中?
可以定义一个简单的函数来达到目的,如下:
<%!
String blanknull(String s) {
return (s == null) ? "" : s;
}
%>

然后在JSP的FORM中,可以这样使用



17、如何中SERVLET或JSP下载一个文件(如:binary,text,executable)?
现提供两个解决方案:
A:使用HTTP,
B:在Servlet中,通过设置ContentType和使用java.io包的Stream等类可作到.例如:
response.setContentType("application/x-msword");
然后想输出缓冲中写一些东东即可。

18、使用useBean标志初始化BEAN时如何接受初始化参数
使用如下两标签即可:



19、使用JSP如何获得客户浏览器的信息?
使用request.getHeader(String)即可


20、能象调用子程序一样调用JSP吗?
当然可以,用


21、当我重编译我的JSP使用的一个类后,为什么JVM继续使用我的老CLASS?


<%@include file="abc.jsp"%>与之间的差别?
前一个为静态包含,而后一个为动态包含


22、JSP的缺点?
1。对JAVA程序进行调试没有好东东
2。因大多数的servlet引擎不支持connection pooling
3。Servlet引擎没有标准
4。JSP与其它脚本语言的交互


23、JSP能进行递归调用吗?
当然可以,如对form的提交给本页


34、如何实现JSP的国际化?
为各种版本提供resource bundles属性文件即可

25、在JSP中如何写文本文件?
使用PrintWriter对象,如:
<%@ page import="java.io.*" %>
<%
String str = "print me";
String nameOfTextFile = "/usr/anil/imp.txt";
try {
PrintWriter pw = new PrintWriter(new FileOutputStream(nameOfTextFile));
pw.println(str);
pw.close();
} catch(IOException e) {
out.println(e.getMessage());
}
%>


26、如何在JSP中包括绝对路径文件?
使用URLConnection即可。


27、在servlets和JSP之间能共享session对象吗?
当然可以,
HttpSession session = request.getSession(true);
session.putValue("variable","value");


28、JavaScript的变量能复制到JSP的SESSION中吗?


29、如何设置cookie在某一时间后过期?
用Cookie.setMaxAge(int)


30、如何获得当前的sessions数?
可以使用HttpSessionBindingListeners来跟踪


31、能设置一些代码在我所有的JSP文件之上运行?如果可以,能共享吗?
当然可以,可以为你的JSP文件定义一个别名:/jsp/=ybwen.genius.myPreprocessingServlet,而以/jsp/为前缀的文件可以使用


32、对一个JSP页,如果多个客户端同时请求它,同步可能吗?
在jsp:useBean语法中使用beanName有何好处?
beanName使用Beans.instantiate()初始化Bean


33、当我使用时,在浏览器的地址栏没有改变?
使用response.sendRedirect("newURL")


34、如何转换JSP 0.9版本的文件到JSP1.1?
可使用sed/awk即可


35、使用JSP能设置HTML FORM中输入域的焦点,不用JavaScript?
没办法


36、使用JSP连接到数据库连接缓冲池的最好方法是什么?
1.使用JDBC2。0中带有此服务的Driver
2.使用提供有此服务的Application server
3.自己写

     本人很穷没有什么东西,就是放了几本书在电脑旁边,没有想到有人喜欢,感觉是我的fans,每次都要来翻看本人觉得也没什么啊,他们公司可能也要用到,但是:
   本人电脑的垃圾片也给拷走了,难道也是相同原因吗?请不要盲目崇拜,谢谢。。。。
         感觉好像有些疲倦,在记忆力上好下功能有些减弱,还有就是法学的理论方面好像也是记忆的东西,不是和那个理科一样要推理,感觉很让人那有些零碎的感觉。
     保持睡眠时间,要做到睡眠充足,精神才好。。。。
     在弱的思维条件下,我的思维就像一匹脱缰之野马,必须要控制好思考。
     最后没有几天了,加油。。。。。smile

点击在新窗口中浏览此图片

一个鸡蛋去茶馆喝茶,结果它变成了茶叶蛋;
一个鸡蛋跑去松花江游泳,结果它变成了松花蛋;
一个鸡蛋跑到了山东,结果它变成了鲁(卤)蛋;
一个鸡蛋无家可归,结果它变成了野鸡蛋;
一个鸡蛋在路上不小心摔了一跤,倒在地上,结果它变成了导弹;
一个鸡蛋跑到人家院子里去了,结果它变成了原子弹;
一个鸡蛋跑到青藏高原,结果它变成了氢弹;
一个鸡蛋生病了,结果它变成了坏蛋;
一个鸡蛋嫁人了,结果它变成了混蛋;
一个鸡蛋跑到河里游泳,结果它变成了核弹;
一个鸡蛋跑到花丛中去了,结果它变成了花旦;
一个鸡蛋骑着一匹马,拿着一把刀,原来它是刀马旦;
一个鸡蛋滚来滚去,越滚越圆,结果就变成了圆蛋--元旦快乐  

滚动条颜色生成器 IE5.5+


[/url]
[url=http://www.lanyueer.com/wyzz/color.htm]

[url=http://www.lanyueer.com/wyzz/chuangkou.htm][/url]
分页: 316/339 第一页 上页 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 下页 最后页 [ 显示模式: 摘要 | 列表 ]