C指针原理(93)-C应用技巧(2)

来源:互联网 发布:vb 截图部分图像 编辑:程序博客网 时间:2024/05/29 06:27
键盘缓冲区残余信息问题 

#include <stdio.h>
int main()
{
    int a;
    char c; 
    do
    {
        scanf("%d",&a);
        scanf("%c",&c);
        printf("a=%d     c=%c\n",a,c);
        /*printf("c=%d\n",c);*/
    }while(c!=''N'');

   scanf("%c",&c);这句不能正常接收字符,什么原因呢?我们用printf("c=%d\n",c);将C用int表示出来,启用printf("c=%d\n",c);这一句,看看scanf()函数赋给C到底是什么,结果是 c=10 ,ASCII值为10是什么?换行即\n.对了,我们每击打一下"Enter"键,向键盘缓冲区发去一个“回车”(\r),一个“换行"(\n),在这里\r被scanf()函数处理掉了(姑且这么认为吧^_^),而\n被scanf()函数“错误”地赋给了c. 
解决办法:可以在两个scanf()函数之后加个fflush(stdin);,还有加getch(); getchar();也可以,但是要视具体scanf()语句加那个,这里就不分析了,读者自己去摸索吧。但是加fflush(stdin);不管什么情况都可行。 
函数名: fflush 
功 能: 清除一个流 
用 法: int fflush(FILE *stream); 
#include <stdio.h>
int main()
{
    int a;
    char c; 
    do
    {
        scanf("%d",&a);
        fflush(stdin);
        scanf("%c",&c);
        fflush(stdin);
        printf("a=%d     c=%c\n",a,c); 
    }while(c!=''N'');
}      
这里再给一个用“空格符”来处理缓冲区残余信息的示例: 
运行出错的程序: 
#include <stdio.h>
int main()
{
    int i;
    char j;
    for(i = 0;i < 10;i++)
    {
        scanf("%c",&j);/*这里%前没有空格*/
    }

使用了空格控制符后: 
#include <stdio.h>
int main()
{
    int i;
    char j;
    for(i = 0;i < 10;i++)
    {
        scanf(" %c",&j);/*注意这里%前有个空格*/
    }

    可以运行看看两个程序有什么不同。 

本博客所有内容是原创,如果转载请注明来源

http://blog.csdn.net/myhaspl/

高级版的取子串函数,可以完成正向取子串,反向取子串,
1、调用:
substr(取出的子串,源串,起始位置,长度)
函数返回实际取到子串的长度
其中长度可以为正数(从左边向右边取),长度为负数(从右边向左边取),长度可以超过实际能取到的子串长度,函数会智能判断,取长度范围内尽可能长的子串。


2、函数源代码
C代码  
int substr(char* dchr,char *schr,int begin,int len){  
//作者:myhaspl@myhaspl.com 
//取子串函数,dchr为取好后的子串,schr为源串,返回成功取出的子串数目,len为负数,则从begin向头部移动(正向),否则向尾部移动(反向),begin为起始位置(从1开始),len为子串长度  
  
    int slen=0;  
  
    int rc=0;      
  
    if (begin<=0) begin=1;//起始位置为0时,会从1开始  
  
    slen=strlen(schr)-begin;      
  
    if (slen<=0||len==0){//当len为0或begin的位置已经超过源串长度时,取空串  
  
       *dchr=NULL;  
  
       return rc;  
  
    }  
  
    if (len<0){//len为负数,表示从begin处向头部移动len个字符的子串,允许出现len移过头的现象(begin=3,len=-6,则取从位置1到位置3的子串)  
  
        len=-len;  
  
        if(len>strlen(schr)) begin=1;  
  
        else if((begin-len)<=0){  
  
            len=begin;  
  
            begin=1;  
  
        }  
  
        else {  
  
             begin-=len;  
  
             begin++;  
  
        }  
  
    }  
  
  
  
     begin--;  
  
     schr+=begin;  
  
     int i=0;  
  
     for(i=0;i<len&&*schr!=0;i++){  
  
        *dchr++ = *schr++;           
  
     }  
  
     *dchr=0;   
  
     rc=i;  
  
  return rc;  
  
}

c_预定义宏-反映编译信息

  

1、     __LINE__:被编译的文件中的行号

2、     __FILE__:编译的日期

3、     __DATE__:编译的日期("Mm dd yyyy")

4、     __TIME__:编译的时间("hh:mm:ss")

5、     __STDC__:如果编译器符合C标准(C89或C99),则值为1

C-#line和#error

1、
1)源代码:
test2.c
C代码  
#line 1  
int main(void){  
printf("line 1\n");  
printf("line 2\n");  
printf("line 3\n");  
printf("line 4\n");  
printf("line 5\n");  
printf("line 6\n");  
printf("line 7\n");  
printf("line 8\n");  
#include "test1.c  
 test1.c
 
C代码  
#line 9 "test2.c"  
#define LINUX  
#ifdef WIN32  
  printf("win32\n");     
#elif defined LINUX  
  printf("linux %d %s\n",__LINE__,__FILE__);          
#else  
  #error no flag define   
  //如果LINUX和WIN32没有定义,#error会显示错误信息,然后停止编译  
#endif  
}  
  2)运行结果:
mysea@mysea-pc:~/test$ ./test2
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
linux 13 test2.c


 
2、#error表示停止编译,显示错误信息
3、#line 直接指定下一行的行号及文件名
1)指定行号
#line n
2)指定文件名和行号
#line n "filename"
4、源代码的#include "test1.c"和#line 9 "test2.c"表示:test2.c和test1.c实质属于一个C程序:test2。
1)注意这只是标注,如果要在编译时把test1.c包括进来,必须加上#include "test1.c
 
 
2)编译时,编译test2
 
 
 
mysea@mysea-pc:~/test$ gcc -o test2 test2.c
 


0 0