A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© qddnovo 中级黑马   /  2014-6-7 22:10  /  2012 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 qddnovo 于 2014-6-8 12:46 编辑

这是自己学习的时候一点一点记录下来的,希望和大家分享到有用的地方

获取指定长度的字符串,或者说为字符串数组获取用户输入的字符
void get_str(char str[], int len)
{
        int i=0, c;
        while (i<len)
        {
                c = getchar();/*这里是防止开始之前用户输入过回车,我们就跳过不处理*/
                if (c == '\n')
                {
                        if (!i)
                                continue;
                        str = '\0';
                        break;
                }
                str[i++] = c;
        }
        if (i == len)
        {
                if (c != '\n')
                        while (getchar() != '\n')
                                ;
                str = '\0';
        }
}
使用举例:
char str[11];//结尾保存’\0’
get_str(str,sizeof(str)-1);
或者使用如下格式
#define NAME_CUT 50
char name[NAME_CUT+1];
get_str(str,NAME_CUT);

添加双引号的宏
#define F(x) _F(x)
#define _F(x) #x
使用举例:
在这种场景下
#define NAME_CUT 50
char name[NAME_CUT+1]
我们需要打印name,就可以写成
printf(“%” F(NAME_CUT) ”s\n”,name);
当然真如果出现这种情况,我推荐使用如下宏
#define CUT_FORMAT(x)  _CUT_FORMAT(x)
#define _CUT_FORMAT(x) “%”#x”s”
使用就改为
printf(CUT_FORMAT(NAME_CUT) “\n”,name);

推荐的链表的声明格式
typedef
        struct node
        {
                ......
        }
NODE;/*数据类型*/
typedef
        struct list
        {
                NODE data;
                struct NODE *next;
        }
LIST;/*链表类型*/
使用举例
#define NUM_CUT 10  /*数据中编号最大长度*/
#define NAME_CUT 20 /*数据中姓名最大字符数*/
typedef
        struct
        {
                char num[NUM_CUT + 1];
                char name[NAME_CUT + 1];
                char sex;
                char age;
        }
STU;/*数据类型*/
typedef
        struct NODE
        {
                STU data;
                struct NODE *next;
        }
LIST;/*链表类型*/
这种写法非常漂亮,容易扩展

简单的malloc宏,添加了’日志’记录
#define MALLOC(mp) \
{\
        if (NULL == (mp = malloc(sizeof(*mp)))) \
        {\
                fputs("内存分配失败,程序退出......", stderr);\
                exit(EXIT_FAILURE); \
        }\
}
使用举例
假设存在如下环境
#define NUM_CUT 10  /*数据中编号最大长度*/
#define NAME_CUT 20 /*数据中姓名最大字符数*/
typedef
        struct
        {
                char num[NUM_CUT + 1];
                char name[NAME_CUT + 1];
                char sex;
                char age;
        }
STU;/*数据类型*/
STU *stu;
那么为stu开辟一个空间只需要添加下面的宏语句.
MALLOC(stu);//显然它也存在一个C关于malloc的通病,就是内存不足时,再打印文本也是无法执行的.但是它的原意是日志记录,虽然不一定会记录成功.
再扩展一下MALLOC如下:
#define MALLOC(var) if(!(var=malloc(sizeof(*var)))){\
        fputs("内存申请失败,程序退出中...\n",stderr);\
        exit(EXIT_FAILURE);\
}
文件打开的简单宏,添加了’日志’记录
#define FOPEN(file,path,type) \
{\
        if (NULL == (file = fopen(path, type)))\
        {\
                fputs("内存不足程序退出中", stderr);\
                exit(EXIT_SUCCESS);\
        }\
}
举例
FILE *file;
FOPEN(file,”work_log.rec”,”rb”);

在控制台上清除输入缓存
                while (getchar() != '\n')
                        ;
举例
譬如存在如下语句
int c,num;
printf(“请输入一个整数:”);
scanf(“%d”,&num);
printf(“请再输入一个字符:”);
c=getcahr();
在上面的scanf和getchar之间就存在输入缓存问题,默认getchar()接收的值为’\n’.
这样c获取的值不是我们事先预估的
解决办法就是在二者之间加上
While(getchar()!=’\n’)
  ;
扩展一下,更加严格的应该是这段代码
int ch;
While((ch=getchar())!=EOF&&ch!=’\n’)
  ;
上面的情况是允许用户使用退出getchar()的操作,getchar这个函数在接收错误的时候返回-1,其实就是EOF文件结束标志宏.在window上可以按下Ctrl+Z,Linux上可以按下Ctrl+D达到让getchar函数返回-1的效果,结束当前的输入.
在这里,我采用的设计思路是,要么关闭当前程序,要么就必须输入完整.关键看程序员的想法吧!

关于scanf函数获取用户输入值的一种简便用法
        while (printf(......)
,scanf(......)!=......||......)
        {
                while (getchar() != '\n')
                        ;
                puts(......);
        }
举例
例如存在如下要求,需要接收用户输入的一个数,这个数必须小于250,大于0
代码如下:
int num;
while(printf(“请输入一个大于0小于250的整数:”),
  scanf(“%d”,&num)!=1||num<=0||num>=250)
{
  while(getchar()!=’\n’)
  ;
    puts(“输入错误,请按照提示重新操作!”);
}
当然有时嫌它代码重复,可以定义如下简单宏
#define CLEAR         while (getchar() != '\n')/*清除缓存*/
#define CLEARANDMSG {CLEAR;puts("输入出错,请按照提示重新操作!");}
使用的话就可以写成
int num;
while(printf(“请输入一个大于0小于250的整数:”),
  scanf(“%d”,&num)!=1||num<=0||num>=250)
      CLEARANDMSG;
但是上面的代码很丑,关键看自己怎么看了.

关于printf输出格式串%*的用法
#define NAME_CUT 50
char name[NAME_CUT+1];
printf("%*s\n",NAME_CUT,name);
举例
对于这个技巧,是为了避免一些错误,例如如果name数组中没有’\0’,输出采用%s则会使输出内容不可控.还有一点就是它也统一控制了姓名打印对齐的格式.

比较古老的关于结构体空间声明技巧
typedef
        struct node
        {
                int num;
                char name[];
        }
NODE;
举例
上面是C99定义包含空数组的结构体,在比较老的时候还存在
typedef
  struct node
  {
  int num;
  char name[1];
  }
NODE;
typedef
  struct node
  {
  int num;
  char name[0];
  }
NODE;
上面两种模式,思路都一致.声明的时候可以写成
int n=10;
NODE node=malloc(sizeof(NODE)+n);
达到可变数组的目的.(注结构体中 char name[]和char *name,是不同的)

高级简单一点的FOPEN宏的实现
#define FOPEN(file,path,type) \
FILE *##file;\
if (NULL == (##file = fopen(path, type)))\
{\
        fputs("内存不足程序退出中", stderr);\
        exit(EXIT_SUCCESS);\
}
举例
如果想将worker_one.rec文件内容复制到worker_two.rec文件中,
创建并打开文件对象的代码就是:
FOPEN(worker_one_file,”worker_one.rec”,”rb”);
FOPEN(worker_two_file,”worker_one.rec”,”wb”);
详细完整的代码如下:
FOPEN(wo_file,”worker_one.rec”,”rb”);
FOPEN(wt_file,”worker_one.rec”,”wb”);
for(int c;(c=fgetc(wo_file))!=EOF;fputc(c,wt_file))
  ;
fclose(wo_file);
fclose(wt_file);

1 个回复

倒序浏览
给力,为啥没人回复呢?{:3_57:}
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马