其一:关于动态存储分配函数的调用
STU *fun(STU a[ ], int m) //主函数中调用函数语句:pOrder=fun(a,m);
{ //函数功能为查找结构体数组中前m名学生成绩,并输出
STU b[N], *t;
int i,j,k;
// t=(STU *)calloc(m,sizeof(STU)); 这是一句被屏蔽的语句
t=(STU *)calloc(sizeof(STU),m); //实际上以上这两个语句都被运行成功,为什么?我想说明的问题是:calloc( , )函数中参数位置是否能调换?
for(i=0; i
b[i]=a[i];
for(k=0; k
{
for(i=j=0; i
if(b[i].s > b[j].s)
j=i; //找出最大的数所在的结构体的序号
t[k]=b[j]; //实际上是在b[N]这个新建的数组中进行操作的,原来的数据并没有被破坏
b[j].s=0; //将前面的已经比较的分数赋予0值,不再参加比较
}
return t;
}
其二:在已经过排序数组中实现查找和删除功能(实际上还有改进的地方!)
int fun(int a[], int n) //for()语句的思想是使用了两个flag实现的
{ //函数功能是在数组中查找相同数据,并删除相同的,保留一个
int m=1;
for(int i=1,j=0;i
if(a[j]==a[i]) //此处是为了判断i后面是否仍存在相同数据
; //这是一个空语句,最给力的就是这两个标志i和j
else
{
j++; //否则,将j向后移动,准备覆盖相同数据
a[j]=a[i];
m++; //将i++功能都放在了for语句的判断部分中
}
return m; //最后返回的是除去相同数值后,数组中剩余数的数目
}
其三:求余数,对余数的分析。
unsigned fun ( unsigned w ) //函数的功能是求n位数w的n-1位数w`,比如数1987,调用函数求出值为987
{
if(w>10000) w%=10000; //一个数对10000求余数,余数是小于10000
else if(w>1000)
w%=1000; //一个数对1000求余数,余数小于1000,依次类推,就能求出低n-1位数
else if(w>100)
w%=100;
else if(w>10)
w%=10;
return w ; //求出的数值就是所求的低n-1位数
} //我仅知道一个数能对10求余数,而不知道能对任何数求余数
其四:删除字符数组中的空格(这样写是有错误的!)
void fun(char *str) //函数调用语句:fun(str); 函数的功能是删除字符串中所有的空格字符
{
char a[81]; //重新定义了一个字符数组
int i=0,n=0;
for( ;*str!=NULL; )
a[n++]=*str++; //这里将原数组进行了赋值,运行最后指针指向的是字符串的末尾
a[n]=NULL;
for( n=0;a[n]!=NULL; )
if(a[n]==' ')
n++;
else
str[i++]=a[n++]; //虽然字符数组的指针使用可以和数组差不多,实际上这个程序是运行不出来的!程序很繁琐
str[i]=NULL;
}
下面的程序是正确的:
void fun(char *str)
{
int i=0,j=0;
for(;str[i]!=NULL&&str[j]!=NULL;) //证明了字符数组的指针可以当做数组来进行操作,而且这里所用到的判断很给力,很精确
{ //这里需要注意的是当str[j]==NULL时,将会结束
for( ;str[j]!=NULL; )
if(str[j]==' ')
j++;
else
{str[i++]=str[j++];break;} //此处跳出了循环,改变了j的取值
}
str[i]=NULL; //在逻辑上是没有任何问题的,思路方面都是用到了两个标志i和j
}
其五:对链表的逆置
void fun(NODE *h) //调用函数语句:fun(head); 函数的功能是对链表进行逆置
{
NODE *p, *q, *r;
p = h->next;
if (p==NULL)
return; //函数没有返回值,在书写return语句时,不能写返回0或是1
q = p->next;
p->next = NULL;
while(q)
{
r = q->next;
q->next = p;
p = q;
q =r;
}
h->next = p;
} //程序思路是将原链表中的每一个结点取出,在第一个结点的前面做添加结点操作
其六:在源字符串中查找子字符串的个数
int fun(char *s, char *t) //函数调用语句:m=fun(a, b);
{
int n;
char *p , *r;
n=0;
while(*s) //这里比较要从源字符串的每一个字符开始进行比较
{
p=s; //s指针的指向已经发生了改变
r=t;
while(*r) //循环比较
if(*r==*p)
{ r++; p++; }
else break; //break跳出所在的循环语句,去执行下面的语句,而不等到判断*r是否指向最后的空字符
if(*r==0) //如果r指向的是空字符,说明存在这个子字符串
n++;
s++; //实际上是从源字符串的每一字符开始比较的
}
return n; //函数返回相同字符串的个数
}
其七:分析函数指针,函数指针指向要调用的函数
double f1(double x)
{ return x*x; }
double f2(double x, double y)
{ return x*y; }
double fun(double a, double b) //函数调用语句:r = fun(x1, x2);
{
double (*f)( ); //定义了函数的指针
double r1, r2;
f=f1; /* point fountion f1 指针指向函数f1*/
r1=( *f )( a ); //调用函数f1
f=f2; /* point fountion f2 指针指向函数f2*/
r2 =( *f )( a , b ); //调用函数f2
return r1 + r2;
}
出现的问题:
“=”: 无法从“double (__cdecl *)(double)”转换为“double (__cdecl *)(void)”
1> 该转换要求reinterpret_cast、C 样式转换或函数类型转换
1>c:\documents and settings\administrator\my documents\visual studio 2008\c\c46\c46\c46.cpp(16) : error C2197: “double (__cdecl *)(void)”: 用于调用的参数太多
1>c:\documents and settings\administrator\my documents\visual studio 2008\c\c46\c46\c46.cpp(18) : error C2440: “=”: 无法从“double (__cdecl *)(double,double)”转换为“double (__cdecl *)(void)”
1> 该转换要求reinterpret_cast、C 样式转换或函数类型转换
1>c:\documents and settings\administrator\my documents\visual studio 2008\c\c46\c46\c46.cpp(19) : error C2197: “double (__cdecl *)(void)”: 用于调用的参数太多
P.S. 这些问题都是在调用函数时发生的,比如: r1=( *f )( a ); r2 =( *f )( a , b ); 实际在定义这个函数指针时:double (*f)( ); 其中是没有参数的,所以会发生这样的错误,我想问的是这样的错误怎么解决?
其八:循环赋值带来的问题
int fun(char *str) //函数调用语句:fun(s) 这个函数是判断字符串是否为回文
{
int i=0;
char *p;
p=str;
for(;*p!=NULL;p++)
i++;
p=str+i-1; //p指向最后一个字符
for(i=1;str<=p;p--,str++) //i=0,i作为标致。通过指针来判断是否退出循环
{ //一个指针向前循环,一个指针向后循环,完成判断
if(*str!=*p)
{ i=0;break; } //break;语句退出循环,说明该字符串不是回文
else
; //i=1。这里会输出最后一次比较的结果,而不是其中的某一次,因此在这里不能够重复给i赋值
}
return i;
}
其九:插入排序算法的实现
void insert(char *aa) //函数调用语句:insert(a);
{
int i,j,n;
char ch;
n=strlen(aa);
for( i=1; i
{
ch=aa[i];
j=i-1;
while ((j>=0) && ( ch
{ aa[j+1]=aa[j]; //aa[j+1]==aa[i] 但是不能用i替换,j这个变量很重要
j--;
}
aa[j+1]=ch;
}
}
P.S.这是经典的插入排序算法,这个程序写地很精巧,真的应该好好的记住算法。
以上就是我这几天的成果了,一些好的算法我们应该仔细分析其精妙之处,一些不懂的地方还要好好琢磨。从实践中来到实践中去,将实践中的经验总结下来,供以后的自己看看,并有效地运用到工作中去。在以上几点中还透露出一些问题,这些问题后面在学习C Primer Plus过程中应该会遇到,希望自己以后能完全弄明白。我相信通过自己的努力能够精通C语言,还能够做到一通百通。