当前位置:   article > 正文

课堂案例代码 持续补充 文章-1

课堂案例代码 持续补充 文章-1

 B站视频 C++就业班  本文都是C语言的 前面的基础课程  ,从文章-2开始对应数据结构

1.文件读写相关

1.1. 文件版  四则运算

现在文件里用函数写进4个等式 但是不写结果 

在while循环中,如下处理每一行

然后用fgets读出每一行,sscanf提取变量值,进入switch算出结果,然后sprintf打印出带着结果的一个完整等式。

最会strcat拼接成一个大字符串(所有内容) w 模式清空文件并重写进去。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include<string.h>
  4. //文件版四则运算
  5. //在yunsuan.txt里写了4个算式
  6. //用fwrite写还是事先自己写
  7. char allres[1024]={0};
  8. void writeOne(void) {
  9. FILE *fp1=fopen("yunsuan.txt","w");
  10. if(!fp1){
  11. perror("打开失败");
  12. return ;
  13. }
  14. fputs("12+3=\n",fp1);
  15. fputs("20-5=\n",fp1);
  16. fputs("3*4=\n",fp1);
  17. fputs("24/6=\n",fp1);
  18. fclose(fp1);
  19. }
  20. void getres(){
  21. FILE *fp2=fopen("yunsuan.txt","r");
  22. if(!fp2){
  23. perror("打开失败");
  24. return ;
  25. }
  26. char buf[1024];//先把整个文件读出来
  27. //这样才方便删除所有文件原来部分
  28. int a;
  29. int b;
  30. char c;
  31. int res;
  32. char resline[100];
  33. while(1){
  34. fgets(buf,1024,fp2);
  35. if(feof(fp2)){
  36. break;
  37. }
  38. printf("%s",buf);
  39. sscanf(buf,"%d%c%d=\n",&a,&c,&b);
  40. //printf("%d %d %c\n",a,b,c);
  41. switch (c) {
  42. case '+':
  43. res=a+b;
  44. break;
  45. case '-':
  46. res=a-b;
  47. break;
  48. case '*':
  49. res=a*b;
  50. break;
  51. case '/':
  52. res=a/b;
  53. break;
  54. default:
  55. printf("没有找到运算符");
  56. break;
  57. }
  58. sprintf(resline,"%d%c%d=%d\n",a,c,b,res);
  59. printf("%s\n",resline);//test0
  60. strcat(allres,resline);
  61. }
  62. printf("-----------------\n");
  63. printf("%s",allres);
  64. fclose(fp2);
  65. }
  66. void rewrite(){
  67. //w是直接全部清空的 模式
  68. FILE *fp3=fopen("yunsuan.txt","w");
  69. if(!fp3){
  70. perror("打开失败");
  71. return ;
  72. }
  73. fputs(allres,fp3);
  74. fclose(fp3);
  75. }
  76. int main(void) {
  77. writeOne();
  78. getres();
  79. rewrite();
  80. return EXIT_SUCCESS;
  81. system("pause");
  82. }

1.2.fread  fwrite   大文件拷贝

自己写了一个 但是只能复制图的 黑背景??。用二进制读写就没事了

自己写的函数缺陷:每次调用先得改新文件的名字。导致必须复制一次函数整体。

例1:复制yunsuan.txt 文本文件
  1. void mycopyb(char* pathname){
  2. FILE *fp1=fopen(pathname,"rb+");
  3. if(!fp1){
  4. perror("打开失败");
  5. return ;
  6. }
  7. char cont[1024]={0};
  8. FILE *fp2=fopen("mycopy.txt","wb+");
  9. if(!fp2){
  10. perror("打开失败");
  11. return ;
  12. }
  13. while(!feof(fp1)){
  14. fread(cont,1,1024,fp1);
  15. fwrite(cont,1,1024,fp2);
  16. }
  17. fclose(fp1);
  18. fclose(fp2) ;
  19. }
  20. int main(void) {
  21. //测试一个txt文件 注意括号里参数写原文件
  22. //函数缺陷是新文件名必须现改 重复写函数
  23. mycopyb("yunsuan.txt");
  24. return EXIT_SUCCESS;
  25. system("pause");
  26. }
例2:复制一个jpg 文件ab.jpg   看老师的代码 修改,加上一个fread的返回值,

当返回值等于0时说明读取失败

  1. void mycopyb(char* pathname){
  2. FILE *fp1=fopen(pathname,"rb+");
  3. if(!fp1){
  4. perror("打开失败");
  5. return ;
  6. }
  7. char cont[1024]={0};
  8. int ret=0;
  9. FILE *fp2=fopen("mycopy2.jpg","wb+");
  10. if(!fp2){
  11. perror("打开失败");
  12. return ;
  13. }
  14. while(!feof(fp1)){
  15. ret=fread(cont,1,1024,fp1);
  16. if(ret==0){
  17. break;
  18. }
  19. fwrite(cont,1,1024,fp2);
  20. }
  21. fclose(fp1);
  22. fclose(fp2) ;
  23. }
  24. int main(void) {
  25. mycopyb("ab.jpg");
  26. return EXIT_SUCCESS;
  27. system("pause");
  28. }

1.3 游戏配置文件解析

假设有个游戏文件,记录了游戏角色的各种信息,txt中信息如下:

#英雄ID
heroID:zhaoyun
#英雄能力
heroskill:fight
#英雄道具
herotool:bigknife
#英雄血量
heroHP:10000
#英雄防御能力
herotank:20000

通过读文件操作过滤无效信息,将记录保存到结构体数组中。 

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. struct info{
  5. char key[256];
  6. char val[256];
  7. };
  8. //多少行有效信息
  9. int lines(){
  10. int ll=0;
  11. FILE *fp=fopen("gameinfo.txt","r");
  12. if(fp==NULL){
  13. perror("文件没有打开");
  14. }
  15. char buf[256]={0};
  16. while(fgets(buf,256,fp)!=NULL){
  17. if(strchr(buf,':')!=NULL){
  18. printf("%s\n",buf);
  19. ll++;
  20. // sscanf(buf,"%s:%s",key,val);
  21. // printf("key是%s,val是 %s\n",key,val);
  22. //这样吧整个一行都算成key 也又算成val 了!!
  23. //必须用字符串截取函数
  24. //memset(key,0,128);
  25. // memset(val,0,128);
  26. }
  27. memset(buf,0,256);
  28. }
  29. fclose(fp);
  30. return ll;
  31. }
  32. //从文件中,提取有效信息放到 数组中
  33. void putarr(struct info **infoARR,int len){
  34. struct info *arr=(struct info *)malloc(sizeof(struct info)*len);
  35. int index=0;
  36. FILE *fp2=fopen("gameinfo.txt","r");
  37. if(fp2==NULL){
  38. perror("文件没有打开");
  39. }
  40. char buf2[256]={0};
  41. while(fgets(buf2,256,fp2)!=NULL){
  42. if(strchr(buf2,':')!=NULL){
  43. memset(arr[index].key,0,256);
  44. memset(arr[index].val,0,256);
  45. char *pos=strchr(buf2,':');
  46. strncpy(arr[index].key,buf2,strlen(buf2)-strlen(pos));
  47. strncpy(arr[index].val,pos+1,strlen(pos-1));
  48. index++;
  49. if(index==len){
  50. break;
  51. }
  52. }
  53. memset(buf2,0,128);
  54. }
  55. fclose(fp2);
  56. *infoARR=arr;
  57. }
  58. //先遍历一下数组 看看弄好了么
  59. void printALL(struct info *arr,int len){
  60. for(int i=0;i<len;i++){
  61. printf("%s is %s\n",arr[i].key,arr[i].val);
  62. }
  63. }
  64. //cesh测试,根据英雄的key,打印出属性值,要求对应正确。
  65. void getval(const char *kword,struct info *arr,int len){
  66. int flag=0;
  67. for(int i=0;i<len;i++){
  68. if(strcmp (arr[i].key,kword)==0){
  69. printf("the attribute is %s ",arr[i].val);
  70. flag=1;
  71. }
  72. }
  73. if(flag==0){
  74. printf ("no such attribution\n");
  75. }
  76. }
  77. int main()
  78. {
  79. int nums=lines();
  80. printf("有效信息一共 %d 行 \n",nums);
  81. struct info *ptrIn=NULL;
  82. putarr(&ptrIn,nums);
  83. printALL(ptrIn,nums);
  84. getval("heroHP",ptrIn,nums);
  85. //getval("heroMP",ptrIn,nums); //no such attribution
  86. system("pause");
  87. return 0;
  88. }

1.4 文件的加密和解密

把所有字符进行位运算,先左移4位,再右移1位,然后变更符号位。

解密时,先左移1位 再右移5位 (??高位4位会丢失,这里没看明白)

  1. void code(const char* fileA, const char* fileB){
  2. FILE *fp=fopen(fileA,"r");
  3. FILE *fp2=fopen(fileB,"w");
  4. if(fp==NULL){
  5. perror(" open is fail\n");
  6. }
  7. if(fp2==NULL){
  8. perror(" open is fail\n");
  9. }
  10. char ch;
  11. short temp;
  12. while((ch=fgetc(fp))!=EOF){
  13. temp=(short)ch;
  14. temp=temp<<4;
  15. temp=temp|0x8000;//1000 0000 0000 0000 两字节哦
  16. //printf("%d\n",temp);
  17. fprintf(fp2,"%hd",temp);
  18. }
  19. fclose(fp);
  20. fclose(fp2);
  21. }
  22. void decode(const char* fileB, const char* fileC){
  23. FILE *fp3=fopen(fileB,"r");
  24. FILE *fp4=fopen(fileC,"w");
  25. if(fp3==NULL){
  26. perror(" open3 is fail\n");
  27. }
  28. if(fp4==NULL){
  29. perror(" open4 is fail\n");
  30. }
  31. char ch;
  32. short temp;
  33. while(!feof(fp3)){
  34. fscanf(fp3,"%hd",&temp);
  35. temp=temp<<1;
  36. temp=temp>>5;
  37. //疑问,最开始最高位那4个数字无法恢复了。。
  38. printf("%d\n",temp);
  39. ch=(char)temp;
  40. fputc(ch,fp4);
  41. }
  42. fclose(fp3);
  43. fclose(fp4);
  44. }
  45. int main()
  46. {
  47. code("incode.txt","decode.txt");
  48. decode("decode.txt","res.txt");
  49. //打开res 和incode看是不是一模一样就行
  50. system("pause");
  51. return 0;
  52. }

2.指针基础属性

2.1利用指针步长,获取结构体属性的值。

  1. struct Person{
  2. int a;
  3. char b;
  4. char buf[64];
  5. int d;
  6. };
  7. int main (){
  8. struct Person p1={100,'w',"water cup",12};
  9. printf("%d\n",sizeof(p1)); //76
  10. // char *pp=&p1; BAO CUO ERROR
  11. printf("属性d的值是%d\n",*((char*)&p1+72));

 2.2  offsetof( struct 结构体名,属性名) 函数

    #include<stddef.h>

  1. struct Person p1={100,'w',"water cup",12};
  2. int aaa=offsetof(struct Person,d);
  3. printf("%d\n",aaa); //72

3.数据结构方面基础代码

3.1 带头节点的链表

创建在堆上的 叫做动态链表。头结点没有数据,只有一个指针域。

创建initList  ,遍历foreach, 释放freeList 三个函数。

外加一个插入函数,第一个参数是头结点,第二个参数int old是在数据等于old的节点后面插入,第三个参数是插入的新值。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include<string.h>
  4. struct Node{
  5. int num;
  6. struct Node* next;
  7. };
  8. //初始化链表
  9. struct Node* initList(){
  10. struct Node* phead;
  11. if(phead==NULL){
  12. perror("FAIL IN MALLOC");
  13. }
  14. phead=(struct Node *)malloc(sizeof(struct Node));
  15. phead->next=NULL;
  16. struct Node* ptail=phead;
  17. int n=0;
  18. while(1){
  19. int m=0;
  20. printf("Please type in the %d th number\n",n+1);
  21. scanf("%d",&m);
  22. if(m==-1){
  23. printf("List ends\n");
  24. break;
  25. }
  26. else{
  27. struct Node* ptr=(struct Node *)malloc(sizeof(struct Node));
  28. ptr->num=m;
  29. ptr->next=NULL;
  30. n++;
  31. ptail->next=ptr;
  32. ptail=ptr;
  33. }
  34. }
  35. return phead;
  36. };
  37. //链表的遍历
  38. void foreach(struct Node* header){
  39. if(header==NULL){
  40. perror("list is NULL");
  41. }
  42. while(header->next!=NULL){
  43. header=header->next;
  44. printf("the num is %d\n",header->num);
  45. }
  46. }
  47. //再链表某个值的后面插入一个新值
  48. void listinser(struct Node* header,int old,int newval){
  49. if(header==NULL){
  50. perror("list is NULL");
  51. }
  52. struct Node* ptr=header->next;
  53. while(ptr!=NULL){
  54. if(ptr->num==old){
  55. break;
  56. }
  57. ptr=ptr->next;
  58. }
  59. if(ptr==NULL){
  60. printf("no such data in the list\n");
  61. return;
  62. }
  63. struct Node* newnode=( struct Node*)malloc(sizeof(struct Node));
  64. newnode->num=newval;
  65. newnode->next=ptr->next;
  66. ptr->next=newnode;
  67. }
  68. //摧毁整个链表
  69. void listfree(struct Node* list){
  70. if(list==NULL){
  71. perror("list is NULL");
  72. }
  73. struct Node* pp=list;
  74. while((list->next)!=NULL){
  75. list=list->next;
  76. free(pp);
  77. pp=NULL;
  78. pp=list;
  79. }
  80. free(list);
  81. list=NULL;
  82. }
  83. int main(void) {
  84. struct Node* mylist=initList();
  85. foreach(mylist);
  86. listinser(mylist,30,2000);
  87. printf("插入操作完成,现在链表重新遍历\n");
  88. foreach(mylist);
  89. listfree(mylist);
  90. free(mylist);
  91. mylist=NULL;
  92. if(mylist==NULL){
  93. printf("right\n");
  94. }
  95. system("pause");
  96. return EXIT_SUCCESS;
  97. }
3.1.1按照位置来插入 新节点。

第二个参数pos表示在第几节点后面插入新节点,头结点当做第0个。

  1. void listinsBpos(struct Node* header,int pos,int newval){
  2. if(header==NULL){
  3. perror("list is NULL");
  4. }
  5. int inpos=0;
  6. struct Node* ptr=header;
  7. while(ptr!=NULL){
  8. if(inpos==pos){
  9. break;
  10. }
  11. ptr=ptr->next;
  12. inpos++;
  13. }
  14. if(ptr==NULL){
  15. printf("no such data in the list\n");
  16. return;
  17. }
  18. struct Node* newnode=( struct Node*)malloc(sizeof(struct Node));
  19. newnode->num=newval;
  20. newnode->next=ptr->next;
  21. ptr->next=newnode;
  22. }
3.1.2 链表倒置

头结点为pheader ,第一个有数据域的节点为p1 , 后面依次为p2, p3 每次让p2->next = p1 然后再移动p1  p2的位置就可以了。

  1. void reverLink( struct Node* head ){
  2. struct Node* p1=head;
  3. struct Node* p2=head->next;
  4. struct Node* p3=p2->next;
  5. if(p3==NULL){
  6. printf("only one NODE having data\n");
  7. return;
  8. }
  9. p2->next=NULL; //第一个有数据域的节点,成为尾巴,next 为NULL
  10. p1=p2;
  11. p2=p3;
  12. while(p2!=NULL){
  13. struct Node* pnext=p2->next;
  14. p2->next=p1;
  15. p1=p2;
  16. p2=pnext;
  17. }
  18. head->next=p1;//把头节点挪过来,让它指向原来的尾巴
  19. }

4.模拟或者改写字符串相关API

4.1   字符串复制函数strcpy

3种方式 zhuyi注意第三种,赋值为0 退出while循环

  1. void mycopy(char *str1,char *str2){
  2. int num=strlen(str1);
  3. for(int i=0;i<=num;i++){
  4. str2[i]=str1[i];
  5. }
  6. }
  7. void mycopy2(char *str1,char *str2){
  8. int num=strlen(str1);
  9. while(*str1!='\0'){
  10. *str2=*str1;
  11. str1++;
  12. str2++;
  13. }
  14. }
  15. void mycopy3(char *str1,char *str2){
  16. while(*str2++=*str1++){
  17. }
  18. }
  19. void mytest(){
  20. char ss1[64]="gets water";
  21. char ss2[64]={0};
  22. // mycopy(ss1,ss2);
  23. //mycopy2(ss1,ss2);
  24. //mycopy3(ss1,ss2);
  25. printf("%s\n",ss2);
  26. }

4.2  字符串翻转函数

  1. void myverse(char *str){
  2. int num=strlen(str);
  3. int a=0;
  4. int b=num-1;
  5. while(a<b){
  6. char temp='0';
  7. temp=str[a];
  8. str[a]=str[b];
  9. str[b]=temp;
  10. a++;
  11. b--;
  12. }
  13. }

利用指针

  1. void rev2(char *buf){
  2. int num=strlen(buf);
  3. char temp='0';
  4. char *start=buf;
  5. char *end=buf+num-1;
  6. while(start<end){
  7. temp=*start;
  8. *start=*end;
  9. *end=temp;
  10. start++;
  11. end--;
  12. }
  13. }

4.3 判断一个字符串是否回文

视频中老师的写法 

  1. int str_huiwen(char *str){
  2. char *start=str;
  3. char *end=start+strlen(str)-1;
  4. while(start<end){
  5. if(*start!=*end){
  6. return 0;
  7. }
  8. start++;
  9. end--;
  10. }
  11. return 1;
  12. }

自己写法

  1. bool huiwen(char *str){
  2. char *start=str;
  3. char *end=start+strlen(str)-1;
  4. while(*start==*end){
  5. start++;
  6. end--;
  7. if(start>end){
  8. return true;
  9. break;
  10. }
  11. }
  12. return false;
  13. }

4.4 字符串查找strstr( )模拟

 注意,C语言中strstr 函数是返回地址(就是子串在母串中的首地址 ), 还是一个可以打印的字符串,但是我这个函数返回的是子串的第一个字母是母串的第几个字符。

  1. int mystrsub(const char *str,const char*sub){
  2. int num=0;
  3. while(*str!='\0'){
  4. if(*str==*sub){
  5. const char *temp1=str;
  6. const char *temp2=sub;
  7. while(*sub!='\0'){
  8. if(*temp1!=*temp2){
  9. break;
  10. }
  11. temp1++;
  12. temp2++;
  13. }
  14. if(*temp2=='\0'){
  15. printf("子串匹配成功位置是%d\n",num);
  16. return num;
  17. }
  18. }
  19. str++;
  20. num++;
  21. }
  22. return -1;
  23. }
  24. void test2(){
  25. const char *word="adegdnfhi";
  26. const char* subword="dnf";
  27. int ret=mystrsub(word,subword);
  28. printf("%d\n",ret);
  29. }

 4.5  在母串中,子串出现的次数

这个是利用了库自带的strstr( )函数

  1. 字符串查找 找到的次数 利用已有的strstr <string.h>
  2. int ser_time(char *sear,char*tar){
  3. int k=strlen(tar);
  4. int count=0;
  5. char *r=strstr(sear,tar);
  6. while(r!=nullptr){
  7. printf("%s\n",r);
  8. r+=k;
  9. count++;
  10. r=strstr(r,tar);//再新的 掐去了头的 字符串里寻找
  11. }
  12. return count;
  13. }

 4.6字符串复制

4.7 strlen字符串长度统计功能

  1. //zhi利用传统功能实现 strlen功能
  2. int mystrlen(char str[]){
  3. int i=0;
  4. while(str[i]!='\0'){
  5. i++;
  6. }
  7. return i;
  8. }
  9. //zhi利用指针实现 strlen功能
  10. int mystrlen2(char str[]){
  11. char *cp=str;
  12. while((*cp)!='\0'){
  13. //'\0' 不是空格,是NULL字符啦,是一个字符串的结束
  14. cp++;
  15. }
  16. return cp-str;
  17. }

5.一些基础小例子

5.1 模拟电子表打印

#include <windows.h>       //Sleep()函数

  1. for(int i=0;i<24;i++){
  2. for(int j=0;j<60;j++){
  3. for(int k=0;k<60;k++){
  4. printf("%02d : %02d : %02d\n",i,j,k);
  5. Sleep(1000);
  6. system("cls");//清除屏幕
  7. }
  8. }
  9. }

??C语言日期函数?待补充 

5.2 99乘法表 

  1. for(int i=1;i<9;i++){
  2. for(int j=1;j<=i;j++){
  3. printf("%d * %d = %d ",j,i,j*i);
  4. }
  5. printf("\n");
  6. }

5.3 水仙花数字

5.4 猜数字 

#include <time.h>     //  srand(time(NULL))

总是自动有个空格输入导致自动跳转无限循环      解决办法

  1. srand(time(NULL));
  2. int r_num=rand()%101+1; //1-100
  3. int a;
  4. while(1){
  5. printf("请输入数字\n");
  6. scanf("%d",&a);
  7. while(getchar()!='\n'){
  8. continue;
  9. }
  10. if(a==r_num){
  11. printf("猜对了");
  12. }
  13. else{
  14. printf("猜错了,是否继续, Y N\n");
  15. char n;
  16. scanf("%c",&n);
  17. if(n=='N'){
  18. printf("输入的字符是%c,表示您拒绝继续\n",n);
  19. break;
  20. }
  21. }
  22. }

5.5统计字符串中各个字母出现次数 

  1. char example[25] ="there is a big lake";
  2. int countarr[26]={0};
  3. //一个整数 数组,共26个数字,代表26个字母。初始化每个数都是零
  4. for(size_t i=0;i<25;i++){
  5. if(!isblank(example[i])){ //头文件cctype
  6. int count=static_cast<int>(example[i]-'a');
  7. countarr[count]++;
  8. }
  9. }
  10. //printf("现在统计结果\n");
  11. for(size_t j=0;j<26;j++){
  12. if(countarr[j]!=0){
  13. printf("%c字母在句子中出现次数是%d\n",j+'a',countarr[j]);
  14. }
  15. //j +'a'隐形数据类型转换,不放心的可以用(char)强制转
  16. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/436436
推荐阅读
相关标签
  

闽ICP备14008679号