炽翼铁冰's Blog

Trying to become a programmer

C语言 fgets函数用法

fgets (buf, size, fp)
其行为方式如下:
(1)遇到换行或文件结束EOF则返回。
(2)按行读取。
(3)每一行结束处的换行字符‘\n’也算该行字符。
(4)对于大小为size的buf,最多只读取size-1个字符。
(5)自动地把buf中最后一个字符(通常是换行符)的后面一个字节填充零结束符('\0')。

因此如果想把buf中的换行符去掉,可以这样:buf[strlen(buf)-1] = '\0';当前前提是buf足够大,可以容纳完整的一行(包括最后的那个换行符)。

fputs (str, fp)
(1)把str中零结束符之前的全部文字输入到文件中。
(2)输入完成后,不会增加额外的特殊字符,如换行符等。

如果想输入完str后,就换行,则应该在上述调用后,再调用fputc('\n',fp);才行。

转自:http://www1.qcxy.hb.cn/dxx/blog/u/zhangtao/archives/2008/546.html

PL/SQL Developer调试存储过程步骤(转)

一、定位你的procedure
1。在屏幕左边的对象浏览器中展开procedure
2。找到你的procedure

二、打开测试窗口
1。在你的procedure上点击右键
2。在弹出的菜单中选择test
3。PL/SQL Devoloper就会打开一个测试窗口并自动生成一个调用块
4。在测试窗口的下方输入你的procedure的入口参数

三、打开编辑窗口
1。在你的procedure上点击右键
2。在弹出的菜单中选择edit
3。PL/SQL Devoloper就会打开编辑窗口
4。在需要的地方设置断点

四、开始调试
1。回到调试窗口
2。打开debug菜单,你就会看见start项已经可以用了,点击它
3。接下来就可以用调试窗口上的按钮进行单步跟踪

所有的参数,不管是数字类型,还是字符类型,均不要加引号

Eclipse和VI结合

Eclipse的External Tool能完成我想要的一切。在某个视图中选中需要编辑的文件(或文件包含的类,方法,等)之后,只要单击设置好的vim外部工具,Vim就会被启动并打开相应的文件。在Eclipse中建立这个外部工具的过程非常简单,如下简单的配置即可:


  open external tool dialog下创建program:
 

           name    :  vim
           location : vim路径
           working directory:  ${project_loc}
           arguments:  -p --remote-tab-silent ${resource_loc}


        
       p.s. -p --remote-tab-silent ${resource_loc} 这是打开一个新的标签页,而不是一个新的vim进程。

原文:http://www.blogjava.net/luedipiaofeng/archive/2009/12/01/304340.html

C字符数组赋值

举例如下:

char a[10];
1、定义的时候直接用字符串赋值
char a[10]="hello";
注意:不能先定义再给它赋值,如
 char a[10];
 a[10]="hello";
这样是错误的!

2、对数组中字符逐个赋值
char a[10]={'h','e','l','l','o'};

3、利用strcpy
char a[10];
strcpy(a, "hello");

易错情况:
1、char a[10]; a[10]="hello";//一个字符怎么能容纳一个字符串?况且a[10]也是不存在的!
2、char a[10]; a="hello";//这种情况容易出现,a虽然是指针,但是它已经指向在堆栈中分配的10个字符空间,现在这个情况a又指向数据区中的hello常量,这里的指针a出现混乱,不允许!

还有:不能使用关系运算符“==”来比较两个字符串,只能用strcmp() 函数来处理。


C语言的运算符根本无法操作字符串。在C语言中把字符串当作数组来处理,因此,对字符串的限制方式和对数组的一样,特别是,它们都不能用C语言的运算符进行复制和比较操作。直接尝试对字符串进行复制或比较操作会失败。例如,假定str1和str2有如下声明:

char str1[10], str2[10];

利用=运算符来把字符串复制到字符数组中是不可能的:

str1 = "abc";     /*** WRONG ***/

str2 = str1;       /*** WRONG ***/

C语言把这些语句解释为一个指针与另一个指针之间的(非法的)赋值运算。但是,使用=初始化字符数组是合法的:

char str1[10] = "abc";

这是因为在声明中,=不是赋值运算符。

试图使用关系运算符或判等运算符来比较字符串是合法的,但不会产生预期的结果:

if (str1==str2) ...    /*** WRONG ***/

这条语句把str1和str2作为指针来进行比较,而不是比较两个数组的内容。因为str1和str2有不同的地址,所以表达式str1 == str2的值一定为0。

 

动态SQL语句写法

一、下面的这段动态SQl代码只是对从数据库中表中取得固定个数的字段的时候加以使用:

int TestTabPre()
{
 
   EXEC SQL BEGIN DECLARE SECTION;
     int      countFlag;
     VARCHAR  dynstmt[5000];
     char     SubSQL [5000];   
     char     A_char[100];
  EXEC SQL END DECLARE SECTION;

    memset(SubSQL,0,sizeof(SubSQL));
   
   
    /*动态SQL的生成*/   
    strcpy(SubSQL,"SELECT ");
    strcat(SubSQL," A");
    strcat(SubSQL," FROM  TBL_WKKTDAYKEIREKI");
    strcat(SubSQL,"   WHERE    NO = '");
    strcat(SubSQL,"020316");
    strcat(SubSQL,"'");

    /*动态SQL的在数据库中解析*/   
     strcpy((char *)dynstmt.arr,SubSQL);
     dynstmt.len = (unsigned short)strlen((char *)dynstmt.arr);
     EXEC SQL  PREPARE S FROM :dynstmt;
     EXEC SQL  DECLARE CC CURSOR FOR S;

    /*动态SQL的在游标的打开*/   
     EXEC SQL  OPEN CC ;
     if(sqlca.sqlcode != 0)
     {   
        /*游标的打开ERROR*/
     return -1;
     }
     for(;;)
     {
        memset(A_char,0,sizeof(A_char));
        EXEC SQL FETCH CC INTO :A_char;
        if(sqlca.sqlcode ==0 )
        {   
             /*游标的打开成功*/
                ...
             
        }
        else if(sqlca.sqlcode ==1403)
        {
            /*游标的打开完毕*/
            break;
        }
        else
        {
            /*游标fetch中出现ERROR*/
           EXEC SQL  CLOSE CC ;
           return -1;
        }

   }  /*end for*/
   
    EXEC SQL  CLOSE CC ;
    return 0;
 
}

二、对于从数据库一个表中取得不固定的字段,并且这些字段的数据类型也不明确时,就要使用数据库(Oracle)自带结构体来解决。
 

 

EXEC SQL INCLUDE sqlda;
SQLDA * select_dp;

int DbOperate(char * sql,char * id, char * name)
{
    EXEC SQL BEGIN DECLARE SECTION;
        VARCHAR  dynstmt[5000];
        char     SubSQL [5000];   
        EXEC SQL VAR SubSQL IS STRING(5000);
    EXEC SQL END DECLARE SECTION;

    char  strid[6];
   
    int i,null_ok,precision,scale;
    char foruda[100];
 
   
    memset(strid,0,sizeof(strid));
    memset(foruda,0,sizeof(foruda));

 
    /* if (access(KARI_FILE_PATH,0) != 0)
     {     
        sprintf(foruda,"mkdir -m 777 ../%s",FindSelect(KARI_FILE_PATH));   
        system(foruda);
     }*/

       
     i = setjmp(jmp_continue);
   
     /*不定的SQL的传入*/
     strcpy(SubSQL,sql);

     /*SQL的解析*/
     strcpy((char *)dynstmt.arr,SubSQL);
     dynstmt.len = (unsigned short)strlen((char *)dynstmt.arr);
     memset(select_dp,0,sizeof(select_dp));
     EXEC SQL  PREPARE S FROM :dynstmt;
   
     if(sqlca.sqlcode != 0)
     {
       printf("sqlca.sqlcode =[%d]\r\n",sqlca.sqlcode);
        /*ERROR*/
        return -1;
     }

     EXEC SQL DECLARE CC CURSOR FOR S;
     EXEC SQL  OPEN CC;
     
     if(sqlca.sqlcode != 0)
     {
         printf("sqlca.sqlcode =[%d]\r\n",sqlca.sqlcode);
         return -1;
     }
      /*SQL的所需最大的字段的条数*/
     select_dp->N = MAX_ITEMS;
     EXEC SQL DESCRIBE SELECT LIST FOR S INTO select_dp;
     
      if(sqlca.sqlcode != 0)
     {
         printf("sqlca.sqlcode =[%d]\r\n",sqlca.sqlcode);
         return -1;
     }
     
     memset(select_dp,0,sizeof(select_dp));
     if(select_dp->F<0)
     {
        return -1;
     }
      /*重新设置最大条数*/
     select_dp->N = select_dp->F;
     
     for(i=0;i<select_dp->F;i++)
     {
               
        sqlnul(&(select_dp->T[i]),&(select_dp->T[i]),&null_ok);
        /*类型的转化*/
        switch(select_dp->T[i])
        {
            case 1:
                  select_dp->L[i]=select_dp->L[i] * 2 + 4;
                  break;
            case 2:
                 sqlprc(&(select_dp->L[i]),&precision,&scale);
                   if(precision==0) precision =40;
                 select_dp->L[i]=precision+2;
                 break;
            case 8:select_dp->L[i]=240;
                 break;
            case 11:
                 select_dp->L[i]=18;
                 break;
            case 12:
               
                 select_dp->L[i]=9;
                 break;
            case 23:
                 break;
            case 96:
                 select_dp->L[i]=select_dp->L[i] + 2;
            case 24:
                 select_dp->L[i]=240;
                 break;
      }
       select_dp->V[i]=(char *)realloc(select_dp->V[i],select_dp->L[i]+1);
       if(select_dp->T[i]!=24)
       {
           select_dp->T[i]=5;
       }
     }
     
      if(sqlca.sqlcode != 0)
      {
        printf("sqlca.sqlcode =[%d]\r\n",sqlca.sqlcode);
        ProcDBerror();
         /*ERROR*/
         return -1;
      }
        for(;;)
        {
           
           EXEC SQL WHENEVER SQLERROR DO ProcDBerror();
         
           EXEC SQL AT :gbDb_name FETCH CC USING DESCRIPTOR select_dp;
             if(sqlca.sqlcode ==0 )
             {
                  for(i=0;i<select_dp->F;i++)
                     {
                            printf("entry=[%s]\n".select_dp->V[i]);
                         
                     }
                 
          }
          else if( sqlca.sqlcode==1403 )
          {
                break;
          }
          else
          {
             return -1;
          }
         
       }/* for(;;)end*/
      /*free 释放空间*/
     for(i=0;i<MAX_ITEMS;i++)
     {
       free(select_dp->I[i]);
       free(select_dp->V[i]);
     }
     sqlclu(select_dp);
     EXEC SQL AT :gbDb_name CLOSE CC;
     EXEC SQL  AT :gbDb_name COMMIT WORK RELEASE;
   
   }/*end else*/
     
     
     /*sprintf(path,"iconv -c -f UTF-8 -t shift_jis %s >%s",csvfilepath,id);*/
     /*system(path);*/
     return 0;
}

C不定参数写法

由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦;即使采用C++,如果参数个数不能确定,也很难采用函数重载.对这种情况,有些人采用指针参数来解决问题.下面就c语言中处理不定参数数目的问题进行讨论.

在stdarg.h这个头文件中有这么几个宏,参考参考:
 

#define _INTSIZEOF(n)   ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )           //第一个可选参数地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址
#define va_end(ap)    ( ap = (va_list)0 )                            // 将指针置为无效

在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自己插入的代码段的目的.
总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.
堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:
最后一个参数
倒数第二个参数
...
第一个参数
函数返回地址
函数代码段 (这是在一篇文章中对函数堆栈地址的解释,感觉解释得还算通俗易懂)

主要函数介绍:

va_start使argp指向第一个可选参数。va_arg返回参数列表中的当前参数并使argp指向参数列表中的下一个参数。va_end把argp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。

示例代码:

 

 

#include 〈stdio.h〉
#include 〈string.h〉
#include 〈stdarg.h〉
  
int demo( char, ... );
void main( void )
{
   demo("DEMO", "This", "is", "a", "demo!", "");
}
  
int demo( char msg, ... )
{

   va_list argp;
   int argno = 0;
   char para;

  
   va_start( argp, msg );
   while (1)
    {
      para = va_arg( argp, char);
      if ( strcmp( para, "") == 0 )
            break;
       printf("Parameter #%d is: %s\n", argno, para);
       argno++;
   }
   va_end( argp );
  
    return 0;
}