自己把一些学习中和使用中的一些点滴有用的记录下来和大家分享。
1.获取指定长度的字符串,或者说为字符串数组获取用户输入的字符
void get_str(char str[], int
len)
{
int
i=0, c;
while
(i<len)
{
c
= getchar();/*这里是防止开始之前用户输入过回车,我们就跳过不处理*/
if
(c == ‘\n‘)
{
if
(!i)
continue;
str[i] =
‘\0‘;
break;
}
str[i++] = c;
}
if
(i == len)
{
if
(c != ‘\n‘)
while (getchar() !=
‘\n‘)
;
str[i]
= ‘\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);
原文地址:http://www.cnblogs.com/xiaobajiu/p/3776236.html