您的位置:首页 > Web前端

[黑马IOS自学第七篇]fets文件函数等,结构体,结构体数组,宏学习

2015-11-21 09:50 393 查看
一.fgets函数



 fgets不能进行格式化输出输入
 代码如下

<span style="font-size:18px;">//fgets()
/*
文件操作相关函数
从键盘上接收一个字符串保存到数组中

scanf()缺点不能接收空格
gets(str)优点 :可以接收空格

*/
char str[10] ;
fgets(str,sizeof(str),stdin);//安全的,输入的字符串长度大于
puts(str);
//数组长度时,会将最后一个元素变为\0
/*
12345678abcd
12345678a
*/

for (int i = 0; i < 10 ; i++) {
printf("%d",str[i]);
}
/*
如果只输入8个第九个元素为空格
aaaaaaaa
aaaaaaaa

97 97 97 97 97 97 97 97 10 0

*/
int len =strlen(str);//不包含\0如果少就包含空格所以整体字符大一个
printf("%d\n",len);

if (str[len-1]=='\n') {
str[len-1]='\0';
}
for (int i = 0; i < 10 ; i++) {
printf("%d",str[i]);
}
printf("\n");

fputs(str,stdout);//不会自动换行
printf("\n");
puts(str);//带换行

/*
总结果:
aaa
aaa

97 97 97 10 0 95 -1 127 0 0 4
97 97 97 0 0 95 -1 127 0 0
aaa

*/

return 0;

</span>


 



2).const使用
 const int Mx =10;
   
//常量是read
only
   
int *p =&Mx;
   *p = 100 ;//强制修饰常量
   
printf("Mx = %d , *p =%d\n",Mx,*p);
   
//Mx = 10, *p = 100

   
const int Mx =10;
   
//常量是read
only
    
   
int *p =&Mx;
   
//intializingint * with an expression of type const       int * discards qulifier
   *p = 100 ;//强制修饰常量
   
printf("Mx = %d , *p =%d\n",Mx,*p);
   
//Mx = 10, *p = 100
    
   
//主要是看const和*的位置
   
//1.const修饰的指针变量指向可变
const在 *左边,
   
int a = 10 ;
   
int b = 20 ;
   
const int *p1 =&a;
               p1=&b;//指向可以改变
    *p1=1000;//read-onlyvariable is not assignable
   
//p1指向的变量的值是不能改变
    
   
const int *p2 =&b;
              p2 =p ;
    *p2=1000;//read-onlyvariable is not assignable
    
   
//2.const修饰的指针变量变量指向的变量值可以变,指向不能变
   
//const在 *的右侧指向的值可以改变,指向不可以
   
int * const p3 = &a;
    *p3 =2000 ;
    p3=&b;//read-onlyvariable is not assignable
    
   
//3.指向和值都不能改变
   
//const在 *的两侧
   
const int *
const p4 = &a;
    *p4 = &b;//read-onlyvariable is not assignable
    *p4 = 1000;//read-onlyvariable is not assignable
 

二.内存管理的基本概念


 

2).动态即是运行的时候分配的



   


 


  


 


3).动态内存分配的好处
1、当你定义了一个指针,而且要往里面写数据时,必须要动态分配内存给他。

2、动态分配的内存在堆上,你有权利决定什么时候将他释放掉。

3、动态分配的内存请记得一定要释放掉,不然容易引起内存泄露。
管理用户分配的内存空间

2).常见的动态内存分配函数
 




int *p = (int*)malloc(4*sizeof(int));//从内存的堆区分配16个字节的内存空间
if (p != NULL){
*p = 10 ;
*(p+1) = 100 ;
*(p+2) = 1000 ;
*(p+3) = 10000 ;
printf("%p\n",p);
printf("%p\n",p+1);
printf("%p\n",p+2);
printf("%p\n",p+3);

for (inti = 0 ; i< 4; i++) {
printf("%d\n",*(p+i));
}

}

/*
0x100100480
0x100100484
0x100100488
0x10010048c
10
100
1000
10000
*/
3).野指针和内存泄露



 
  
int *p = (int*)malloc(4*sizeof(int));
   
//该句话会造成内存泄露
 
   
free(p);//释放内存空间
free空间的首地址 p为野指针
   
//p =NULL;
    *p =100;
   
printf("%d\n",*p);
   
//还是*p还是存放了地址可以进行访问
   
//但是逻辑上不能让他继续访问此时要将p
= NULL;
   
//再访问就会报错
    
   
return 0;
 
在p释放之前,先释放堆区的内存空间
指针被释放后再去使用,指针已经不存在,也会成为野指针
 
4).free函数的使用



 
 
5).指针函数
int* max(int a,int b){
//ab 在 *max分配的内存空间里形参新分配的空间和实参地址不一样

printf("%p\n",&a);
printf("%p\n",&b);
//returna>b?&a:&b;
return NULL;

}
int* max2(int*a ,int* b){
//形参和实参地址不一样实参和形参是地址传递,没有分配新的空间

printf("%p\n",a);
printf("%p\n",b);
return *a>*b?a:b;

}
int main(intargc,const char* argv[]) {

int a = 3 ,b= 4;
printf("a =%p\n",&a);
printf("b =%p\n",&b);
//int*p=max(a,b);
int *p=max2(&a,&b);
printf("%p\n",p);
/*
a = 0x7fff5fbff78c
b = 0x7fff5fbff788
0x7fff5fbff78c
0x7fff5fbff788
0x7fff5fbff788
*/
return 0;

char *printDay2(intn ){

char *printDay[20];

switch (n) {
case 1:
*printDay="MONDAY";
break;
case 2:
*printDay="TUESDAY";
break;
case 3:
*printDay="WEDNESDAY";
break;
case 4:
*printDay="THURSDAY";
break;
case 5:
*printDay="FRIDAY";
break;
case 6:
*printDay="SATURDAY";
break;
case 7:
*printDay="SUNDAY";
break;

default:
*printDay="输入错误!";
break;
}

return *printDay;

}
int * getMax (int*arr ,int len){

int max = *arr ;
for (int i = 1;i<len; i++) {
if (*(arr+i)>max) {
max=*(arr+i);
}
}
return &max;
//addressof stack memory associated with local variable 'max' returned
}
int main(intargc,const char* argv[]) {

int arr[10]={11,22,3230,444,533,62,7,83,9,22};
printf("%s\n",printDay2(9));
printf("%d\n",*(getMax(arr,10)));
return 0;
}


6).函数指针

定义一个指针变量存放函数名的指针就叫函数指针
 
#include<stdio.h>

int sum(int a ,int b)
{
return a + b ;
}

int main(intargc,const char* argv[]) {

//定义函数指针可以不写形参
int (*p1)(int ,int);
//初始化函数指针
p1=sum;
printf("%d\n",p1(2,3));
printf("%d\n",(*p1)(2,3));
//5
return 0;
}



三.构造类型
数组类型,结构体类型,共用体类型
结构体:由若干成员组成
结构体定义完成后,计算机并不会给结构体分配内存空间
会在定义结构体变量后,分配内存空间
#include<stdio.h>
#include<string.h>
//1.先定义结构体
struct Student{

int sno ;
char name[20];//char*name;
char sex ;
int age;
float score ;
};
structStudentstud1,stud2,stud3;

//2.定义一个学生结构体
struct stu{

int sno ;
char name[20];//char*name;
char sex ;
int age;
float score ;
}stud5,stud6,stud7;

//3.匿名结构体
struct{
int sno ;
char name[20];//char*name;
char sex ;
int age;
float score ;

}stud8,stud9;

int main(intargc,const char* argv[]) {

//成员变量访问方法
stud1.age= 10 ;
//stud1.name="zhangsan";//arraytype 'char[20]' is not assignable
strcpy(stud1.name,"zhangsan");
stud1.sex='M';
printf("%s\n",stud1.name);

//stud1.name占用多少字节
printf("%ld\n",sizeof(stud1.name));
//utf-8国际通用编码 xcode默认的中文编码一个汉字占用3字节
//gb2312 gbk国际一个汉字占两字节
//stud1.name 字符串长度
printf("%ld\n",strlen(stud1.name));

//1.结构体初始化
//stud2={12,"zhangsans",'F',18,90.3f}; //expected expression

struct Studentstud10={12,"zhangsans",'F',18,90.3f};

//2.指定元素初始化
struct Studentstud11={.name="zhangsans"};


2).结构体数据成员对齐的意义
 


 3).结构体对齐的含义



 4).内存之间大小的倍数,结构体大小的计算方法和步骤
 



#include<stdio.h>
struct Student{

int sno ;//4
char sex ;//1
float score ;//4
};
struct Student2{

short sno ;//2
char sex ;//1
float score ;//4
};
struct Student3{

short sno ;//2
char sex ;//1
float score ;//4
double d;//8
};
struct Student4{

char sex[13] ;//4 16还空余3个
char score[13] ;//3 12(12个字节实际存储10个)
int d;//4
};
int main(intargc,const char* argv[]) {

struct Studentstd1;
printf("%ld\n",sizeof(std1));//12
//计算结构变量再内存中占用的字节数的方法
//1.先找对其模数,结构体变量中基本数据类型占字节数最大的那个
//2.在计算结构体变量中各个成员占用字节和

struct Student2std2;
printf("%ld\n",sizeof(std2));//8

struct Student3std3;
printf("%ld\n",sizeof(std3));//16
//double的位置如果在float之上结果为24

struct Student4std4;
printf("%ld\n",sizeof(std4));//32
return 0;
}

函数外部定义的结构体类型类似全局变量
 全局作用域:从自定义的哪一行开始直到本文件结束为止

5).作用域分类
结构体根据作用于可以分为全局结构体,局部结构体
局部变量的结构体会覆盖全局的

6).结构体数组定义



#include<stdio.h>
#define LEN5
struct person {

char name[8] ;
char telNum[12];

};
int main(intargc,const char* argv[]) {

struct personcontacts[LEN];

for (int i = 0; i < LEN ; i++) {
scanf("%s%s",contacts[i].name,contacts[i].telNum);
}

for (int i = 0; i < LEN ; i++) {
printf("姓名:%s,电话:%s\n",contacts[i].name,contacts[i].telNum);
}

return 0;
}


 
 7).指向结构体变量的指针



8).指针访问结构变量属于间接访问
 #include<stdio.h>
#include<string.h>
struct person// struct是关键字 person是结构体名
{

char name[8] ;
char telNum[12];
char *id;
int age ;

}per1; //结构体变量名

int main(intargc,const char* argv[]) {

structperson *p = &per1;//p是结构体指针
//结构体指针间接访问成员值的方法
//1).(*p).age; (*p)相当于per1
//2).p->agep是结构体指针的时候写法
(*p).age =10;
(*p).id="2332";
strcpy(p->name,"sdsd");
// strcpy((*p).name,"sdsd");
printf("%s\n",(*p).name);
//incompatiblepointer to integer conversion to 'char' from char[5]
//(*p)->age =100;
//memberreference type 'struct person' is not a pointer ,maybe you
//meant touse '.' to fix it
return 0;
}



// main.c
// 结构体嵌套
//
// Created by CHINGWEI_MACPC on 15/11/6.
// Copyright © 2015年 itcast. All rights reserved.
//

#include<stdio.h>
struct Time {

int hour ;
int second ;
int minite ;
};
struct Date
{

int month;
int day ;
int year ;
struct Timetime ;

};
struct Student
{

char name[8] ;
int age ;
float score ;
struct Datebirthday;

//可以嵌套自己类型的结构体指针
//struct Student stu; //错误书写
//structStudent *stu;

};

int main(intargc,const char* argv[]) {

struct Studentstu1={"mike",18,89.5f,{2,12,2006,{10,23,13}}};
printf("姓名:%s,年龄:%d,成绩:%f,生日:%02d/%02d/%d,时间:%02dh:%02dm:%ds\n",
stu1.name,stu1.age,stu1.score,stu1.birthday.day
,stu1.birthday.month,stu1.birthday.year,stu1.birthday.time.hour,stu1.birthday.time.minite,stu1.birthday.time.second);

struct Person// struct 是关键字 person是结构体名
{

char name[8] ;
int age ;

struct Person*children;

};
//结构体嵌套指针的使用
struct Personkim={"kim",20,NULL};

structPerson p1 ={"小白",38,&kim};

structPerson p2 ={"小白",38,&kim};

printf("名字:%s,年纪:%d,儿子:%s\n",p1.name,p1.age,(*p1.children).name);

//便于理解方法2 p2.children->name
printf("名字:%s,年纪:%d,儿子:%s\n",p2.name,p2.age,p2.children->name);

return 0;
}


结构体成员值作为函数参数



#include<stdio.h>
struct Student
{

char name[8] ;
float score ;

};
void xiugai(floatscore )
{
score=2.2f;
}
void printScore(structStudent stu)
{

stu.score=2.2f;

}
int main(intargc,const char* argv[]) {

struct Studentstu1={"liu",12.3f};

//1.结构体成员变量的成员值作为函数参数是值传递
xiugai(stu1.score);
printf("%s,%f\n",stu1.name,stu1.score);

//2.用结构体变量作为函数的参数也是值传递
printScore(stu1);
printf("%s,%f\n",stu1.name,stu1.score);
return 0;
}
结构体指针作为函数参数
将地址传递给函数
#include<stdio.h>
struct Student
{

char name[8] ;
float score ;

};
void printScore(structStudent *stu)
{

(*stu).score=2.2f;

}
int main(intargc,const char* argv[]) {
struct Studentstu1={"liu",12.3f};
//liu,2.200000
printScore(&stu1);
printf("%s,%f\n",stu1.name,stu1.score);

return 0;
}
枚举类型,基本数据类型,不是构造类型,因为不能再分解为任何基本类型



 #include<stdio.h>
enumweek2{KMon1,KTue1,KWed1=5,KThur1,KFri1,KSta1,KSun1};
int main(intargc,const char* argv[]) {

//定义变量 1.
enum week1{KMon,KTue,KWed,KThur,KFri,KSta,KSun}iWeek1;
//纠正型变量
//2.
enum week2iWeek2;

//赋值
iWeek1=KMon;//0
iWeek2=KFri1;//7
printf("%d\n",iWeek1);
printf("%d\n",iWeek2);
return 0;
}

#include<stdio.h>
int sum(int a ,int b ){

return a+b;
}
int main(intargc,const char* argv[]) {

//1.基本数据类型
typedef intINTERGER;

//2.用在数组,给数组起别名
typedefint ARRAY[5];//相当于
ARRAY arr1 ={5,4,5,6,7};
for (int i = 0; i < 5 ; i++) {
printf("%d\n",arr1[i]);
}
//3.给结构体起别名 1)
struct Person {
int age ;
char *name;

};
typedef struct Person P;
P person2={22,"nmle"};
printf("%d,%s\n",person2.age,person2.name);

//3.给结构体起别名 2)
typedef struct Car {
int age ;
char *name;

}MYCAR;
MYCAR car1 = {22,"sdsd"};
printf("%d,%s\n",car1.age,car1.name);

//3.给结构体起别名 3)
typedef struct {
int age ;
char *name;

}IPHONE;
IPHONE iP = {22,"sdsd"};
printf("%d,%s\n",iP.age,iP.name);

//4.给枚举起别名
//
typedef enumSex{Kse1,Kse2,Kse3}Isex;

typedef enum {Kw3,Kw2,Kw1}weekday;

typedef enum Sex S ;

S s1 ,s2;

s1=Kse2;
s2=Kse3;

//5.给函数指针

typedef int(*FUN)(int,int);
FUN f1,f2;
f1=sum;
f2=sum;
printf("%d\n",f1(2,3));
printf("%d\n",f2(4,3));

return 0;
}


预处理命令编译之前的工作
#开头的预处理命令
无参宏定义方法



 


#include<stdio.h>
#define LEN5
#define X (x*y+2*3)//最好加一个括号
#define Y x*y+2*3

#define PI3.14
#define R4
#define AREA PI*R*R//宏的嵌套
#define INT1 int//起别名

int main(intargc,const char* argv[]) {

#undef LEN
int a[R+4];//int a[6]
int x=1 ,y=1;
//1.宏的作用域 #undef宏名取消宏定义
printf("X*X = %d\n",X*X);//49
printf("Y*Y = %d\n",Y*Y);//13

//2.宏的嵌套
printf("%.f\n",AREA);

//3.起别名
INT1 a1 = 12;
printf("a1 = %d\n",a1);
return 0;
}

无参数宏
#include<stdio.h>
#defineMAX(x,y) x+y
#defineequaL(m,n) m=x+y;n=x*y;
//1.宏名和形参之间不能有空格
int main(intargc,const char* argv[]) {
// insertcode here...
int r = 1 ;
printf("%d\n",MAX(r, r));//2

int x = 2 , y =3;
int i ,j ;
equaL(i, j);//4
// a+3+y,a-1+y
printf("%d,%d\n",i,j);

return 0;
}

// 有参宏应用

#include<stdio.h>
#defineMAX(a,b) a>b?a:b
int main(intargc,const char* argv[]) {

printf("Max(32,444)=%d\n",MAX(32, 444));
return 0;
}

// typedef和define的区别
//
// Created by CHINGWEI_MACPC on 15/11/9.
// Copyright © 2015年 itcast. All rights reserved.
//

#include<stdio.h>
#defineINT1 int
typedefint INT2;
#defineINT3 int*
typedefint* INT4;
int main(intargc,const char* argv[]) {
//宏定义变量
int num = 10;
INT1 a ,b ;
a=10;
b=10;
printf("a = %d\n",a);

//别名定义变量
INT2 a1,b1;
a1=100;
b1=100;
printf("a1 = %d\n",a1);

//宏定义变量
INT3 a3 ,b3 ;//只有 int *a3, 只有a3是指针变量
a3=#
b3=num;
printf("a3 = %d,b3=%d\n",*a3,b3);

//别名定义变量
INT4 a4,b4;//a4,b4都是指针变量
a4=#
b4=#
printf("a4 = %d,b4=%d\n",*a4,*b4);

return 0;
}


 


 
  条件编译:
       发生在预处理阶段,在编译之前做的事情
       
       核心:根据条件编译指定的代码
       条件不同:编译的部分也不同,生成的目标文件也不同
.o大小不同
 
 */
#include<stdio.h>
#define score100
int main(intargc,const char* argv[]) {
#if score <60
printf("Grade :F");
#elif score <=69
printf("Grade : D");
#elif score <=79
printf("Grade : C");
#elif score <=89
printf("Grade : B");
#else
printf("Grade : A");
#endif
printf("\n");
return 0;
}


 
 
只编译一部分,



 



// 条件编译指令
//
// Created by CHINGWEI_MACPC on 15/11/9.
// Copyright © 2015年 itcast. All rights reserved.
//

#include<stdio.h>
#define DEBUG11
int main(intargc,const char* argv[]) {
int a =0 ;
#ifdefDEBUG1
a = 10 ;
#else
a=10000;
#endif
printf("%d\n",a);
printf("%d\n",DEBUG);
#ifndef DEBUG2//如果没有定义宏
a= 100 ;
#else
a=-1;
#endif
printf("%d\n",a);
return 0;
}

#include<stdio.h>
#define DEBUG11
#if DEBUG1 ==1
//显示调试信息
#defineLog(format,...) printf(format,## __VA_ARGS__);
//...表示可变参数 //##可以有一个或者多个
#else
//不显示调试信息
#defineLog(format,...);
#endif

void test2(){

Log("test------->%-5.2f ,%d,%d\n",10.3f,3,30);
}
void test(){

Log("test ----- >%d\n",10);
}
int main(intargc,const char* argv[]) {

Log("xxxxxxx----->%d\n",10);
test();
test2();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息