C语言笔记(八):位域、文件访问、typedef自定义类型

位域

很明显,是对位进行操作的,目的就是为了节约存储空间

位域也是c里面的一种数据类型

语法:

struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度

和结构体相似首先先看定义

#include <stdio.h>

struct Dog{
    unsigned char a:1;
    unsigned char b:3;
}dog;
int main(){
printf("dog所占的字节:%d
",sizeof(dog));
return 0;
}

关于位域暂时先不过多了解,知道位域是为了节省存储空间,并使处理简便就行了

typedef

这个关键字从字面意思来看就是定义一个新类型。也就说,除了基本数据类型之外,可以自定义数据类型。比如我们之前使用的struct,以及union,都是自己的定义的类型,但是在声明以及使用的时候必须加上struct等关键字才能识别,在定义结构体的时候,也用到过了typedef关键字来创建一个结构体类型。且在声明结构体变量的时候没有用到struct关键字,详情看结构体的定义的方式四

使用typedf

一般将自定义的类型使用大写字母

#include <stdio.h>
int main ()
{

	typedef struct {
		//结构体类型里的属性,则可以通过变量来对结构体属性进行赋值等操作
		int  age;
		char  color [20];
	}Dogs;	//定义了小狗类型的结构体这里是定义在函数里面的
  	 Dogs dog1;
     Dogs dog2;
     Dogs dog3,dog4;
   return 0;
}

也可以对结构体使用 typedef 来定义一个新的数据类型名字,然后使用这个新的数据类型来直接定义结构变量,如下:

#include <stdio.h>
int main ()
{

	typedef struct Dogs{
		//结构体类型里的属性,则可以通过变量来对结构体属性进行赋值等操作
		int  age;
		char  color [20];
	}Dog;	//定义了小狗类型的结构体这里是定义在函数里面的
  	 Dog dog1;
     Dog dog2;
     Dog dog3,dog4;
   return 0;
}

这里将Dogs类型名字变成了Dog

typedef 和 #define的区别

  • typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
  • typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

比如使用#define 来定义两个别名

#include <stdio.h>
 
#define TRUE  1
#define FALSE 0
 
int main( )
{
   printf( "TRUE 的值: %d
", TRUE);
   printf( "FALSE 的值: %d
", FALSE);
 
   return 0;
}

typedef通常用来自定义类型或者修改类型的别名,在定义多个变量的时候能保证自己定义的类型所有的变量都是之前的同种类型。define不能

输入和输出(I/O )

输入in 输入out

格式化输入和输出

所谓的格式化也就是用%d或者%f等等来接收数据

代码实例:

//输入和输出
//scanf printf
//puts gets
//getchar putchar
#include <stdio.h>
int main()
    {
       
		  int a;
		  char ca [100],cb;
		  
//scanf 和printf 任意类型都可以操作

		  /*

		  printf("请你输入一个两位数的数字比如(99):
");//直接输出字符串也就是双引号里的内容

		  scanf("%d",&a);//使用scanf,将键盘输入的值赋值给变量a

		  printf("您输入的数字是:%d
",a);//格式话输出a,这里的a是int型所以用%d接
		
			*/

// puts gets 造作字符串

		    /*
		  
		  //从这里可以看到,puts函数输出,自带
回车,且只能输出字符串,也就说,打印输出双引号里的所有内容,不会识别或者
或%d等等
		  puts("请输入一个字符串:");

		  printf("使用printf格式化输出:%d
",gets(ca)); //也就是说,gets函数会返回键盘上输入的字符串

		  puts("使用 puts函数输出:");
		  puts(ca);//会返回一个0

				*/


//getchar()和putchar() 一般用来操作字符,都是对字符进行操作
	puts("请输入一个字符:");
	cb=getchar();//getchar会返回一个int型数字,且只会get键盘输入的首个字符
	putchar(cb);//putchar也会返回一个int型数字,且只会输出首个字符
	putchar('
');	//单引号,换行


			  return 0;
}

scanf()和printf()

输入也就是scanf函数:标准输入(键盘)读取并格式化

语法:scanf(“格式化规定符”,变量地址);

输出也就是printf函数:格式化输出到标准输出(屏幕)

语法:printf("格式化字符串", 参量表);

#include <stdio.h>
int main(){
    int a = 0;//定义一个默认的int型变量初始值为0
    printf("请输入你要打印的数据:");
    scanf("%d",&a)//格式化键盘上的数据
    printf("您输入的数是:%d",a);
    return 0;
}

非格式化输入和输出

getchar() 和 putchar() 函数

一般真对输入和输出对象是单个字符

getchar函数的原型是:int getchar(void) 函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。也就说,在回车后,只会获取到你键盘输入的第一个字符

putchar函数的原型是:int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。也就是说,打印的时候,指挥打印第一个字符;

#include <stdio.h>
 
int main( )
{
   	int  c;
    char a ='a';//定义一个变量a,初始值是123
   printf( "请你输入一个数,最好是两位以上的,才好出效果 :");
   c = getchar( );
   printf( "
你输入的值是: ");
   putchar( c );
   printf( "
");
   putchar(a);//打印输出一个123,实际上只会打印第一个字符
   putchar("
");//换行
   return 0;
}

putchar只能输出字符,且是首个字符

也就是说,putchar(c)和printf("%c",c);等价

getch()和getche()函数

长得和getchar很像,功能也是:这两个函数都是从键盘上读入一个字符。

两者的区别是getch()函数不将读入的字符回显在显示屏幕上,而getche()函数却将读入的字符回显到显示屏幕上。

利用回显和不回显的特点,这两个函数经常用于交互输入的过程中完成暂停等功能。

gets() 和 puts() 函数

一般针对输入和输出对象是字符串

gets()函数用来从标准输入设备(键盘)读取字符串直到回车结束,但回车符不属于这个字符串。其调用格式为:

gets(s);*//s为字符串变量(字符串数组名或字符串指针)*

gets(s)函数与scanf(“%s”, &s)相似,但不完全相同,使用scanf(“%s”,&s)函数输入字符串时存在一个问题,就是如果输入了空格会认为输入字符串结束,空格后的字符将作为下一个输入项处理,但gets() 函数将接收输入的整个字符串直到回车为止,gets()会吸收空格

puts()函数用来向标准输出设备(屏幕)字符串并换行,其调用格式为:

puts(s);//s为字符串变量(字符串数组名或字符串指针)

puts()函数的作用与语printf(“%s ”, s)相同。

int main()
{
  char s[20], *f;
  strcpy(s, "飞龙在天");
  f="Thank you";
  puts(s);
  puts(f);
}

(1)puts()函数只能输出字符串,不能输出数值或进行格式变换。
(2)可以将字符串直接写入puts()函数中。如:puts(“Hello, Turbo C2.0”);

scanf() 和 gets() 的区别

  • scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。回车也就是添加了一个空格在后面,所有就结束录入了。
  • gets() 认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束,所以,不管输入了多少个空格,只要不按下回车键,对 gets() 来说就是一个完整的字符串。换句话说,gets() 用来读取一整行字符串,能识别空格的。

文件读写

很好记,每个文件的操作函数都有个f,打开则是open则是fopen。关闭则是fclose。等等

打开文件

使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息

FILE *fopen( const char * filename, const char * mode );

filename 是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个:

模式 描述
r 打开一个已有的文本文件,允许读取文件。表示必须此文件已经存在
w 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。
a 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。
r+ 打开一个文本文件,允许读写文件。表示必须此文件已经存在
w+ 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。
a+ 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。

如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式:

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

看代码,打开一个已有的文件

#include <stdio.h>
int main()
{
     FILE *fp = NULL; //设置一个文件指针
	 fp = fopen("C:\Users\高冷的男神\Desktop\test.txt","r");
	if(fp == NULL ){
		printf("Fail to open file!
");
		exit(0);  //退出程序(结束程序) return 0;
	}else{
	printf("open success");
	}
	return 0;
}

默认指针是NULL,如果fp不为空,则表示打开文件成功

结果是打印的是open success

关闭文件

使用 fclose( ) 函数。函数的原型如下:

 int fclose( FILE *fp );

如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。

#include <stdio.h>
int main()
{
     FILE *fp = NULL; //设置一个文件指针
    //打开文件
	 fp = fopen("C:\Users\高冷的男神\Desktop\text.txt","r");
    //判断文件是否打开
	if(fp == NULL ){
		printf("Fail to open file!
");
		exit(0);  //退出程序(结束程序) return 0;
	}else{
		puts("open success");
	}
    
    //关闭文件流
	//记得用完关闭文件
    if(fclose(fp)==0){
        puts("文件关闭成功");
    }else{
        puts(fclose(fp));
    }
	return 0;
}

写入文件

写入文件,首先需要打开文件,且要有写入权限,比如w,或者r+等

方式一和方式二和方式三都会将文件里的内容清空,然后再写入新的数据

方式一和方式二和方式三都会将文件里的内容清空,然后再写入新的数据

方式一和方式二和方式三都会将文件里的内容清空,然后再写入新的数据

  • 这里记住fputc只能写一个字符,返回字符的ascll码
  • fputs能存字符串,返回的是一个非负数一般是0,
  • fprintf能存字符串,返回的是字符长度,这个长度包括了转义字符的长度,但是会记
  • 如果都写入失败,则都返回eof,一般是-1,

方式一fputc

int fputc( int c, FILE *fp );
  1. int :fputc返回的类型
  2. fputc:fputc函数名,固定了的
  3. int c:写入的内容(字符,int则是ascll里对应的字符)
  4. FILE*fp: 一个file类型的指针,也就是文件地址

逗号前面是写入的数据,逗号后面是地址

如果写入成功,则会返回这字符的是ascll表格对应值,bir a的值是65,如果失败,则返回-1(EOF)

这里可以直接转入一个字符,或者int型,也会自动翻译成字符的

方式二fputs

int fputs("hello", FILE *fp );

逗号前面是写入的数据,逗号后面是地址

如果写入成功,则会返回一个非负值一般都是0,如果失败,则返回-1(EOF)

方式三fprintf

int fprintf(FILE *fp,int c, )

和fputs相反,逗号前面是地址,逗号后面是要写是数据

这里注意,如果写入成功,则返回写入数据的长度,且要计算转义字符的长度的,比如说 也是占1个长度如果写入失败则返回-1 也就是EOF

代码实例:

#include <stdio.h>
int main()
{

	int fpts,fpr,fptc;
	char  a = 'D';
     FILE *fp = NULL; //设置一个文件指针
    //打开文件
	 fp = fopen("C:\Users\高冷的男神\Desktop\text.txt","w");
    //判断文件是否打开
	if(fp == NULL ){
		puts("文件打开失败");
		exit(0);  //退出程序(结束程序) return 0;
	}else{
		puts("file open success");
	}

	//写入文件
	 fptc = fputc(a,fp);
	 fpts = fputs("I love you fputs
",fp);
	 fpr = fprintf(fp,"hello c
");
	

	 //判断文件是否写入成功

	 //判断fputc的写入方式
	 if(fptc>0){
	 
	puts("fputc的写入方式成功");
	printf("fptc: %d
",fptc);
	 }else{
	 
		puts("fputc的写入方式失败");
			 printf("fptc: %d
",fptc);
	 }


	 //判断fputs的写入方式
	 if(fptc>0){
	 puts("fputs写入成功");
	 printf("fpts: %d
",fpts);
	 }else{
	 puts("fpts write fail");
	 printf("fpts: %d
",fpts);
	 }


	 //判断fprintf的写入方式
	 if(fptc>0){
	 puts("fprintf写入成功");
	 printf("fpr: %d
",fpr);
	 }else{
	 puts("fprintf write fail");
	 printf("fpr: %d
",fpr);
	 }
    


			//关闭文件流
			//记得用完关闭文件
			if(fclose(fp)==0){
				puts("文件关闭成功");
			}else{
				puts("文件关闭失败");
				puts(fclose(fp));
			}
	return 0;
}

读取文件

写用put,那么读则用get。文件到 读写,读,也就是将文件读取到内存里,然后显示在电脑上,写则是将内存里的东西,保存在文件里。

所以这里也有三种方式

方式一fgetc

int fgetc( FILE * fp );
  • 则是读取单个字符到计算机里
  • 返回值是读取的字符的ASCII码,如果发生错误则返回 EOF一般是-1。

方式二fgets

char *fgets( char *buf, int n, FILE *fp );

方式三fsanf

int fscanf(FILE *fp, const char *format, ...)

括号里,指针,接收类型。字符数组名

实例代码:

//文件读取
#include <stdio.h>
int main(){

	//定义一个文件指针打开一个文件,使用r权限,只读模式
	FILE *file = fopen("C:\Users\高冷的男神\Desktop\text.txt","r");


	 char fgc;
	//定义一个字符数组用来存放读取的字符或者字符串
	 char fgs[100];


	 //判断文件是否打开成功
	//判断指针地址是否为空,入股没有改文件,则找不到地址,则会给一个NULL指针
	if(NULL == file){
		puts("sorry,no found yours file");
		printf("file 的值是: %d
",file);
	
	}else{
		puts("文件打开成功,即将开始读取数据");


		//使用方式一,fgetc
		//fgetc:读取一个数据
		//fgetc() 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF
			fgc =  fgetc(file);
			putchar(fgc);
			putchar('
');//换行
			//判断fgetc读取成功了否
			//如果读取失败,或者结束,则会返回一个小于0的数,默认是-1
			(fgc >0) ?  printf("fgetc读取成功	fgetc的的返回值是:%c
",fgc):
			printf("fgetc读取失败	fgetc的的返回值是:%c
",fgc);



			//fgets()函数
			//char *fgets( char *buf, int n, FILE *fp );
			//(数组名,数组长度,文件指针)
			//返回的结果就是读取的字符串会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
			//如果这个函数在读取最后一个字符之前就遇到一个换行符 '
' 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。


		fgets(fgs, 255, file);
		puts(fgs);

		//fscanf 读取失败则返回一个小于0的数
		fscanf(file,"%s",fgs);
		puts(fgs);
	


	//关闭访问
		puts("文件读取结束,即将关闭访问文件调用fclose函数");
		if(0==fclose(file)){
			puts("文件访问关闭成功");
		}
		else{
			puts("文件访问关闭失败");
			printf("fclose函数的返回值是:%d
",fclose(file));
		}
	}


	return 0;
}
原文地址:https://www.cnblogs.com/yuxiangqiezi/p/13128625.html