一、位(适用于单片机)
位域、把一个字节拆开使用。分成不同的区域,每个区域还可以命名。使其对不同位域进行使用。
使用方法:
在结构体定义时,在结构体成员后面使用冒号(:)和数字来表示该成员所占的位数。
例:
#include
int main(void)
{
struct Test
{
unsigned int a:1; //给其a分配占一个二进制位
unsigned int b:1; //默认无符号整型占4个内存空间
unsigned int c:1;
};
struct Test test;
test.a = 0;
test.b = 1;
test.c = 1;
printf("a = %d b = %d c = %d\n", test.a, test.b, test.c);
printf("size of test = %d\n", sizeof(test));
getchar();
return 0;
}
结果:
a = 0 b = 1 c = 1 //3位;一个字节等于8位
size of test = 4 //4字节
//默认分配一个整型,在其int内分别为其分配。还有其29位内存未使用
无名位域
——位域成员可以没有名字,只要给出数据类型和位宽即可。
——无名位域一般用来填充或者调整内存。不能拿来使用。
例:
struct Test
{
unsigned int x:100;
unsigned int :200;
unsigned int z:300;
unsigned int :424;
}
注意:
//注意变量所占的坑位一定要能够存储其值
//位域的宽度不能超过它所依附的长度,如不能超过test的长度
//不能对位域进行取址运算
逻辑位运算符:(对两个或者两个以上进行判断)
只作用于整型数据,并且对数据当中每个二进制位进行运算。
移位运算符:(将二进制位进行左移或者右移)
左移位:"<<"
右移位:">>"
例:
#include
int main(void)
{
int value = 1;
while (value < 1024)
{
value <<= 1; //value = value << 1;
printf("左移的value = %d\n", value);
}
printf("————————————————————\n");
while (value > 0)
{
value >>= 1;
printf("右移的value = %d\n", value);
}
printf("\n");
getchar();
return 0;
}
结论:左移N位是乘以2的N次方,右移N位是除以2的N次方。(移位的效率是最高的)
注意:
—移位的操作数如果为负,或者右边的操作数大于左边操作数支持的最大宽度,表达式的结果属于“未定义行为”。
—有符号于无符号对移位运算符有着不同的影响。
二、文件操作
文件含义:是存储在某种长期存储设备或临时存储设备中的一段数据流。
类型:文本文件、二进制文件
文件操作流程:打开(必须)——读/写——关闭(必须)
(一)、打开文件
fopen()打开文件并返回文件指针
两个参数:path(路径,绝对路径与相对路径)、mode(模式,如只读模式等)。
返回值:
1.如果文件打开成功,则返回一个指向FILE结构的文件指针;
2.如果文件打开失败,则返回NULL并设置errno为指定的错误。
注意:打开到关闭中间有一个缓冲区。
(二)、读写操作
分为:随机读写、顺序读写
fgetc():用于从文件流中读取下一个字符并推进文件的位置指示器(用来指示接下来要读写的下一个字符的位置)。
参数:只有一个参数"stream"该参数是一个FILE对象的指针,指示下一个待读取的文件流。
返回值:将读取的unsigned char类型转换为int类型并返回。如果文件结束或者遇到错误则返回EOF。
注:fgetc()和getc()描述基本上一样。fgetc是一个函数,而getc则是一个宏的实现。
fputc():用于写入一个字符到指定文件中并推进文件的位置指示器
参数:参数C和stream,C指定待写入的字符、stream是一个FILE对象的指针,指定一个待写入的文件流。
返回值:如果函数没有错误,返回值是写入的字符、如果函数发生错误,返回值是EOF。
注:fputc()和putc()描述基本上一样。fputc()是一个函数,而putc()则是一个宏的实现。
例:
//把一个文件的内容以单字符形式传输到另一个文件中。
#include
#include
int main(void)
{
FILE *fp1,*fp2;
int ch;
if ((fp1 = fopen("test1a.txt", "r")) == NULL)
{
printf("文件打开失败!\n");
exit(EXIT_FAILURE);
}
if ((fp2 = fopen("test1b.txt", "w")) == NULL)
{
printf("文件打开失败!\n");
exit(EXIT_FAILURE);
}
while ((ch = fgetc(fp1)) != EOF)
{
fputc(ch, fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
fgets():用于从指定文件中读取字符串。最多读取size-1个字符'\0'就自动结束。'\n'会被作为一个合法的字符读取。
参数:三个参数,s、size、stream. s(字符型指针)用于指向存放读取字符串的位置、size指定读取的字符数(包括'\0')、stream是一个FILE对象的指针,指定一个待读取的数据流。
返回值:如果函数调用成功,返回s参数指向的地址;如果在读取字符串的过程中遇到EOF,则EOF指示器被设置下一读取地址;如果还未读取任何字符串就遇到EOF,则s参数指向的位置保持原来的内容,函数返回NULL;如果在读取的过程中发生错误,则error指示器被设置,函数返回NULL(注:s参数指向的内容可能被改变)
fputs():用于将字符串写入到指定文件中,'\0'不会被一并写入。
参数:两个,s、stream. s(字符型指针)指向存放待写入字符串的位置;stream是一个FILE对象的指针,指定一个待写入的数据流。
返回值:如果函数调用成功,返回一个非0值;如果函数调用失败,返回EOF。
例:
#include
#include
#define MAX 1024
int main(void)
{
FILE * fp;
char buffer[MAX];
if ((fp = fopen("test2.txt", "w")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fputs("写入第一段字符串\n", fp);
fputs("写入第二段字符串\n", fp);
fputs("写入第三段字符串\n", fp);
fclose(fp); //关闭是为了让字符串写入进文件,同时重置字符串指示器的位置
if ((fp = fopen("test2.txt", "r")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
while (!feof(fp)) //循环打印,feof用来检测文件是否是末尾(详细请查找手册)
{
fgets(buffer, MAX, fp);
printf("%s", buffer);
}
/*
feof检测到末尾指示器被设置(未读取完毕),返回一个非零;如果未被设置(读取完毕),返回一个0.
*/
fclose(fp);
return 0;
}
结果:
root@debian:~/C# gcc test2.c && ./a.out
写入第一段字符串
写入第二段字符串
写入第三段字符串
写入第三段字符串
//多打印了一行的原因在于“最后的'\n'会被作为一个合法的字符读取,然后退出读取”,再次读取,直接遇到EOF.及返回值如同第二点:如果还未读取任何字符串就遇到EOF,则s参数指向的位置保持原来的内容,函数返回NULL;
注意小例子:
/*
*printf与scanf本来是从终端输入输出
*fprintf与fscanf指定文件的输入和输出
*二进制文件进行读写,fputs可以指定对二进制操作,但该文件并不一定就是二进制文件
* */
#include
#include //输入输出函数
int main(void)
{
FILE *fp;
if ((fp = fopen("date.txt", "wb")) == NULL)//“b”二进制方式打开
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fputc('5', fp);
fputc('2', fp);
fputc('0', fp);
fputc('\n', fp);
fclose(fp);
return 0;
}
输出结果:
root@debian:~/C/test12/test12_2# cat date.txt
520
fscanf():用于从指定文件中读取格式化字符串。
fprintf():用于打印格式化字符串到指定文件中。
参数(它们的参数与printf和scanf的参数一样,只是输入的位置发生改变"添加了一个file结构体的指针"):(stream、format).stream是一个FILE对象的指针,指定一个待写入的数据流。format是一个格式化字符串,由格式化占位符和普通字符组成。
例子:
/*
*printf与scanf本来是从终端输入输出
*fprintf与fscanf指定文件的输入和输出
*例子:获取当前写入的字符串并打印到文件内
* */
#include
#include //输入输出函数
#include //为了localtime
int main(void)
{
FILE *fp;
struct tm *p;
time_t t;
time(&t);
p = localtime(&t);
if ((fp = fopen("date.txt", "w")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "%d-%d-%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
fclose(fp);
//读取写入文件
int year, month, day;
if ((fp = fopen("date.txt", "r")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fscanf(fp, "%d-%d-%d", &year, &month, &day);
printf("%d-%d-%d\n", year, month, day);
fclose(fp);
return 0;
}
二进制文件操作:
fread()函数与fwrite()函数
fread():用于从指定文件中读取指定尺寸的数据。
fread():用于从指定文件中写入指定尺寸的数据。
例子:
/*
*printf与scanf本来是从终端输入输出
*fprintf与fscanf指定文件的输入和输出
*例子:对二进制进行操作fread与fwrite
* */
#include
#include //输入输出函数
#include //对字符串的操作
struct Date
{
int year;
int month;
int day;
};
struct Book
{
char name[40];
char author[40];
char publisher[40];
struct Date date;
};
int main(void)
{
FILE *fp;
struct Book *book_for_write, *book_for_read;
book_for_write = (struct Book *)malloc(sizeof(struct Book));
book_for_read = (struct Book *)malloc(sizeof(struct Book));
//检查是否分配成功
if (book_for_write == NULL || book_for_read == NULL)
{
printf("内存分配失败!\n");
exit(EXIT_FAILURE);
}
strcpy(book_for_write->name, "《C Primer Plus》");
strcpy(book_for_write->author, "Stephen P rata");
strcpy(book_for_write->publisher, "人民邮电出版社");
book_for_write->date.year = 11;
book_for_write->date.month = 22;
book_for_write->date.day = 33;
if ((fp = fopen("date.txt", "w")) == NULL)//为了证明打开形式跟具体写入一致,没有加‘b’
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fwrite(book_for_write, sizeof(struct Book),1,fp);
fclose(fp);
if ((fp = fopen("date.txt", "r")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fread(book_for_read, sizeof(struct Book),1,fp);
printf("书名:%s\n",book_for_read->name);
printf("作者:%s\n",book_for_read->author);
printf("出版社:%s\n",book_for_read->publisher);
printf("出版日期:%d-%d-%d\n", book_for_read->date.year, book_for_read->date.month, book_for_read->date.day);
fclose(fp);
return 0;
}
结果:
root@debian:~/C/test12/test12_3# ./a.out
书名:《C Primer Plus》
作者:Stephen P rata
出版社:人民邮电出版社
出版日期:11-22-33
root@debian:~/C/test12/test12_3# vim date.txt
随机读写:
ftell()得到当前文件指针位置。
rewind()初始化文件指针(使文件指针回到文件头)。
fseek()设置文件流的位置指示器。如果函数成功返回0,如果失败返回非零。+-
函数原型:int fseek(FILE *stream, long offset, int fromwhere);
参数解析:stream指向文件流。offset指定从fromwhere参数的位置起偏移多少字节。fromwhere(SEEK_SET文件头、SEEK_CUR当前的读写位置、SEEK_END文件末尾)
/*
*录入相关信息并读取
* */
#include
#include
#define N 4
struct Stu
{
char name[24];
int num;
float score;
}stu[N], sb;
int main(void)
{
FILE *fp;
int i;
if ((fp = fopen("sorce.txt", "wb")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
printf("请开始录入成绩(格式:姓名 学号 成绩):\n");
for (i = 0; i < N; i++)
{
scanf("%s %d %f", stu[i].name, &stu[i].num, &stu[i].score);
}
fwrite(stu, sizeof(struct Stu), N, fp);//结构体用二进制写入
fclose(fp);
if ((fp = fopen("sorce.txt", "rb")) == NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fseek(fp, sizeof(struct Stu), SEEK_SET);
fread(&sb, sizeof(struct Stu), 1, fp);
printf("%s(%d)的成绩是:%.2f\n",sb.name, sb.num, sb.score);
fclose(fp);
return 0;
}