高级c语言(五)

embedded/2024/9/22 21:37:52/
输出缓冲区:

当我们使用标准库的输出系列函数打印数据到屏幕,数据并不会立即显示到屏幕上,而先存储到一块内存中,我们把这块内存称为输出缓冲区,等满足相关条件后,再从缓冲区中显示到屏幕,相关条件有:

1、从输出状态切换到输入状态。
2、缓冲区满了,1k=1024个字节,系统会把缓冲区中所有数据一起显示到屏幕了。
3、程序正常结束时,系统会把缓冲区中所有数据一起显示到屏幕了。
4、遇到'\n'时,'\n'前面的数据会立即显示到屏幕上。
5、调用fflush(stdout) 强制刷新,会把立即输出缓冲区中所有数据一起显示到屏幕了。
总结:缓冲区机制的目的是为了提高输入输出效率
练习1:实现一个动态时钟,在屏幕上动态显示出 hh:mm:ss
#include <unistd.h>
#include <stdlib.h>
int main(int argc,const char* argv[])
{int sec = time(NULL);   
​for(;;){   system("clear");printf("%d:%d:%d",(sec/3600+8)%24,sec/60%60,sec%60);    fflush(stdout);sleep(1);sec++;}
}
​

输入缓冲区:

当我们从终端输入数据给程序时,系统并没有立即把数据交给程序读取,而先存储到了一块内存中,我们这块内存称为输入缓冲区,直到我们按下Enter键时,系统才会把缓冲区中的数据给程序读取。

当我们输入的数据过多,或者类型不匹配,标准的输入系列函数就会读取失败,或只读取一部分,剩余的数据就会残留缓冲区中,影响后续数据的输入,当我们发现这情况情况后,应先清理输入缓冲区,后续的数据才能正常输入

清理输入缓冲区的方式:

方法1:
while('\n' != getch()); //  清空缓冲区,直到按下回车结束
​
方法2:正则表达式
scanf("%*[^\n]");   //  从缓冲区中读取任意类型数据并丢弃,直到遇到'\n'
scanf("%*c");       //  从换乘区中读取一个字符并丢弃
​
方法3:
stdin->_IO_read_ptr = stdin->_IO_read_end;  
//  设置输入缓冲区的位置指针到缓冲区末尾,此时缓冲区会被操作系统自动清空
​
注意:1、方法3只能在Linux系统中使用2、如果输入缓冲区中本来就没有垃圾数据,使用方法1和方法2就需要你手动多输入一个'\n'作为垃圾数据,程序才能往下走

字符:
什么是字符:

字符就是符号或图案,但在计算机中以整数形式存在,当需要显示时,会根据ASCII表中的对应关系显示出相应的符号或图案。

在C语言中使用char类型的变量存储字符的ASCII码值,也就是使用整数进行模拟字符,标准的ASCII码表的范围是:0~127,共128个字符,其他的语种,使用-128~-1进行设计字符编码,比如中文的汉字,使用的是2~3字节存储一个汉字。

重要的字符:
'\0' ASCII值是 0  空字符  字符串的结束标志
'0' ASCII值是 48
'A' ASCII值是 65
'a' ASCII值是 97
输出:
printf(“%c”,ASCII值);
putchar(ASCII值);
字符的输入:
char ch;
scanf("%c",&ch);
ch = getchar();
注意:

当先输入数值型数据(整数形、浮点型),再输入字符型数据时,前一次的输入会残留一个'\n'或空格,影响字符型数据的输入,是缓冲区在影响字符的输入

有以下方法解决:
方法1:增加一个空白字符的接收函数
scanf("%*c");
getch();
getchar();
​
方法2:在%c前面增加一个空格
scanf(" %c");
​
方法3:全部清空输入缓冲区
stdin->_IO_read_ptr = stdin->_IO_read_end;
练习2:先输入n的值,再连续输入n个字符,统计出每个字符出现的次数
#include <stdio.h>
​
int main(int argc,const char* argv[])
{int n;printf("请输入n的值:");scanf("%d",&n);
​char arr[128] = {},ch;for(int i=0; i<n; i++){scanf(" %c",&ch);                                                                        arr[ch]++;}for(int i=0; i<128; i++){if(arr[i]){printf("%c 出现了%hhd次\n",i,arr[i]);}}
}
​

aaabbdce

a 3 b 2 d 1 c1 e1

判断字符类型的函数:
函数名函数功能
isalnum()当字母或数字字符时, 返回真值
isalpha()当字母字符时, 返回真值
iscntrl()当控制字符时, 返回真值
isdigit()当数字字符时, 返回真值
isgraph()当非空格可打印字符时, 返回真值
islower()当小写字母字符时, 返回真值
isprint()当可打印字符时, 返回真值
ispunct()当标点字符时, 返回真值
isspace()当空格字符时, 返回真值
isupper()当大写字母字符时, 返回真值
isxdigit()当十六进制字符时, 返回真值
串型结构:

由若干个相同类型的数据组成顺序表(数组),在数据的末尾有一个结束标志,在使用这种数组时,可以不关心数组的长度。并且串型结构的处理都是批量性的

#include <stdio.h>
​
void show_string(int arr[])
{for(int i=0; arr[i] != ~0; i++){   printf("%d ",arr[i]);}   
}
​
int main(int argc,const char* argv[])
{int arr[] = {33,5,0,63,34,23,5,~0,32,23,56};             show_string(arr);
}

字符串:
什么是字符串:

由字符类型组成的串型结构,它的结束标志是'\0',使用它可以存储单词、句子、文章、汉字等更丰富的信息,一般使用char类型的数组存储。

// 定义字符串时,要为'\0'预留位置
char arr1[] = {'H','e','l','l','o','\0'};
char arr2[10] = {'H','e','l','l','o'};
字符串字面值:

1、"由双引号包括着的若干个字符"

2、它是以常量字符数组的形式存在,末尾隐藏着一个'\0'。

3、它们会被存储在text内存段,一旦强行修改就会出现段错误。

4、使用指针指向字符串字面值时,一定要用const加以保护,防止出现段错误,宁可出现编译时的错误,也不要出现运行时的错误。

5、编译器会优化它的存储,相同的字符串字面值,只会存储一份在text内存段中。

6、最常用的是用它给字符数组初始化,char arr[] = "hello" 编译器会自动拷贝字符串到数组的内存中(包括'\0'),完成初始化就有了两份字符串存储在内存中,一份存储在stack\data,另一份还存储在text。

注意:使用字符串字面值给字符数组赋值,只能在定义字符数组时使用,这是编译器帮忙完成拷贝的,在完成字符数组的定义后,只能使用strcpy函数对字符串进行赋值。memcpy

#include <string.h>int main(int argc,const char* argv[])
{char str[] = {'a','b','c','1','2',0};char str1[5] = {'A','B','c','1','2'};str[0] = 'A';printf("%s\n",str);printf("%s\n","hehehedijfdio");printf("%s\n","hehehedijfdio");const char* p = "hehe";//   text内存段const char* p1 = "hehe";//  text内存段printf("%p %p %s\n",p,p1,p);
//  p[0] = 'H';char str2[] = "hello world hehexiaixijefikdfm";str2[1] = 'E';                                                                               
//  str2 = "hehe";strcpy(str2,"xixihaha");printf("%s\n",&str2[9]);}
字符串的输出:
printf("%s",字符串的首地址);
puts(字符串的首地址); // 输出完字符串后会再输出一个\n
字符串的输入:
scanf("%s",存储字符串的首地址);
缺点:不能输入带有空格的字符串char *gets(char *s);
返回值:就是s,为了链式调用
缺点:直接从终端中接收字符数据,遇到'\n',可以接收空格字符,但是它不检查数据的长度跟存储空间的关系,所以很容易接收过长产生段错误、脏数据,官方编译器不建议使用该函数,会产生警告char *fgets(char *s, int size, FILE *stream);
功能:可以从指定文件stream中读取不超过size-1个字符会自动在末尾添加'\0',并存储到s中,返回值也是s,为了链式调用
stream: 数据的来源,写stdin即可 stdout 一切皆文件
size:最多只能读取size-1个字符,必定会为'\0'预留位置
缺点1:如果输入的字符个数不足size-1个时,会把最后输入的'\n'一起接收
缺点2:如果输入的字符个数超过size-1个时,超出部分的字符数据会继续残留在输入缓冲区中,会继续影响后序的输入解决方法:char usr[6] = {};printf("请输入字符串:");fgets(usr,6,stdin);int len = -1;//  计算出'\0'下标为lenwhile(usr[++len]);//  检查'\0'前面是否是'\n'if('\n' == usr[len-1]){//  证明输入不足size-1usr[len-1] = '\0';}else{//  证明输入超过size-1个,\n在缓冲区中,有残留//  清理输入缓冲区//while('\n' != getch());stdin->_IO_read_ptr = stdin->_IO_read_end;}#include <stdio.h>                                                                                      char* my_fgets(char *s, int size)
{if(NULL == s)return NULL;fgets(s,size,stdin);int len = -1;while(s[++len]);if('\n' != s[len-1])stdin->_IO_read_ptr = stdin->_IO_read_end;elses[len-1] = '\0';return s;
}int main(int argc,const char* argv[])
{char str[10] = {};my_fgets(str,10);printf("---%s---\n",str);
}

操作字符串的常用函数:
size_t strlen(const char *s);
功能:计算字符串的长度,不包括'\0'char str[] = "he\0he \ni";printf("strlen:%d\n",strlen(str));	2printf("sizeof:%d\n",sizeof(str));  9printf("sizeof:%d\n",sizeof("xixixx")); 7printf("strlen:%d\n",strlen("xixixx")); 6char* p = "xixixx";                     printf("sizeof:%d\n",sizeof(p));	指针 4\8printf("strlen:%d\n",strlen(p));	6简答题:sizeof(运算符)跟strlen (函数)的区别?char *strcpy(char *dest, const char *src);
功能:把字符串src拷贝到dest处,相当于 = 运算符
注意:会把src末尾的'\0'一起拷贝过来char *strcat(char *dest, const char *src);
功能:把src字符串追加到dest的末尾  相当于 += 运算符
注意:从dest的\0开始追加src,并且会把src的\0一起追加过来int strcmp(const char *s1, const char *s2);
功能:按字典序比较两个字符串s1 > s2 返回正数s1 < s2 返回负数s1 == s2 返回0逐个字符进行比较,一旦出结果立即结束,后面的不再比较
重点笔试题:
练习:自己实现 strlen、strcpy、strcat、strcmp四个函数的功能(不能调用str系列函数)
#include <stdio.h>size_t my_strlen(const char* s)
{const char* temp = s;while(*temp) temp++;return temp - s;
}char* my_strcpy(char* dest,const char* src)
{char* temp = dest;                             //  必须把src末尾的'\0'拷贝给destwhile(*temp++ = *src++);return dest;
}char* my_strcat(char* dest,const char* src)
{char* temp = dest;//  temp移动到dest的'\0'位置while(*temp) temp++;//  把src逐个字符拷贝到dest末尾while(*temp++ = *src++);return dest;
}int my_strcmp(const char* s1,const char* s2)
{while(*s1 == *s2 && *s1) s1++,s2++;return *s1 - *s2;/*if(*s1 > *s2) return 1;if(*s1 < *s2) return -1;return 0;*/
}int main(int argc,const char* argv[])
{char str1[10] = "abcde";char str2[10] = "ccc";char str3[10] = "bb";printf("my_strlen:%d\n",my_strlen(str1));printf("my_strcpy:%s\n",my_strcpy(str1,str2));printf("my_strcat:%s\n",my_strcat(str3,str2));printf("my_strcmp:%d\n",my_strcmp("aac","abc"));
}

字符串相关函数:
int atoi(const char *nptr);
功能:字符串转int类型long atol(const char *nptr);
功能:字符串转long类型long long atoll(const char *nptr);
功能:字符串转long long类型double atof(const char *nptr);"2.4"
功能:字符串转double类型char *strstr(const char *haystack, const char *needle);
功能:查找haystack中是否存在needle
返回值:needle第一次在haystack出现的位置,如果找不到返回NULL
"abcdefcd"  "cad"char *strchr(const char *s, int c);
功能:查找字符串s中是否有字符c。
返回值:c在s中第一次出现的位置,如果找不到返回NULL。int sprintf(char *str, const char *format, ...);
功能:把任意类型的数据输出到str中 把任意类型的数据拼接成字符串
返回值:字符串str的长度int sscanf(const char *str, const char *format, ...);
功能:从str中读取任意类型数据 从字符串中解析任意类型的数据
返回值:成功读取到的变量个数int n = 10; double d = 3.14;long long l = 444;char str[256] = {}; sprintf(str,"学号:%d 分数:%lf 总分:%lld\n",n,d,l);printf("--%s--",str);int n1 = 0;double d1 = 0;long long l1 = 0;sscanf(str,"学号:%d 分数:%lf 总分:%lld",&n1,&d1,&l1);printf("%d %lf %lld\n",n1+10,d1,l1);         

电子通讯录作业:
联系人信息:

姓名、性别、联系电话

功能:

1、添加联系人

2、删除联系人 (按名字删除)

3、修改联系人信息 (按名字查找)

4、查询联系人 (按名字或者电话查询 选做:支持模糊查询)

5、显示所有联系人

6、该通讯录最多只存储100个联系人

7、选做:考虑数据存储在堆内存中

#include <stdio.h>//	名字
char name[100][20];
//	性别
char sex[100];
//	电话
char tel[100][12];int main()
{for(;;){//	功能提示puts("1、添加联系人");puts("2、删除联系人");puts("3、修改联系人");puts("4、查询联系人");puts("5、列出联系人");puts("6、退出系统");switch(getch()){case 1:	//	执行添加联系人的函数break;...}}
}


http://www.ppmy.cn/embedded/113507.html

相关文章

DAY 13 : 排序

定义 稳定排序和非稳定排序 设文件f&#xff08;R1……Ri……Rj……Rn&#xff09;中记录Ri、Rj&#xff08;i≠j&#xff0c;i、j1……n&#xff09;的key相等&#xff0c;即KiKj。 若在排序前Ri领先于Rj&#xff0c;排序后Ri仍领先于Rj&#xff0c;则称这种排序是稳定的&…

机器学习与深度学习的区别

1. 定义 机器学习&#xff08;Machine Learning&#xff09; 定义&#xff1a;机器学习是一种通过构建和训练模型&#xff0c;使计算机能够从数据中学习并做出预测的技术。它包括一系列算法&#xff0c;这些算法可以从数据中识别模式&#xff0c;并使用这些模式对新数据进行预…

静态库 动态库

https://blog.csdn.net/mahoon411/article/details/113565482 库&#xff1a;可执行代码的二进制文件&#xff0c;里面有可以直接使用的函数&#xff0c;变量等&#xff1b;不能单独运行 因为 Linux 和 Win 的链接器、汇编器、编译器的不同&#xff0c;相同代码的库不同 Lin…

QT<24> Qt和windows中获取CPU序列号号以及主板序列号

前言&#xff1a;在qt中获取CPU和主板唯一序列号&#xff0c;可以在程序构造函数中判断是否与windows中一致&#xff0c;不一致可以直接退出程序&#xff0c;防止程序daoyong。 一、获取电脑CPU唯一序列号 QString MainPage::get_cpu() {QString cmd"wmic cpu get proc…

计算机组成原理-存储系统(二)半导体存储器

2.1DAM芯片 分类&#xff1a; DRAM芯片&#xff1a;使用栅极电容存储信息SRAM芯片&#xff1a;使用双稳态触发器存储信息 核心区别&#xff1a;储存元不一样 2.2DRAM和SRAM的比较 对于DRAM中&#xff1a; 1&#xff1a;电容内存储了电荷0&#xff1a;电容内未存储电荷 DR…

【百日算法计划】:每日一题,见证成长(016)

题目 环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环 思路1 用哈希表的思想&#xff0c;遍历链表&#xff0c;判断节点在哈希表中是否存在。 public boolean hasCycle2(ListNode head) {HashSet<ListNode> hashSet new HashSet<>();ListNo…

VS2022中的调试

目录 前言&#xff1a; 使用&#xff1a; 调试&#xff1a; 前言&#xff1a; 在日益繁忙的工作环境中&#xff0c;选择合适的编程工具已成为提升开发者工作效率的关键。不同的工具能够帮助我们简化代码编写、自动化任务、提升调试速度&#xff0c;甚至让团队协作更加顺畅。…

Vue3+TypeScript+Vite+Less 开发 H5 项目(amfe-flexible + postcss-pxtorem)

参考文档 amfe-flexible&#xff1a;将根元素 html 的字体大小 fontSize&#xff08;1rem&#xff09; 设为 viewWidth / 10&#xff0c;以适配不同终端 postcss-pxtorem&#xff1a;将 px 单位转换为 rem 单位 安装依赖 pnpm add amfe-flexible pnpm add postcss-pxtorem …