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:
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代码只是对从数据库中表中取得固定个数的字段的时候加以使用:
{
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)自带结构体来解决。
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 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 〈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;
}