通过这次考核,我发现自己存在很多问题,C语言基础不够扎实,存在知识盲区,还有一些知识点理解不够深刻,应该再好好研究 C Primer Plus 这本书,扎实基础,同时要多刷题,强化代码能力。
软协的门牌号是:FZ131!!!记牢记牢记牢!!!
1. 正负数在计算机中存储 :
十进制的整数 22 和 -22 在 8 位计算机中的存储分别为( )
A. 11101010,00010110
B. 00010110,11101010
C. 00010110,10010110
D. 10010110,11101010
22转化为二进制为00010110,负数在计算机中,以补码的形式存储,22的补码为,从右向左数的0和第一个出现的1不变,其余取反,所以是11101010,选B。
2. 浮点型数据比较
下面代码会输出 c!=d c=1.900000,d=1.900000。分析原因并给出修改方案
#include<stdio.h>
int main()
{
double a = 1.6;
double b = 0.3;
double c = 1.9;
double d = a + b;
if (c == d)
{
printf("c==d");
}
else
printf("c!d c=%lf d=%lf", c, d);
return 0;
}
任意一个二进制浮点数V可以表示成 (-1)^(s)*M*2^(E) 的形式。
(-1)^(s)表示符号位(s=0时V为正数,s=1时V为负数)
M表示有效数字,大于等于1,小于2
2^(E)表示指数位
如十进制的9.0,写成二进制形式为1001.0,相当于1.001*2^(3) = (-1)^(0)*1.001*2^(3) (s=0,M=1.001,E=3)
所以计算机中存储的浮点型数据并不准确,只是一个大概值,所以 d = a + b 在1.9 附近,不等于c,所以c != d 。
修改方案:使用fabs函数,fabs()函数是返回浮点数的绝对值的一个函数,定义在math.h头文件中。
3. 自动类型转换:
(多选)下列关于自动类型转换描述正确的是( )
A. int 型和 int 型运算时,不会发生自动类型转换
B. float 型和 float 型运算时,不会发生自动类型转换
C. long 型和 float 型运算时,会发生自动类型转换
D.long 型和 int 型运算时,会发生自动类型转换
必定的转换:char型、short型数据运算时必定先转换为int型,float型数据运算时转换成double型。
不同类型的转换: int 型和 long 型运算时,先将 int 型直接转换成 long 型,最终结果为 long 型。float 型和 int 型运算时,先将float 型转换成 double 型,int 型转换成 double 型,最终结果为 double 型。
所以选ACD.
4. 输出 a > b :
(1)
if(a>b)
max=a;
else max=b;
(2)
int max;
max=a>b ? a : b ;
5. strlen 和 sizeof 的区别:
strlen:计算字符串的长度的函数,遇到第一个NULL(‘\0’)为止,不包括‘\0’, 时间复杂度为O(n)
sizeof: 计算变量、对象或类型所占字节数的多少,是一个运算符,时间复杂度为常数
char s1[] = "hello";
char* s2 = "hello";
char s3[10] = ''hello";
sizeof(s1) = 5 strlen(s1) = 5
sizeof(s2) = 4 strlen(s2) = 5
sizeof(s3) = 10 strlen(s3) = 5
s2是一个指针,对于指针,sizeof所得值,在32位系统是4,在64系统是8
strlen,不管是数组还是指针,只要遇到第一个‘\0’就为止,hello字符串是这样的{‘h’, ‘e’,‘l’,‘l’,‘o’,‘\0’}的所以strlen(“hello”) = 5
sizeof:用法,sizeof(int)、sizeof(2)、sizeof(2+1)、sizeof(f())(int f(),f是一个函数,sizeof是返回值类型的大小,返回值是void,是不能使用sizeof的),但是位域不能被sizeof计算。sizeof是一个关键字不是函数,发生在编译时刻,所以可以用作常量表达式。
总结,当参数分别如下时,sizeof返回的值表示的含义如下:
数组——编译时分配的数组空间大小;
指针——存储该指针所用的空间大小(在32位系统是4,在64系统是8);
类型——该类型所占的空间大小;
对象——对象的实际占用空间大小;
函数——函数的返回类型所占的空间大小。函数的返回类型不能是voidsizeof只关心这块内存的大小,不关心这块内存存放了什么数据,strlen只关心这块内存存放的数据,不关心这块内存的大小,直到遇到第一个NULL为止。
6. 链表访问数据域:
-> : 指针类型
. : 结构体类型
所以,访问p结点的数据域:p->data,还可以(*p).data 。
7. 指针与数组:
int a[5] = { 6,3,4,7,9 };
int* p = a;
写出++*p,*p++,*(p++),(*p)++,*++p,*a++,*++a的对应的值
(注:若用程序测试,记住一个一个测,要不然p的值已经发生变化)
++与*同时出现,并且挨在一起的时候,自右向左运算,
*:取值运算符,与指针组合使用,获得指针所指向变量的值,a是数组,所以*a报错,没有结果。
++*p :先取p的值,p指向数组a的首地址,*p是6,++*p为7
*p++:先取p的值,*p++后还是++前的值,所以*p++为6
*(p++):先进行p++,p还是指向数组a的首地址,取首地址的值,所以*(p++)为6
(*p)++:先取数组a的首地址,(*p)为6,(*p)++,还是++前的结果,所以(*p)++为6
*++p:先++p,p指向a[2], 所以*++p为3
总结:只有++(p*)、(*p)++、++*p,指针位置不变,改变数组的原始数值
其他情况都是指针指向下一个,指针的位置+1。
8. 文件读取
下面的程序功能是:新建test.txt文件,为其写入字符串“ok”,并从中读取出来。现已知下面程序无法实现该功能,请在横线上填写一行代码,完善此功能。
#include<stdio.h>
int main()
{
FILE* fp = fopen("test.txt", "a+");
char s[20] = "ok";
fputs(s, fp);
char t[20];
fseek(fp, 0, 0); //所需要填的代码
fscanf(fp, "%s", t);
puts(t);
fclose(fp);
return 0;
}
9.读入文件,链表的增删改查
要求:
(1) 链表存储
(2) 从本地文件“member.txt” 中读取软协成员信息,并展示全部成员信息(按学号排序后展示)
(3) 通过姓名查询出指定成员并删除成员
(4) 添加新成员
(5) 修改成员的联系方式
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
typedef struct member
{
char name[10];
char num[15];
char dir[10];
char pho[15];
struct member* next;
}Mem;
int CreatRear(Mem** h);
void Delete(Mem** h);
void show(Mem* h);
Mem* Modify(Mem* h);
Mem* Sort(Mem* h);
int SaveFile(Mem* h);
int ReadFile(Mem **h);
int main() //主函数
{
int select = 1;
Mem* head = NULL;
ReadFile(&head);
while (select != 0)
{
printf("-------------------------\n");
printf("---------请选择----------\n");
printf("---------1.数据录入------\n");
printf("---------2.数据删除------\n");
printf("---------3.数据修改------\n");
printf("---------4.数据排序------\n");
printf("---------5.数据展示------\n");
printf("----------请选择:-------\n");
scanf("%d", &select);
switch (select)
{
case 1:
CreatRear(&head);
break;
case 2:
Delete(&head);
break;
case 3:
Modify(head);
break;
case 4:
Sort(head);
break;
case 5:
show(head);
break;
default:
break;
}
}
return 0;
}
int ReadFile(Mem **h) //读取文件
{
FILE* fp;
Mem *head,*p,*q=NULL;
if((fp=fopen("D:\\c\\xi\\members.txt","r+"))==NULL)
{
printf("打开失败!");
exit(-1);
}
//fp=fopen("D:\\c\\xi\\members.txt","r+");
while(!feof(fp))
{
p=(Mem*)malloc(sizeof(Mem));
if(q==NULL)
{
*h=p;
q=*h;
}
else
q->next=p;
p->next=NULL;
fscanf(fp,"%s",p->name);
fscanf(fp,"%s",p->num);
fscanf(fp,"%s",p->dir);
fscanf(fp,"%s",p->pho);
// printf("%s %s %s %s\n",p->name,p->num,p->dir,p->pho);
q=p;
}
fclose(fp);
return 1;
}
int CreatRear(Mem **h) //尾插添加新成员
{
char mname[10];
char mnum[15];
char mdir[10];
char mpho[15];
Mem* p=NULL, * q=NULL;
printf("请输入信息:\n");
printf("姓名:");
scanf("%s", mname);
printf("学号:");
scanf("%s", mnum);
printf("方向:");
scanf("%s", mdir);
printf("电话:");
scanf("%s", mpho);
getch();
p = (Mem*)malloc(sizeof(Mem));
if (p == NULL)
return 0;
strcpy(p->name, mname);
strcpy(p->num, mnum);
strcpy(p->dir, mdir);
strcpy(p->pho, mpho);
p->next = NULL;
if (*h == NULL)
*h = p;
else
{
q = *h;
while (q->next != NULL)
q = q->next;
q->next = p;
}
return 1;
}
void Delete(Mem** h) //删除成员信息
{
char mname[10];
Mem* p = NULL,*q = NULL;
if (q == *h)
*h = q->next;
else
{
p = *h;
while (p->next != q) p = p->next;
p->next = q->next;
}
free(q);
getch();
}
Mem* Modify(Mem* h) //修改成员信息
{
Mem* p = NULL;
char mname[10];
printf("请输入修改后的电话:");
char mpho[15];
scanf("%s", mpho);
strcpy(p->pho, mpho);
getch();
return h;
}
void show(Mem* h) //展示成员信息
{
Mem* p;
p = h;
printf("信息如下:\n");
printf("姓名 学号 方向 电话 \n");
while (p != NULL)
{
printf("%s\n%s\n%s\n%s\n", p->name, p->num, p->dir, p->pho);
p = p->next;
}
getch();
}
Mem* Sort(Mem* h) //按成员的学号排序
{
Mem* h1, * p1, * p2, * q;
h1 = h;
h = h->next;
h1->next = NULL;
while (h!= NULL)
{
q = h;
h = h->next;
p1 = p2 = h1;
while (p2 != NULL)
{
if (strcmp(q->num, p2->num) < 0)
break;
p1 = p2;
p2 = p2->next;
}
if (p1 == p2)
{
q->next = p2;
h1 = q;
}
else
{
p1->next = q;
q->next = p2;
}
}
getch();
return h1;
}
int SaveFile(Mem* h) //保存成员信息至文件
{
Mem* p;
FILE* fp;
fp = fopen("D:\\c语言\\members .txt", "wt");
p = h;
while (p != NULL)
{
fwrite(p, sizeof(Mem), 1, fp);
p = p->next;
}
fclose(fp);
getch();
return 1;
}