文章作者:冰血封情[E.S.T]
信息来源:邪恶八进制 中国
025有关处理多余的字符的话题
scanf()只会处理格式化字符串指定的字符数目 如果用户输入了多余的字符 将仍然被保留在stdin中 这些字符可能导致问题 比如下面的代码
复制内容到剪贴板
代码:
#include <stdio.h>
int main(void)
{
int age;
char name[80];
puts("Enter your age.");
scanf("%d", &age);
puts("Enter your name.");
scanf("%s", name);
printf("Age is %d.\n", age);
printf("Name is %s.", name);
return 0;
}如果在输入名字的时候 用户输入的是23.00 而第一个scanf()调用期望得到一个整数 于是 它就只读取了23 并将它赋值给变量age 如此一来 字符.00将保留在了stdin中
第二个scanf调用期望得到一个字符串 于是他在stdin中找到了.00 那么.00就赋给了name 这的确是个问题
书上提供了两种方法来处理多余的字符 第一种比较简单 是调用一个函数 比如clear_kb()
然后 函数体这么写
void clear_kb(void)
{
char junk[80];
gets(junk);
}
由于利用了gets读区换行符之前所有的字符 当然前面那个函数是有安全隐患的 以前gets的总结中提到过 可能溢出的问题
而且这里注意了 以前咱们学过 每次调用函数的内部动态变量 是会重新建立的 所以不用担心它会满 只要够大就可以咯
当然 由于gets的安全问题 你可以使用下面的函数fflush()来达到同样的效果 而且更加安全
复制内容到剪贴板
代码:
#include <stdio.h>
int main(void)
{
int age;
char name[80];
puts("Enter your age.");
scanf("%d", &age);
fflush(stdin);
puts("Enter your name.");
scanf("%s", name);
printf("Age is %d.\n", age);
printf("Name is %s.", name);
return 0;
}026指针数组和指向数组的指针
如果有这么一个数组int array[3][8]
那么以下的方式将声明一个ptr指针变量 且让他能够指向包含8个int变量的数组 如下
int (* ptr)[8];
为什么加括号?因为[]的优先级高于*
哦 原来是这样哟 其实咱们以前呀 学过一个优先级的问题 也是括号解决*的 在哪呢?我回头翻阅一下的...
呵呵 原来在我第三次总结里的018条 三种存取结构成员的方式其中一种
引用:
2 通过指向结构的指针和间接运算符 比如
struct fuck {
int girl;
char name[20];
};
struct fuck *ptr;
struct fuck eviloctal;
ptr = &eviloctal;
这个时候可以通过(*ptr).girl = 100来存取结构成员
而下面这种就是指针数组了
int *p[4]数组的每个成员都是指针
027函数指针的传递和使用
其实学到这里我已经有点晕了 唉 有关指针的高级主题真是有点麻烦 但是我心里很清楚 这还是灾难的开始 我将来要遇见的还更多 他娘的怎么活呀:(
使用函数指针来调用不同的函数
复制内容到剪贴板
代码:
#include <stdio.h>
void func1(int x);
void one(void);
void two(void);
void other(void);
int main(void)
{
int nbr;
for(;;)
{
puts("Enter an integer between 1 and 10, 0 to exit:");
scanf("%d", &nbr);
if(nbr == 0)
break;
func1(nbr);
}
return 0;
}
void func1(int x)
{
void (*ptr)(void); //定义了一个指向函数的指针
if(x == 1)
ptr = one; //看看指了不是
else if(x == 2)
ptr = two;
else
ptr = other;
ptr();
}
void one(void)
{
puts("You entered 1.");
}
void two(void)
{
puts("You entered 2.");
}
void other(void)
{
puts("You entered something other than 1 or 2.");
}将指针作为参数传递给函数
复制内容到剪贴板
代码:
#include <stdio.h>
void func1(void (*p)(void)); //函数接受一个指向函数的指针
void one(void);
void two(void);
void other(void);
int main(void)
{
int nbr;
void (*ptr)(void); //在函数体里定义的函数指针
for(;;) //死循环来处理直到0后退出
{
puts("Enter an integer between 1 and 10, 0 to exit:");
scanf("%d", &nbr);
if(nbr == 0) //等于0退出
break;
else if(nbr == 1) //等于1的话
ptr = one; //就把指针指向函数one
else if(nbr == 2)
ptr = two;
else
ptr = other;
func1(ptr); //调用函数 传递指针
}
return 0;
}
void func1(void (*p)(void))
{
p(); //通过指针执行相应函数
}
void one(void)
{
puts("You entered 1.");
}
void two(void)
{
puts("You entered 2.");
}
void other(void)
{
puts("You entered something other than 1 or 2.");
}其实上面的关键分别在这里
第一个
void func1(int x); //只接受整型数组
void (*ptr)(void); //定义了一个指向函数的指针
ptr(); //通过指针执行相应函数
第二个
void func1(void (*p)(void)); //函数接受一个指向函数的指针
p(); //通过指针执行相应函数
void (*ptr)(void); //在函数体里定义的函数指针
这里开始我真的要慢点慎重的学习了 争取一次煮熟 否则成了假生米我就挂了 操
028声明函数指针一定要小心
好早以前好象有谁谁谁说过这么一个类似问题 今天我终于看见了
声明函数指针的时候需要用圆括号
比如下面的代码 它声明了一个指向某个函数的指针 该函数是不接任何参数的 但是返回一个字符
char (*function)(void);
下面代码声明了一个返回char指针的函数
char *function(void);
有意思的是 想上面那种 这样写很容易被人误解 可能这样写比较好
char * function(void);
最后强调 初始化指针之前 千万不要使用它 以前说过的 原因么 少给我JB罗嗦 HOHO进入链表的学习咯
029有关malloc和calloc的区别
今天学到链表的时候 书上提了一下malloc和calloc的用法要注意区分 于是查阅了函数手册做个小小的总结
首先是malloc
它是从堆中分配一块内存 当用户使用结束后要free() 把内存反回堆中提供再次调用 其函数功能说明就是分配一块内存 有点泛泛而谈 下面我们继续看另外一个
其次是calloc
首先它的说明就是分配并且刷新一块内存 它的作用是在堆中分配一块最长可达64K的内存 并把内存的每一个字节置为0 其原型是 void *calloc(size_t nitems, size_t size);
nitems是要分配的项数 size每一项的字节数
030指向指针的指针小总结
本来是不想总结它的 因为这个知识点还不算难 但是发觉做题目的时候有点生疏 主要是大脑不好用 浑了 所以还是总结一下吧
具体也不用怎么写 把关键的列出来就清楚了
传统指针的用法中看到的注意事项是这样的
int *ptr;
int var;
声明了以后我们首先把var的地址给指针
ptr = &var;
而如下的语句都是给var赋值
var = 12;
*ptr = 12;
这个时候的*称为间接运算符 其实你先赋值后使用指针也可以的
var = 12;
ptr = &var;
但是你不能这样 在没初始化指针的时候直接给他的地址存东西
*ptr = 12;
这句如果在没有ptr = &var;之前使用 那么天知道指针指到什么地方 只有外部变量才会被自动初始化为0 内部变量的值是不确定的
至于指向指针的指针可以像下面这样
int **ptr_to_ptr = &ptr;
不是声明的时候同时初始化应该这样
int **ptr_to_ptr;
ptr_to_ptr = &ptr;
如此看来 指针也就是一个变量 它只是有的时候扮演特殊的角色 但是它还是具备一般变量的特性的
下面看两个函数 可以充分体验到指针和指向指针的指针的用法
复制内容到剪贴板
代码:
#include <stdio.h>
int main(void)
{
int var = 38;
int *ptr; //定义指针
int **ptr_to_ptr; //定义指向指针的指针的用法
ptr = &var; //分开进行了初始化 这个是把变量的地址给指针
ptr_to_ptr = &ptr; //把指针的地址给指向指针的指针
printf("%d %d %d\n", var, *ptr, **ptr_to_ptr); //打印的都是变量值
printf("%d %d %d\n", &var, ptr, *ptr_to_ptr); //打印的都是变量地址
printf("%d %d\n", &ptr, ptr_to_ptr); //打印的都是一级指针的地址
return 0;
}下面看一个 定义的同时初始化的 和上面一样的例子 以前我就是分不清楚这两个例子
复制内容到剪贴板
代码:
#include <stdio.h>
int main(void)
{
int var = 38;
int *ptr = &var;
int **ptr_to_ptr = &ptr;
printf("%d %d %d\n", var, *ptr, **ptr_to_ptr);
printf("%d %d %d\n", &var, ptr, *ptr_to_ptr);
printf("%d %d\n", &ptr, ptr_to_ptr);
return 0;
}这两个例子对我自己的学习是很有意义的 因为以前我问过bideyore一个问题 但是他讲的我似懂非懂 到底还是明白了
通过以上的两个函数我就知道了 其实把指针和变量是密不可分的