C语言中temp.key是什么意思?

C语言中temp.key是什么意思?!啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

c

4个回答

你这个问题没头没尾的,只能猜测了你这个是一个结构体的属性了,这个没有具体的含义,看你是怎么定义的,比如:

struct Test
{
    int key;
    //...
};


Test temp;

temp.key = 1;

我只是这么猜猜,具体含义看程序

是单片机源码中的C语言吗?如果是的话
根据电路的排布,temp和key分别代表行和列,行、列都确定后,就可以定位是那个按键响应了。
按键按下后,都会进入key4x4()的函数,先用temp来区分出是哪一行(列),再用key来区分具体为那一列(行),从而确定动作按键的具体位置;

最好把问题描述的详细点

你这个问题,首先你得懂结构体的知识,key是结构体成员, "."是域操作符,你这里temp是你定义的一个结构体变量,而这个变量就有内部结构体成员的
相关属性,而这个int类型的key就是这个temp的一个属性,你要操作它,你就要用域操作符(.)来取,给你找来一个关于结构体简单定义的一个链接,
自己琢磨清楚http://www.cnblogs.com/yakun/p/3570437.html

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
GPS单片机protuesLCD1602黑块较多,应该是数据解析的问题。
基于单片机的GPS数据解析LCD出现很多黑块 ![图片说明](https://img-ask.csdn.net/upload/202003/23/1584958335_677407.png) GPS数据用串口助手,发送的。然后发送完再接收。准确没有错误。应该不是串口通信的,问题,LCD在发送数据之前,能正常显示welcome![图片说明](https://img-ask.csdn.net/upload/202003/23/1584958430_582550.png) 我猜测应该是GPS数据解析的问题,因为关于时间的数据,随便怎么修改。LCD1602上面那个21都没变过。 串口代码如下: ``` void RECEIVE_DATA(void) interrupt 4 { unsigned char temp; temp = SBUF; RI = 0; //清除发送完成标志位 //LED1 = ~LED1; SBUF=temp;//将接收到的数据放入到发送寄存器 while(!TI); //等待发送数据完成 TI=0; if(temp == '$') { RX_Count = 0; Flag_GPS_OK = 0; } RX_Buffer[RX_Count++] = temp; if(RX_Count >= 68) { RX_Count = 68; Flag_GPS_OK = 1; } } ``` 数据解析的: ``` while(1) { Scan_Key(); if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'G' && RX_Buffer[6] == ',' && RX_Buffer[13] == '.') //确定是否收到"GNGGA"这一帧数据 { for( i = 0; i < 68 ; i++) { Display_GPGGA_Buffer[i] = RX_Buffer[i]; } Hour = (Display_GPGGA_Buffer[7]-0x30)*10+(Display_GPGGA_Buffer[8]-0x30)+8; //UTC时间转换到北京时间 UTC+8 //0x30为ASCII转换为数字 if( Hour >= 24) //溢出 { Hour %= 24; //获取当前Hour Flag_OV = 1; //日期进位 } else { Flag_OV = 0; } Min_High = Display_GPGGA_Buffer[9]; Min_Low = Display_GPGGA_Buffer[10]; Sec_High = Display_GPGGA_Buffer[11]; Sec_Low = Display_GPGGA_Buffer[12]; Flag_Calc_GPGGA_OK = 1; } if(Page == 0 && Flag_Calc_GPGGA_OK == 1) { /*LED1 = ~LED1;*/ Flag_Calc_GPGGA_OK = 0; LCD1602_write_com(0x80); //设置指针 LCD1602_write_data(Hour/10+0x30); LCD1602_write_data(Hour%10+0x30); LCD1602_write_data(':'); LCD1602_write_data(Min_High); LCD1602_write_data(Min_Low); LCD1602_write_data(':'); LCD1602_write_data(Sec_High); LCD1602_write_data(Sec_Low); LCD1602_write_word(" "); LCD1602_write_data(Display_GPGGA_Buffer[54]); LCD1602_write_data(Display_GPGGA_Buffer[55]); LCD1602_write_data(Display_GPGGA_Buffer[56]); LCD1602_write_data(Display_GPGGA_Buffer[57]); LCD1602_write_word("m"); LCD1602_write_com(0x80+0x40); //设置指针 LCD1602_write_data(Display_GPGGA_Buffer[28]); //N 或者 S LCD1602_write_data(Display_GPGGA_Buffer[17]); //纬度 LCD1602_write_data(Display_GPGGA_Buffer[18]); //纬度 LCD1602_write_data(0xdf); //度 LCD1602_write_data(Display_GPGGA_Buffer[19]); //纬度 LCD1602_write_data(Display_GPGGA_Buffer[20]); //纬度 LCD1602_write_word("'"); //秒 LCD1602_write_data(Display_GPGGA_Buffer[42]); //E 或者 W LCD1602_write_data(Display_GPGGA_Buffer[30]); //经度 LCD1602_write_data(Display_GPGGA_Buffer[31]); LCD1602_write_data(Display_GPGGA_Buffer[32]); LCD1602_write_data(0xdf); LCD1602_write_data(Display_GPGGA_Buffer[33]); LCD1602_write_data(Display_GPGGA_Buffer[34]); LCD1602_write_word("'"); } ```
基于单片机的GPS数据解析,LCD1602proteus仿真时出现一部分黑块待解决
GPS数据解析,LCD1602上黑块较多,而且数据无论怎么变,LCD1602的显示都不变 ![图片说明](https://img-ask.csdn.net/upload/202003/23/1584959625_77299.png)![图片说明](https://img-ask.csdn.net/upload/202003/23/1584959635_593956.png) ``` while(1) { Scan_Key(); if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'G' && RX_Buffer[6] == ',' && RX_Buffer[13] == '.') //确定是否收到"GNGGA"这一帧数据 { for( i = 0; i < 68 ; i++) { Display_GPGGA_Buffer[i] = RX_Buffer[i]; } Hour = (Display_GPGGA_Buffer[7]-0x30)*10+(Display_GPGGA_Buffer[8]-0x30)+8; //UTC时间转换到北京时间 UTC+8 //0x30为ASCII转换为数字 if( Hour >= 24) //溢出 { Hour %= 24; //获取当前Hour Flag_OV = 1; //日期进位 } else { Flag_OV = 0; } Min_High = Display_GPGGA_Buffer[9]; Min_Low = Display_GPGGA_Buffer[10]; Sec_High = Display_GPGGA_Buffer[11]; Sec_Low = Display_GPGGA_Buffer[12]; Flag_Calc_GPGGA_OK = 1; } if(Page == 0 && Flag_Calc_GPGGA_OK == 1) { /*LED1 = ~LED1;*/ Flag_Calc_GPGGA_OK = 0; LCD1602_write_com(0x80); //设置指针 LCD1602_write_data(Hour/10+0x30); LCD1602_write_data(Hour%10+0x30); LCD1602_write_data(':'); LCD1602_write_data(Min_High); LCD1602_write_data(Min_Low); LCD1602_write_data(':'); LCD1602_write_data(Sec_High); LCD1602_write_data(Sec_Low); LCD1602_write_word(" "); LCD1602_write_data(Display_GPGGA_Buffer[54]); LCD1602_write_data(Display_GPGGA_Buffer[55]); LCD1602_write_data(Display_GPGGA_Buffer[56]); LCD1602_write_data(Display_GPGGA_Buffer[57]); LCD1602_write_word("m"); LCD1602_write_com(0x80+0x40); //设置指针 LCD1602_write_data(Display_GPGGA_Buffer[28]); //N 或者 S LCD1602_write_data(Display_GPGGA_Buffer[17]); //纬度 LCD1602_write_data(Display_GPGGA_Buffer[18]); //纬度 LCD1602_write_data(0xdf); //度 LCD1602_write_data(Display_GPGGA_Buffer[19]); //纬度 LCD1602_write_data(Display_GPGGA_Buffer[20]); //纬度 LCD1602_write_word("'"); //秒 LCD1602_write_data(Display_GPGGA_Buffer[42]); //E 或者 W LCD1602_write_data(Display_GPGGA_Buffer[30]); //经度 LCD1602_write_data(Display_GPGGA_Buffer[31]); LCD1602_write_data(Display_GPGGA_Buffer[32]); LCD1602_write_data(0xdf); LCD1602_write_data(Display_GPGGA_Buffer[33]); LCD1602_write_data(Display_GPGGA_Buffer[34]); LCD1602_write_word("'"); } 通信的代码 void RECEIVE_DATA(void) interrupt 4 { unsigned char temp; temp = SBUF; RI = 0; //清除发送完成标志位 //LED1 = ~LED1; SBUF=temp;//将接收到的数据放入到发送寄存器 while(!TI); //等待发送数据完成 TI=0; if(temp == '$') { RX_Count = 0; Flag_GPS_OK = 0; } RX_Buffer[RX_Count++] = temp; if(RX_Count >= 68) { RX_Count = 68; Flag_GPS_OK = 1; } } ```
求!!!!怎么在C语言添加背景音乐
我打算在个C语言程序中加背景音乐,找了好多都不行,总会报错,希望有大佬可以教我一下怎么加背景音乐,用的是DV源代码如下(拜托了各位大佬!!!) #include <stdio.h> #include <windows.h> #include <time.h> #include <conio.h> #include <stdlib.h> #define N 65 int status[N][N]={{0},{0}};//记录棋盘情况,0无,1红棋/玩家,2为白棋/电脑 int flag=0;//判断输赢 int direct[2];//方向 int Value1[N][N]={{0},{0}};//计算权值 int Value2[N][N]={{0},{0}};//计算权值 int regrex,regrey,regrex1,regrey1; int count=0;//计算棋子数量 void chess_board();//打印棋盘 void red_movexy();//红子棋移动光标 void white_movexy();//白棋移动光标 void red_chess(int x,int y);//红棋 void white_chess(int x,int y);//白棋 void man_machine();//人机对战 int judge_chess(int x,int y);//判断这个位置是否下过 int judge_winner(int x,int y,int temp);//判断输赢 void machine_attack();//电脑进攻权值 void machine_defend();//电脑防守权值 void find_position();//寻找最佳权值 void Regret();//悔棋函数 void BackGround(unsigned int ForeColor, unsigned int BackGroundColor) //颜色 { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台的句柄 SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);//改变当前光标的背景和字体颜色 } void gotoxy(int x, int y) //光标函数 { HANDLE handle; COORD coord; //获取坐标轴结构体 coord.X = x; coord.Y = y; handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄,值为-11 SetConsoleCursorPosition(handle, coord); //移动光标到x,y处 } void chess_board()//打印棋盘 { int i,j; for(i=0;i<=30;i++) for(j=0;j<=60;j+=4) { gotoxy(j,i); printf("|"); } for(i=0;i<=30;i+=2) for(j=1;j<=57;j+=4) { gotoxy(j,i); printf("---"); } } void chess_menu()//打印棋盘旁的菜单 { int i,j; for(i=1;i<=29;i++) { gotoxy(67,i); printf("||"); } for(i=1;i<=29;i++) { gotoxy(89,i); printf("||"); } gotoxy(69,1); printf("--------------------"); gotoxy(69,29); printf("--------------------"); gotoxy(75,3); printf("模 式"); gotoxy(73,9); printf("WASD移动光标"); gotoxy(73,10); printf("选择下棋位置"); gotoxy(73,11); printf("按空格键确认"); gotoxy(73,12); printf("按Q悔棋"); gotoxy(73,20); printf("提 示"); } void red_movexy()//红棋移动光标 { loop2:gotoxy(direct[0],direct[1]); char key='y'; int temp; while(key!=' ') { key=getch(); switch(key) { case 'W': case 'w': direct[1]-=2; if(direct[1]<=1) direct[1]=1; break; case 's': case 'S': direct[1]+=2; if(direct[1]>=29) direct[1]=29; break; case 'a': case 'A': direct[0]-=4; if(direct[0]<=2) direct[0]=2; break; case 'd': case 'D': direct[0]+=4; if(direct[0]>=58) direct[0]=58; break; case 'q': case 'Q': { int message=MessageBox(NULL,"是否确定悔棋?","友情提示",MB_OKCANCEL); if(IDCANCEL==message) break; if(IDOK==message) { Regret(); break; } } } gotoxy(direct[0],direct[1]); } temp=judge_chess(direct[1],direct[0]); if(temp==1) { gotoxy(70,22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop2; } } void white_movexy()//白棋移动光标 { loop1:gotoxy(direct[0],direct[1]); char key='y'; int temp; while(key!='0') { key=getch(); switch(key) { case 72: direct[1]-=2; if(direct[1]<=1) direct[1]=1; break; case 80: direct[1]+=2; if(direct[1]>=29) direct[1]=29; break; case 75: direct[0]-=4; if(direct[0]<=2) direct[0]=2; break; case 77: direct[0]+=4; if(direct[0]>=58) direct[0]=58; break; case 'B': case 'b': { int message=MessageBox(NULL,"是否确定悔棋?","友情提示",MB_OKCANCEL); if(IDCANCEL==message) break; if(IDOK==message) { Regret(); break; } } } gotoxy(direct[0],direct[1]); } temp=judge_chess(direct[1],direct[0]); if(temp==1) { gotoxy(70,22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop1; } } void red_chess(int x,int y)//打印红棋 { BackGround(4,0); regrex=x;//记录上一落子的位置 ,方便悔棋 regrey=y; count++; printf("●"); status[x][y]=1; } void white_chess(int x,int y)//打印白棋 { BackGround(7,0); regrex1=x; regrey1=y; printf("●"); count++; status[x][y]=2; } void machine_chess(int x,int y)//电脑落子 { BackGround(7,0); status[x][y]=2; regrex1=x; regrey1=y; count++; gotoxy(y,x); printf("●"); } int judge_chess(int x,int y)//判断这个地方是否有棋子 { if(status[x][y]==0) return 0; else return 1; } int judge_winner(int x,int y,int temp)//判断输赢 { int i,j,n1,n2; n1=n2=0; for(i=x,j=y+4;j<=58;j+=4)//右 { if(status[i][j]==temp) n1++; else break; } for(i=x,j=y;j>=2;j-=4)//左 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; n1=n2=0; for(i=x,j=y;i>=1;i-=2)//上 { if(status[i][j]==temp) n1++; else break; } for(i=x+2,j=y;i<=30;i+=2)//下 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; n1=n2=0; for(i=x-2,j=y+4;i>=1&&j<=58;i-=2,j+=4)//右上 { if(status[i][j]==temp) n1++; else break; } for(i=x,j=y;i<=30&&j>=2;i+=2,j-=4)//左下 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; n1=n2=0; for(i=x,j=y;i>=0&&j>=0;i-=2,j-=4)//左上 { if(status[i][j]==temp) n1++; else break; } for(i=x+2,j=y+4;i<=30&&j<=58;i+=2,j+=4)//右下 { if(status[i][j]==temp) n2++; else break; } if(n1+n2>=5) return temp; return 0; } void machine_attack()//电脑进攻权值 { int i1,j1; int k1,k2,k; for(int i=1;i<=30;i+=2) { for(int j=2;j<=58;j+=4) { if(status[i][j]) Value1[i][j]=0; if(status[i][j]==0) { k1=k2=0; for(i1=i,j1=j-4;j1>=2;j1-=4)//往左数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i,j1=j+4;j1<=58;j1+=4)//往右数寻找电脑棋子数 { if(status[i1][j1]==2) k2++; else break; } k=k1>k2? k1:k2; k1=k2=0; for(i1=i-2,j1=j;i1>=1;i1-=2)//往上数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i+2,j1=j;i1<=30;i1+=2)//往下数寻找电脑棋子数 { if(status[i1][j1]==2) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1? k:k1; k1=k2=0; for(i1=i-2,j1=j-4;i1>=0&&j1>=0;i1-=2,j1-=4)//往左上数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i+2,j1=j+4;i1<=30&&j1<=58;i1+=2,j1+=4)//往右下数寻找电脑棋子数 { if(status[i1][j1]==2 ) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; k1=k2=0; for(i1=i+2,j1=j-4;i1<=30&&j1>=2;i1+=2,j1-=4)//往左下数寻找电脑棋子数 { if(status[i1][j1]==2) k1++; else break; } for(i1=i-2,j1=j+4;i1>=1&&j1<=58;i1-=2,j1+=4)//往右上数寻找电脑棋子数 { if(status[i1][j1]==2) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; switch(k) { case 3: Value1[i][j]=15;break; case 4: Value1[i][j]=25;break; default: Value1[i][j]=3+2*k;break; } } } } } void machine_defend()//防守权值 { int i1, j1; int k1,k2,k; for(int i=1;i<=30;i+=2) { for(int j=2;j<=58;j+=4) { if(status[i][j]) Value2[i][j]=0; if(status[i][j]==0) { k1=k2=0; for(i1=i,j1=j-4;j1>=2;j1-=4)//往左数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i,j1=j+4;j1<=58;j1+=4)//往右数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k=k1>k2? k1:k2; k1=k2=0; for(i1=i-2,j1=j;i1>=1;i1-=2)//往上数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i+2,j1=j;i1<=30;i1+=2)//往下数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; k1=k2=0; for(i1=i-2,j1=j-4;i1>=1&&j1>=2;i1-=2,j1-=4)//往左上数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i+2,j1=j+4;i1<=30&&j1<=58;i1+=2,j1+=4)//往右下数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; k1=k2=0; for(i1=i+2,j1=j-4;i1<=30&&j1>=2;i1+=2,j1-=4)//往左下数寻找玩家棋子数 { if(status[i1][j1]==1) k1++; else break; } for(i1=i-2,j1=j+4;i1>=1&&j1<=58;i1-=2,j1+=4)//往右上数寻找玩家棋子数 { if(status[i1][j1]==1) k2++; else break; } k1=k1>k2? k1:k2; k=k>k1?k:k1; switch(k) { case 3: Value2[i][j]=10;break; case 4: Value2[i][j]=20;break; default: Value2[i][j]=2+k*2; } } } } } void find_position()//找到最有价值的位置 { int k1=0, k2=0; int i, j, max=0; for( i=1;i<=30;i+=2) for( j=2;j<=58;j+=4) { if(max<=Value1[i][j]) { max=Value1[i][j]; k1=i; k2=j; } } for( i=1;i<=30;i+=2) for( j=2;j<=58;j+=4) { if(max<=Value2[i][j]) { max=Value2[i][j]; k1=i; k2=j; } } direct[1]=k1; //将找到的位置传给光标 direct[0]=k2; } void man_machine()//人机对战模式 { loop6:system("cls"); char key; int control; gotoxy(2, 3); printf("1.玩 家 先 手(玩家为红子)"); gotoxy(2, 5); printf("2.电 脑 先 手(电脑为白子)"); gotoxy(2, 7); printf("(输入相应序号选择)"); key=getch(); system("cls"); if(key=='1') control=1; else if(key=='2') { control=1; machine_chess(13,26); } else goto loop6; gotoxy(70,5); printf(" 人 机 对 战 "); direct[1]=15; direct[0]=30; chess_board(); chess_menu(); while(flag==0) { if(control==1) { gotoxy(70,22); BackGround(6,0); printf(" 玩 家 执 手 "); red_movexy(); red_chess(direct[1],direct[0]); flag=judge_winner(direct[1],direct[0],1); } else { gotoxy(70,22); BackGround(6,0); printf(" 电 脑 执 手 "); machine_defend(); machine_attack(); find_position(); machine_chess(direct[1],direct[0]); flag=judge_winner(direct[1],direct[0],2); } control=-control; } gotoxy(8,18); if(flag==1) { BackGround(7,0); MessageBox(NULL,"太厉害了,您竟然战胜了电脑!","五子棋游戏",MB_OK); } if(flag==2) { MessageBox(NULL,"游戏结束,您输给了电脑","五子棋游戏",MB_OK); } if(count>=225) { MessageBox(NULL,"平局","五子棋游戏",MB_OK); } } void Regret()//悔棋函数 { gotoxy(regrey,regrex); BackGround(0,0); printf(" "); status[regrex][regrey]=0; gotoxy(regrey1,regrex1); BackGround(0,0); printf(" "); status[regrex1][regrey1]=0; count-=2; } void welcome()//游戏菜单 { int k; char choose; system("cls"); for(k=2;k<=12;k+=2)//游戏菜单 { gotoxy(5,k); printf("|-----------------|"); } gotoxy(5, 3); printf("| 五 子 棋 游 戏 |"); gotoxy(5, 5); printf("| 菜 单 |"); gotoxy(5, 7); printf("| 1.人 机 对 战 |"); gotoxy(5, 9); printf("| 2.最 高 纪 录 |"); gotoxy(5, 11); printf("| 3.退 出 游 戏 |"); gotoxy(5, 16); printf("温馨提示:输入菜单对应序号进行操作"); gotoxy(5, 18); printf("祝您游戏愉快!"); gotoxy(13, 20); } char Updatediary()//最高纪录 { system("cls"); gotoxy(2, 3); printf("(暂时没有)"); gotoxy(2, 5); printf("(按E键返回,按其它任意键退出)"); return getch(); } int main() { system("title 五子棋"); system("mode con cols=92 lines=33"); char choose,temp; loop:welcome(); choose=getch(); switch(choose) { case '1': man_machine(); break; case '2': temp=Updatediary(); if(temp=='E'||temp=='e') goto loop; break; case '3': int message=MessageBox(NULL,"是否退出?","友情提示",MB_OKCANCEL); if(IDCANCEL==message) goto loop; if(IDOK==message) { break; } } } ``` ```
求助改写一个c语言程序
我的编译环境是vs2013,我有一个五子棋代码,想要改一下棋盘和落子方式。但每次改动都会报错,求大佬帮我改成要求的形式,要求棋盘如下 ![图片说明](https://img-ask.csdn.net/upload/201912/21/1576915117_449851.png)棋盘的输入只能以键盘输入,建议统一以字母为先,如G2.且棋子必须下在棋盘格的交点上,不可下在格子里。 ``` #include <stdio.h> #include <windows.h> #include <time.h> #include <conio.h> #include <stdlib.h> #define N 65 int status[N][N] = { { 0 }, { 0 } };//记录棋盘情况,0无,1红棋/玩家,2为白棋/电脑 int flag = 0;//判断输赢 int direct[2];//方向 int Value1[N][N] = { { 0 }, { 0 } };//计算权值 int Value2[N][N] = { { 0 }, { 0 } };//计算权值 int regrex, regrey, regrex1, regrey1; int count = 0;//计算棋子数量 void chess_board();//打印棋盘 void red_movexy();//红子棋移动光标 void white_movexy();//白棋移动光标 void red_chess(int x, int y);//红棋 void white_chess(int x, int y);//白棋 void man_man(); void man_machine();//人机对战 int judge_chess(int x, int y);//判断这个位置是否下过 int judge_winner(int x, int y, int temp);//判断输赢 void machine_attack();//电脑进攻权值 void machine_defend();//电脑防守权值 void find_position();//寻找最佳权值 void Regret();//悔棋函数 void BackGround(unsigned int ForeColor, unsigned int BackGroundColor) //颜色 { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台的句柄 SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);//改变当前光标的背景和字体颜色 } void gotoxy(int x, int y) //光标函数 { HANDLE handle; COORD coord; //获取坐标轴结构体 coord.X = x; coord.Y = y; handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄,值为-11 SetConsoleCursorPosition(handle, coord); //移动光标到x,y处 } void chess_board()//打印棋盘 { int i, j; for (i = 0; i <= 30; i++) for (j = 0; j <= 60; j += 4) { gotoxy(j, i); printf("|"); } for (i = 0; i <= 30; i += 2) for (j = 1; j <= 57; j += 4) { gotoxy(j, i); printf("---"); } } void chess_menu()//打印棋盘旁的菜单 { int i, j; for (i = 1; i <= 29; i++) { gotoxy(67, i); printf("||"); } for (i = 1; i <= 29; i++) { gotoxy(89, i); printf("||"); } gotoxy(69, 1); printf("--------------------"); gotoxy(69, 29); printf("--------------------"); gotoxy(75, 3); printf("模 式"); gotoxy(75, 20); printf("提 示"); } void red_movexy()//红棋移动光标 { loop2: gotoxy(direct[0], direct[1]); char key = 'y'; int temp; while (key != ' ') { key = _getch(); switch (key) { case 'W': case 'w': direct[1] -= 2; if (direct[1] <= 1) direct[1] = 1; break; case 's': case 'S': direct[1] += 2; if (direct[1] >= 29) direct[1] = 29; break; case 'a': case 'A': direct[0] -= 4; if (direct[0] <= 2) direct[0] = 2; break; case 'd': case 'D': direct[0] += 4; if (direct[0] >= 58) direct[0] = 58; break; case 'q': case 'Q': { int message = MessageBox(NULL, "是否确定悔棋?", "友情提示", MB_OKCANCEL); if (IDCANCEL == message) break; if (IDOK == message) { Regret(); break; } } } gotoxy(direct[0], direct[1]); } temp = judge_chess(direct[1], direct[0]); if (temp == 1) { gotoxy(70, 22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop2; } } void white_movexy()//白棋移动光标 { loop1:gotoxy(direct[0], direct[1]); char key = 'y'; int temp; while (key != '0') { key = _getch(); switch (key) { case 72: direct[1] -= 2; if (direct[1] <= 1) direct[1] = 1; break; case 80: direct[1] += 2; if (direct[1] >= 29) direct[1] = 29; break; case 75: direct[0] -= 4; if (direct[0] <= 2) direct[0] = 2; break; case 77: direct[0] += 4; if (direct[0] >= 58) direct[0] = 58; break; case 'B': case 'b': { int message = MessageBox(NULL, "是否确定悔棋?", "友情提示", MB_OKCANCEL); if (IDCANCEL == message) break; if (IDOK == message) { Regret(); break; } } } gotoxy(direct[0], direct[1]); } temp = judge_chess(direct[1], direct[0]); if (temp == 1) { gotoxy(70, 22); BackGround(4, 0); printf("这里已经被人下过了"); goto loop1; } } void red_chess(int x, int y)//打印红棋 { BackGround(4, 0); regrex = x;//记录上一落子的位置 ,方便悔棋 regrey = y; count++; printf("●"); status[x][y] = 1; } void white_chess(int x, int y)//打印白棋 { BackGround(7, 0); regrex1 = x; regrey1 = y; printf("●"); count++; status[x][y] = 2; } void machine_chess(int x, int y)//电脑落子 { BackGround(7, 0); status[x][y] = 2; regrex1 = x; regrey1 = y; count++; gotoxy(y, x); printf("●"); } int judge_chess(int x, int y)//判断这个地方是否有棋子 { if (status[x][y] == 0) return 0; else return 1; } int judge_winner(int x, int y, int temp)//判断输赢 { int i, j, n1, n2; n1 = n2 = 0; for (i = x, j = y + 4; j <= 58; j += 4)//右 { if (status[i][j] == temp) n1++; else break; } for (i = x, j = y; j >= 2; j -= 4)//左 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; n1 = n2 = 0; for (i = x, j = y; i >= 1; i -= 2)//上 { if (status[i][j] == temp) n1++; else break; } for (i = x + 2, j = y; i <= 30; i += 2)//下 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; n1 = n2 = 0; for (i = x - 2, j = y + 4; i >= 1 && j <= 58; i -= 2, j += 4)//右上 { if (status[i][j] == temp) n1++; else break; } for (i = x, j = y; i <= 30 && j >= 2; i += 2, j -= 4)//左下 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; n1 = n2 = 0; for (i = x, j = y; i >= 0 && j >= 0; i -= 2, j -= 4)//左上 { if (status[i][j] == temp) n1++; else break; } for (i = x + 2, j = y + 4; i <= 30 && j <= 58; i += 2, j += 4)//右下 { if (status[i][j] == temp) n2++; else break; } if (n1 + n2 >= 5) return temp; return 0; } void machine_attack()//电脑进攻权值 { int i1, j1; int k1, k2, k; int i, j; for (i = 1; i <= 30; i += 2) { for (j = 2; j <= 58; j += 4) { if (status[i][j]) Value1[i][j] = 0; if (status[i][j] == 0) { k1 = k2 = 0; for (i1 = i, j1 = j - 4; j1 >= 2; j1 -= 4)//往左数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i, j1 = j + 4; j1 <= 58; j1 += 4)//往右数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k = k1>k2 ? k1 : k2; k1 = k2 = 0; for (i1 = i - 2, j1 = j; i1 >= 1; i1 -= 2)//往上数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i + 2, j1 = j; i1 <= 30; i1 += 2)//往下数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i - 2, j1 = j - 4; i1 >= 0 && j1 >= 0; i1 -= 2, j1 -= 4)//往左上数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i + 2, j1 = j + 4; i1 <= 30 && j1 <= 58; i1 += 2, j1 += 4)//往右下数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i + 2, j1 = j - 4; i1 <= 30 && j1 >= 2; i1 += 2, j1 -= 4)//往左下数寻找电脑棋子数 { if (status[i1][j1] == 2) k1++; else break; } for (i1 = i - 2, j1 = j + 4; i1 >= 1 && j1 <= 58; i1 -= 2, j1 += 4)//往右上数寻找电脑棋子数 { if (status[i1][j1] == 2) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; switch (k) { case 3: Value1[i][j] = 15; break; case 4: Value1[i][j] = 25; break; default: Value1[i][j] = 3 + 2 * k; break; } } } } } void machine_defend()//防守权值 { int i1, j1; int k1, k2, k; int i, j; for (i = 1; i <= 30; i += 2) { for (j = 2; j <= 58; j += 4) { if (status[i][j]) Value2[i][j] = 0; if (status[i][j] == 0) { k1 = k2 = 0; for (i1 = i, j1 = j - 4; j1 >= 2; j1 -= 4)//往左数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i, j1 = j + 4; j1 <= 58; j1 += 4)//往右数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k = k1>k2 ? k1 : k2; k1 = k2 = 0; for (i1 = i - 2, j1 = j; i1 >= 1; i1 -= 2)//往上数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i + 2, j1 = j; i1 <= 30; i1 += 2)//往下数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i - 2, j1 = j - 4; i1 >= 1 && j1 >= 2; i1 -= 2, j1 -= 4)//往左上数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i + 2, j1 = j + 4; i1 <= 30 && j1 <= 58; i1 += 2, j1 += 4)//往右下数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; k1 = k2 = 0; for (i1 = i + 2, j1 = j - 4; i1 <= 30 && j1 >= 2; i1 += 2, j1 -= 4)//往左下数寻找玩家棋子数 { if (status[i1][j1] == 1) k1++; else break; } for (i1 = i - 2, j1 = j + 4; i1 >= 1 && j1 <= 58; i1 -= 2, j1 += 4)//往右上数寻找玩家棋子数 { if (status[i1][j1] == 1) k2++; else break; } k1 = k1>k2 ? k1 : k2; k = k>k1 ? k : k1; switch (k) { case 3: Value2[i][j] = 10; break; case 4: Value2[i][j] = 20; break; default: Value2[i][j] = 2 + k * 2; } } } } } void find_position()//找到最有价值的位置 { int k1 = 0, k2 = 0; int i, j, max = 0; for (i = 1; i <= 30; i += 2) for (j = 2; j <= 58; j += 4) { if (max <= Value1[i][j]) { max = Value1[i][j]; k1 = i; k2 = j; } } for (i = 1; i <= 30; i += 2) for (j = 2; j <= 58; j += 4) { if (max <= Value2[i][j]) { max = Value2[i][j]; k1 = i; k2 = j; } } direct[1] = k1; //将找到的位置传给光标 direct[0] = k2; } void man_man()//人人对战模式 { loop5:system("cls"); char key; int control; gotoxy(2, 3); printf("1.红 子 先 手"); gotoxy(2, 5); printf("2.白 子 先 手"); gotoxy(2, 7); printf("(输入相应序号选择)"); key = _getch(); system("cls"); if (key == '1') control = 1; else if (key == '2') control = -1; else goto loop5; gotoxy(70, 5); printf(" 人 人 对 战 "); direct[1] = 15; direct[0] = 30; chess_board(); chess_menu(); while (flag == 0) { if (control == 1) { gotoxy(70, 22); BackGround(6, 0); printf(" 红 子 执 手 "); red_movexy(); red_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 1); } else { gotoxy(70, 22); BackGround(6, 0); printf(" 白 子 执 手 "); white_movexy(); white_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 2); } control = -control; } if (flag == 1) { BackGround(7, 0); MessageBox(NULL, "游戏结束,红子胜利", "五子棋游戏", MB_OK); } if (flag == 2) { MessageBox(NULL, "游戏结束,白子胜利", "五子棋游戏", MB_OK); } if (count >= 225) { MessageBox(NULL, "游戏结束,平局", "五子棋游戏", MB_OK); } } void man_machine()//人机对战模式 { loop6:system("cls"); char key; int control; gotoxy(2, 3); printf("1.玩 家 先 手(玩家为红子)"); gotoxy(2, 5); printf("2.电 脑 先 手(电脑为白子)"); gotoxy(2, 7); printf("(输入相应序号选择)"); key = _getch(); system("cls"); if (key == '1') control = 1; else if (key == '2') { control = 1; machine_chess(13, 26); } else goto loop6; gotoxy(70, 5); printf(" 人 机 对 战 "); direct[1] = 15; direct[0] = 30; chess_board(); chess_menu(); while (flag == 0) { if (control == 1) { gotoxy(70, 22); BackGround(6, 0); printf(" 玩 家 执 手 "); red_movexy(); red_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 1); } else { gotoxy(70, 22); BackGround(6, 0); printf(" 电 脑 执 手 "); machine_defend(); machine_attack(); find_position(); machine_chess(direct[1], direct[0]); flag = judge_winner(direct[1], direct[0], 2); } control = -control; } gotoxy(8, 18); if (flag == 1) { BackGround(7, 0); MessageBox(NULL, "太厉害了,您竟然战胜了电脑!", "五子棋游戏", MB_OK); } if (flag == 2) { MessageBox(NULL, "游戏结束,您输给了电脑", "五子棋游戏", MB_OK); } if (count >= 225) { MessageBox(NULL, "平局", "五子棋游戏", MB_OK); } } void Regret()//悔棋函数 { gotoxy(regrey, regrex); BackGround(0, 0); printf(" "); status[regrex][regrey] = 0; gotoxy(regrey1, regrex1); BackGround(0, 0); printf(" "); status[regrex1][regrey1] = 0; count -= 2; } void welcome()//游戏菜单 { int k; char choose; system("cls"); for (k = 2; k <= 16; k += 2)//游戏菜单 { gotoxy(5, k); printf("|-----------------|"); } gotoxy(5, 3); printf("| 五 子 棋 游 戏 |"); gotoxy(5, 5); printf("| 菜 单 |"); gotoxy(5, 7); printf("| 1.人 人 对 战 |"); gotoxy(5, 9); printf("| 2.人 机 对 战 |"); gotoxy(5, 11); printf("| 3.游 戏 帮 助 |"); gotoxy(5, 13); printf("| 4.作 者 信 息 |"); gotoxy(5, 15); printf("| 5.退 出 游 戏 |"); gotoxy(5, 18); printf("输入菜单对应序号进行操作"); gotoxy(5, 20); printf("祝您游戏愉快!"); gotoxy(30, 18); } char Gametips()//游戏帮助 { char choose; int key; system("cls"); gotoxy(2, 3); printf("游戏操作:"); gotoxy(4, 5); printf("① 红色棋子WASD移动光标选择下棋位置,按空格键确认,按Q悔棋"); gotoxy(4, 7); printf("② 白色棋子↑↓←→移动光标选择下棋位置,按0确认,按B悔棋"); gotoxy(2, 19); printf("(按E键返回,按其它任意键退出)"); return _getch(); } char Auther()//作者信息 { system("cls"); gotoxy(2, 3); printf("作者:张洪浩"); gotoxy(2, 5); printf("(按E键返回,按其它任意键退出)"); return _getch(); } int main(void) { system("title 五子棋"); system("mode con cols=92 lines=33"); char choose, temp; loop: welcome(); choose = _getch(); switch (choose){ case '1': man_man(); break; case '2': man_machine(); break; case '3': temp = Gametips(); if (temp == 'E' || temp == 'e') goto loop; break; case '4': temp = Auther(); if (temp == 'E' || temp == 'e') goto loop; break; //case '5': //int message=MessageBox(NULL,"是否退出?","友情提示",MB_OKCANCEL); //if(IDCANCEL==message) // goto loop; //if(IDOK==message) break; } } ```
C语言:合并有序双向链表问题
从txt文件中读取5 4 2 3 1 10 6 8 7 9 到数组中,建立了两个递增排序的双向链表,内容分别为 1 2 3 4 5和6 7 8 9 10,现在想将两个链表合并输出一个递增的双向链表,输出时少了1和6 两个数字,双向链表创建时没有设置头结点,怎么修改合并时的代码?或者,怎样创建带头结点的有序双向链表呢?大佬们救命 ``` #include "stdafx.h" #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; #include<fstream> #include<stdio.h> /* C program to insetail nodes in doubly linked list such that list remains in ascending order on printing from left to right */ struct LinkList // A linked list node { int data; struct LinkList *prior; struct LinkList *next; }; // Function to insetail new node void nodeInsetail(struct LinkList **head, struct LinkList **tail, int key) { struct LinkList *p = new LinkList; p->data = key; p->next = NULL; // If first node to be insetailed in doubly // linked list if (*head == NULL) { *head = p; *tail = p; (*head)->prior = NULL; return; } // If node to be insetailed has value less // than first node if ((p->data) < ((*head)->data)) { p->prior = NULL; (*head)->prior = p; p->next = (*head); (*head) = p; return; } // If node to be insetailed has value more // than last node if ((p->data) > ((*tail)->data)) { p->prior = (*tail); (*tail)->next = p; (*tail) = p; return; } // Find the node before which we need to // insert p. LinkList *temp = (*head)->next; while ((temp->data) < (p->data)) temp = temp->next; // Insert new node before temp (temp->prior)->next = p; p->prior = temp->prior; temp->prior = p; p->next = temp; } // Function to print nodes in from left to right void printList(struct LinkList *temp) { while (temp != NULL) { printf("%d ", temp->data); temp = temp->next; } } // Driver program to test above functions int main() { int num[10],i,j=0; int datalen=0; ifstream file("linklist.txt"); while( ! file.eof() ) file>>num[datalen++]; file.close(); struct LinkList *La = NULL, *pa = NULL; for(int i=0;i<5;i++) { nodeInsetail(&La, &pa,num[i]); } printf("\nDoubly linked listA on printing:"); printList(La); struct LinkList *Lb = NULL, *pb = NULL; for(int i=5;i<10;i++) { nodeInsetail(&Lb, &pb,num[i]); } printf("\nDoubly linked listB on printing:"); printList(Lb); printf("\n"); struct LinkList *Lc=NULL;//头 struct LinkList *pc=NULL;//备用地址 struct LinkList *q=NULL; Lc=(struct LinkList*)malloc(sizeof(struct LinkList)); pc=Lc;//备用合并链表起始地址 pa=La->next; pb=Lb->next; (这里有问题!) while(pa&&pb) { if(pa->data<pb->data) { Lc->next=pa; pa->prior=Lc; pa=pa->next; Lc=Lc->next; } else if(pa->data==pb->data) { Lc->next=pa; pa->prior=Lc; Lc=pa; pa=pa->next; q=pb->next; free(pb); pb=q; } else if(pa->data>pb->data) { Lc->next=pb; pb->prior=Lc; pb=pb->next; Lc=Lc->next; } } Lc->next=pa?pa:pb; free(Lb); printf("the result is:"); pa=pc->next; while(pa) { printf("%d ",pa->data); pa=pa->next; } return 0; } 执行结果如下(工作停止) Doubly linked listA on printing:1 2 3 4 5 Doubly linked listB on printing:6 7 8 9 10 the result is:2 3 4 5 7 8 9 10请按任意键继续. . . ```
c语言提示error LNK2019: 无法解析的外部符号
在c语言中实现对对象的管理 前面的代码是这样的 #include <stdlib.h> #include <stdio.h> #include "ObjMgt.h" typedef struct key{ unsigned int key1; unsigned int key2; unsigned int key3; struct key * next; }keyall ; /************************************************************************* 功能:增加单个对象 输入: key1 外部关键字 KEY1 key2 外部关键字KEY2 key3 外部关键字KEY3 输出:无 返回: -1 :失败(对象已经存在或者其它异常) 0 :成功 ***************************************************************************/ int length=0; keyall *phead; keyall *pend; int Addkeyall (unsigned int key1, unsigned int key2, unsigned int key3) { if(phead==NULL){ phead=(keyall *)malloc(sizeof(keyall)); pend=phead; } if(length>10000) return -1; keyall *p=phead; while(p!=NULL) { if(p->key1==key1&&p->key2==key2&&p->key3==key3) return -1; p=p->next; } keyall * temp; temp=(keyall * )malloc(sizeof(keyall)); temp->key1=key1; temp->key2=key2; temp->key3=key3; pend->next=temp; pend=temp; pend->next=NULL; length++; /*请实现*/ return 0; } /******************************************************************************** 功能:删除一个或多个对象 输入: key1 外部关键字 KEY1 key2 外部关键字 KEY2 key3 外部关键字 KEY3 输出:无 返回:无 说明:用例保证参数取值为合法值和通配符0xFFFFFFFF, 通配符表示0~65535范围内的任意值; 举例:key1=1,key2=2,key3= 0xFFFFFFFF,表示删除key1=1,key2=2的所有对象; key1,key2,key3取值全为0xFFFFFFFF时,表示删除所有对象。 *********************************************************************************/ void Deletekeyall (unsigned int key1, unsigned int key2, unsigned int key3) { keyall *p; keyall *pre; p=phead->next; pre=phead; bool keya=false; bool keyb=false; bool keyc=false; if(key1==0xFFFFFFFF) keya=true; if(key2==0xFFFFFFFF) keyb=true; if(key3==0xFFFFFFFF) keyc=true; while(p!=NULL) { if((keya||p->key1==key1)&&(keyb||p->key2==key2)&&(keya||p->key3==key3)) { pre->next=p->next; free(p); p=pre->next; } else { pre=p; p=p->next; } } return ; } /******************************************************************************** 功能:查询单个对象是否存在 输入: key1 外部关键字 KEY1 key2 外部关键字 KEY2 key3 外部关键字 KEY3 输出:无 返回: 0:不存在 1:存在 **********************************************************************************/ int IskeyallExist (unsigned int key1, unsigned int key2, unsigned int key3) { /*请实现*/ keyall *p; p=phead->next; while(p!=NULL) { if(key1==p->key1&&key2==p->key2&&key3==p->key3) return 1; } return 0; } /****************************************************************************************************** Description 清空所有对象 Prototype void Clear(); Input Param 无 Output Param 无 Return Value 无 ********************************************************************************************************/ void Clear(void) { /*在这里实现功能*/ return; } 别人的代码可以使用的是这样的 #include "ObjMgt.h" #include <vector> using namespace std; typedef struct{ unsigned int key1; unsigned int key2; unsigned int key3; }KEY; vector <KEY> allKey; /************************************************************************* 功能:增加单个对象 输入: key1 外部关键字 KEY1 key2 外部关键字KEY2 key3 外部关键字KEY3 输出:无 返回: -1 :失败(对象已经存在或者其它异常) 0 :成功 ***************************************************************************/ int AddObject (unsigned int key1, unsigned int key2, unsigned int key3) { /*请实现*/ if(allKey.size() > 10000) return -1; if(key1 > 65535 || key2 > 65535 || key3 > 65535) return -1; int i,j = allKey.size(); for(i = 0; i < j;i++) if(allKey[i].key1 == key1 && allKey[i].key2 == key2 && allKey[i].key3 == key3) return -1; KEY k = {key1,key2,key3}; allKey.push_back(k); return 0; } /******************************************************************************** 功能:删除一个或多个对象 输入: key1 外部关键字 KEY1 key2 外部关键字 KEY2 key3 外部关键字 KEY3 输出:无 返回:无 说明:用例保证参数取值为合法值和通配符0xFFFFFFFF, 通配符表示0~65535范围内的任意值; 举例:key1=1,key2=2,key3= 0xFFFFFFFF,表示删除key1=1,key2=2的所有对象; key1,key2,key3取值全为0xFFFFFFFF时,表示删除所有对象。 *********************************************************************************/ void DeleteObject (unsigned int key1, unsigned int key2, unsigned int key3) { /*请实现*/ bool allKey1,allKey2,allKey3; if(key1 == 0xffffffff) allKey1 = true; else allKey1 = false; if(key2 == 0xffffffff) allKey2 = true; else allKey2 = false; if(key3 == 0xffffffff) allKey3 = true; else allKey3 = false; int i,j = allKey.size(); vector<KEY>::iterator it ; it = allKey.begin(); while (it != allKey.end()) { if(allKey1 || it->key1 == key1) if(allKey2 || it->key2 == key2) if(allKey3 || it->key3 == key3){ it = allKey.erase(it); continue; } it++; } return ; } /******************************************************************************** 功能:查询单个对象是否存在 输入: key1 外部关键字 KEY1 key2 外部关键字 KEY2 key3 外部关键字 KEY3 输出:无 返回: 0:不存在 1:存在 **********************************************************************************/ int IsObjectExist (unsigned int key1, unsigned int key2, unsigned int key3) { /*请实现*/ if(key1 > 65535 || key2 > 65535 || key3 > 65535) return 0; int i,j = allKey.size(); for(i = 0; i < j;i++) if(allKey[i].key1 == key1 && allKey[i].key2 == key2 && allKey[i].key3 == key3) return 1; return 0; } /****************************************************************************************************** Description 清空所有对象 Prototype void Clear(); Input Param 无 Output Param 无 Return Value 无 ********************************************************************************************************/ void Clear(void) { /*在这里实现功能*/ allKey.clear(); return; } 结果我的连接出现如下错误 1>正在链接... 1>CExampleTest.obj : error LNK2019: 无法解析的外部符号 "void __cdecl DeleteObject(unsigned int,unsigned int,unsigned int)" (?DeleteObject@@YAXIII@Z),该符号在函数 "public: void __thiscall CExampleTest::TestCase01(void)" (?TestCase01@CExampleTest@@QAEXXZ) 中被引用 1>CExampleTest.obj : error LNK2019: 无法解析的外部符号 "int __cdecl IsObjectExist(unsigned int,unsigned int,unsigned int)" (?IsObjectExist@@YAHIII@Z),该符号在函数 "public: void __thiscall CExampleTest::TestCase01(void)" (?TestCase01@CExampleTest@@QAEXXZ) 中被引用 1>CExampleTest.obj : error LNK2019: 无法解析的外部符号 "int __cdecl AddObject(unsigned int,unsigned int,unsigned int)" (?AddObject@@YAHIII@Z),该符号在函数 "public: void __thiscall CExampleTest::TestCase01(void)" (?TestCase01@CExampleTest@@QAEXXZ) 中被引用 1>C:\Users\wang\Desktop\对象管理器\ObjMgt\project\Debug\ObjMgt.exe : fatal error LNK1120: 3 个无法解析的外部命令 1>生成日志保存在“file://c:\Users\wang\Desktop\对象管理器\ObjMgt\project\Debug\BuildLog.htm” 1>ObjMgt - 4 个错误,0 个警告 ========== 生成: 0 已成功, 1 已失败, 0 最新, 0 已跳过 ========== 找了一天了 把网上能够试一试的都试了一遍 ,还是不行
求助:关于在兼容DC上使用TextOut丢失问题
【1】我的想法是先在hdcm上绘图(单击鼠标左键一次就绘制一遍),但不立即更新客户区(未立即InvalidateRect)。 【2】在绘制后,先最小化窗口、再恢复窗口(windows应自动更新客户显示区)后,没有看到文字(矩形正常显示)!这是为什么呢? 【3】特别的,若连续使用多条TextOut,则只有最后一条TextOut不显示,其余均正常显示!若在最后一条TextOut后面再加一些函数,如:Rectangle/LineTo/GetPixel/InvilidateRect等等,就全都正常显示了! 如下是代码: ``` #include <windows.h> LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); DWORD WINAPI yzx(LPVOID asd);//在兼容DC上绘图的(专用)线程 char szClassName[ ]="WTF"; HBITMAP hbitmap; HDC hdcm; HANDLE hev;//控制(绘图)线程的开关 int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { HWND hwnd; MSG messages; WNDCLASSEX wincl; wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ "hjdl", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ 0, /* Windows decides the position */ 0, /* where the window ends up on the screen */ 1000, /* The programs width */ 800, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Make the window visible on the screen */ ShowWindow (hwnd, nFunsterStil); /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (message) /* handle the messages */ { case WM_CREATE: hdc=GetDC(hwnd); hdcm=CreateCompatibleDC(hdc); hbitmap=CreateCompatibleBitmap(hdc,500,500); SelectObject(hdcm,hbitmap); ReleaseDC(hwnd,hdc); hev=CreateEvent(NULL,0,0,NULL); CreateThread(NULL,0,yzx,hwnd,0,NULL); break; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); BitBlt(hdc,0,0,500,500,hdcm,0,0,SRCCOPY); EndPaint(hwnd,&ps); break; case WM_LBUTTONUP: SetEvent(hev); break; case WM_DESTROY: CloseHandle(hev); DeleteObject(hdcm); DeleteObject(hbitmap); PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; default: /* for messages that we don't deal with */ return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } DWORD WINAPI yzx(LPVOID asd) { char temp[111]; int k=0; while(1) { WaitForSingleObject(hev,INFINITE); Rectangle(hdcm,0,0,500,500); sprintf(temp,"%d",++k); TextOut(hdcm,10,10,temp,strlen(temp)); } return 0; } ```
关于在兼容DC上使用TextOut丢失问题
【1】我的想法是先在hdcm上绘图(单击鼠标左键一次就绘制一遍),但不立即更新客户区(未立即InvalidateRect)。 【2】在绘制后,先最小化窗口、再恢复窗口(windows应自动更新客户显示区)后,没有看到文字(矩形正常显示)!这是为什么呢? 【3】特别的,若连续使用多条TextOut,则只有最后一条TextOut不显示,其余均正常显示!若在最后一条TextOut后面再加一些函数,如:Rectangle/LineTo/GetPixel/InvilidateRect等等,就全都正常显示了! ``` #include <windows.h> LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); DWORD WINAPI yzx(LPVOID asd);//在兼容DC上绘图的(专用)线程 char szClassName[ ]="WTF"; HBITMAP hbitmap; HDC hdcm; HANDLE hev;//控制(绘图)线程的开关 int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { HWND hwnd; MSG messages; WNDCLASSEX wincl; wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ "hjdl", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ 0, /* Windows decides the position */ 0, /* where the window ends up on the screen */ 1000, /* The programs width */ 800, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Make the window visible on the screen */ ShowWindow (hwnd, nFunsterStil); /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (message) /* handle the messages */ { case WM_CREATE: hdc=GetDC(hwnd); hdcm=CreateCompatibleDC(hdc); hbitmap=CreateCompatibleBitmap(hdc,500,500); SelectObject(hdcm,hbitmap); ReleaseDC(hwnd,hdc); hev=CreateEvent(NULL,0,0,NULL); CreateThread(NULL,0,yzx,hwnd,0,NULL); break; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); BitBlt(hdc,0,0,500,500,hdcm,0,0,SRCCOPY); EndPaint(hwnd,&ps); break; case WM_LBUTTONUP: SetEvent(hev); break; case WM_DESTROY: CloseHandle(hev); DeleteObject(hdcm); DeleteObject(hbitmap); PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; default: /* for messages that we don't deal with */ return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } DWORD WINAPI yzx(LPVOID asd) { char temp[111]; int k=0; while(1) { WaitForSingleObject(hev,INFINITE); Rectangle(hdcm,0,0,500,500); sprintf(temp,"%d",++k); TextOut(hdcm,10,10,temp,strlen(temp)); } return 0; } ```
(C语言)在二叉搜索树的学习时遇到了问题,求大佬帮忙看看
如题,在学习二叉搜索树时想要自己添加一些内容,但是不知道为什么就是会出错,自己感觉好像问题出在创建二叉树的地方,但是不知道怎么改.希望大佬能帮忙看看,如果能配上讲解就更好了,感谢. 下面贴上代码,之后是罗列的一些问题,如果代码中还有问题希望大佬能指点下我,谢谢: 项目总共三个文件,二叉搜索树头文件.h和.c文件,然后一个用于测试的主函数.c (二叉搜索树头文件) BSTree.h ``` #ifndef BSTREE_H #define BSTREE_H typedef int DataType; //二叉排序树节点定义 struct BinSearchTreeNode { DataType data; struct BinSearchTreeNode *leftchild; struct BinSearchTreeNode *rightchild; }; typedef struct BinSearchTreeNode *BSTreeNode; typedef struct BinSearchTreeNode *BinSearchTree; /****************************************************************/ /* BinSearchTree *create() */ /* 功能:创建二叉排序树 */ /* 输入参数:无 */ /* 返回值:二叉排序树 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BinSearchTree create(); /****************************************************************/ /* void InOrder(BinSearchTree ptree) */ /* 功能:中序遍历二叉排序树 */ /* 输入参数ptree:二叉排序树 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void InOrder(BinSearchTree ptree); /****************************************************************/ /* BSTreeNode BSTSearch(BinSearchTree bt, DataType key) */ /* 功能:检索二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要检索的元素 */ /* 返回值:成功返回NULL,失败返回元素插入的父结点位置 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BSTreeNode BSTSearch(BinSearchTree bt, DataType key); /****************************************************************/ /* int BSTInsert(BinSearchTree bt, DataType key) */ /* 功能:在二叉排序树中插入元素key */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要插入的元素 */ /* 返回值:成功插入返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTInsert(BinSearchTree bt, DataType key); /****************************************************************/ /* int BSTgetMax(BinSearchTree *bt) */ /* 功能:查找二叉排序树的最大值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMax(BinSearchTree *bt); /****************************************************************/ /* int BSTgetMin(BinSearchTree *bt) */ /* 功能:查找二叉排序树的最小值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMin(BinSearchTree *bt); /****************************************************************/ /* int BSTDelete1(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法1 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete1(BinSearchTree *bt, DataType key); /****************************************************************/ /* int BSTDelete2(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法2 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete2(BinSearchTree *bt, DataType key); /****************************************************************/ /* void BST_Destory(BinSearchTree bt) */ /* 功能:销毁二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BST_Destory(BinSearchTree bt); #endif // BSTREE_H ``` 对应的c文件 BSTree.c ``` #include <stdio.h> #include <stdlib.h> #include "BSTree.h" /****************************************************************/ /* BinSearchTree create() */ /* 功能:创建二叉排序树,注意这里输入的应该是先序序列,并且保证是一*/ /* 个二叉排序树的先序序列 */ /* 输入参数:无 */ /* 返回值:二叉排序树 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BinSearchTree create() { int ch = 0;//初始化 BinSearchTree bt; scanf_s("%d", &ch); if (ch == -1) { bt = NULL; } else { bt = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode)); bt->data = ch; //递归赋值左子树 bt->leftchild = create(); //递归赋值右子树 bt->rightchild = create(); } //返回根节点 return bt; } /****************************************************************/ /* void InOrder(BinSearchTree ptree) */ /* 功能:中序遍历二叉排序树 */ /* 输入参数ptree:二叉排序树 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void InOrder(BinSearchTree ptree) { if (ptree == NULL) { return; } InOrder(ptree->leftchild); printf("%d", ptree->data); InOrder(ptree->rightchild); } /****************************************************************/ /* BSTreeNode BSTSearch(BinSearchTree bt, DataType key) */ /* 功能:检索二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要检索的元素 */ /* 返回值:成功返回NULL,失败返回元素插入的父结点位置 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BSTreeNode BSTSearch(BinSearchTree bt, DataType key) { BSTreeNode p, parent; p = bt; parent = p; //记录待插入结点的父结点 while (p) { parent = p; //当查找到时提示,返回NULL if (p->data == key) { printf("Exist this key\n"); return NULL; } //根结点大于要查的结点,进入左分支查找 if (p->data > key) { p = p->leftchild; } //根结点小于要查的结点,进入右分支查找 else { p = p->rightchild; } }//p=NULL,跳出循环 return parent; //查找失败,返回parent }//return NULL和parent是为了便于之后的操作 /****************************************************************/ /* int BSTInsert(BinSearchTree bt, DataType key) */ /* 功能:在二叉排序树中插入元素key */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要插入的元素 */ /* 返回值:成功插入返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTInsert(BinSearchTree bt, DataType key) { BSTreeNode p, temp; temp = BSTSearch(bt, key); //temp保存查找之后的结果 //已存在,返回0 if (temp == NULL) { printf("Exist this key\n"); return 0; } //申请结点的内存空间 p = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode)); //申请失败提示 if (p == NULL) { printf("Alloc Failure!\n"); return 0; } p->data = key; //数据域赋值,左右指针域默认为空 //p->leftchild = NULL; //左子树指针域赋值 //p->rightchild = NULL; //右子树指针域赋值 if (key < temp->data) { temp->leftchild = p; //作为左子树插入 } else { temp->rightchild = p; //作为右子树插入 } return 1; } /****************************************************************/ /* int BSTgetMax(BinSearchTree bt) */ /* 功能:查找二叉排序树的最大值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMax(BinSearchTree *bt) { BSTreeNode temp; temp = bt; if (temp) { while (temp->leftchild) { temp = temp->leftchild; } printf("%d", temp->data); } } /****************************************************************/ /* int BSTgetMin(BinSearchTree bt) */ /* 功能:查找二叉排序树的最小值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMin(BinSearchTree *bt) { BSTreeNode temp; temp = bt; if (temp) { while (temp->rightchild) { temp = temp->rightchild; } printf("%d", temp->data); } } /****************************************************************/ /* int BSTDelete1(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法1 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete1(BinSearchTree *bt, DataType key) { BSTreeNode parent, p, maxpl; p = *bt; parent = NULL; //查找被删除的结点 while (p != NULL) { if (p->data == key) break; //查找到了,跳出循环 if (p->data > key) p = p->leftchild; else p = p->rightchild; }//查询结束 if (p == NULL) { printf("%d not exist\n", key); return 0; } //只有右子树的情况 if (p->leftchild == NULL) { //如果被删除的结点是根结点,那就要修改的是二叉排序树的根 if (parent == NULL) *bt = p->rightchild; //检查是左孩子还是右孩子 else if (parent->leftchild == p) parent->leftchild = p->rightchild; else parent->rightchild = p->rightchild; } //既有左子树也有右子树 if (p->leftchild != NULL) { BSTreeNode parentp; //parentp记录maxpl的父结点 parentp = p; maxpl = p->leftchild; //对称遍历中,右侧的总是大的数 //定位p的左子树中的最大结点maxpl while (maxpl->rightchild != NULL) { parentp = maxpl; maxpl = maxpl->rightchild; } p->data = maxpl->data; //修改p的数据域为maxpl的值 if (parentp == p) //如果maxpl的父结点是p p->leftchild = maxpl->leftchild; //修改p结点的左指针 else parentp->rightchild = maxpl->leftchild; //修改父结点的右指针 p = maxpl; //更新p指针为maxpl结点以便删除 } //释放空间 free(p); return 1; } /****************************************************************/ /* int BSTDelete2(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法2 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete2(BinSearchTree *bt, DataType key) { //parent记录p的父结点,maxpl记录p的左子树中的关键码最大结点 BSTreeNode parent, p, maxpl; p = *bt; parent = NULL; //查找被删除的结点 while (p != NULL) { if (p->data == key) break; //查找到了,跳出循环 parent = p; //注意这一句 if (p->data > key) p = p->leftchild; else p = p->rightchild; }//查找结束 if (p == NULL) { printf("%d not exist!\n", key); return 0; } //只有右子树的情况 if (p->leftchild == NULL) { //删除的是根结点,做特殊处理 if (parent == NULL) *bt = p->rightchild; //p是父结点parent的左孩子,则修改父结点的左指针 else if (parent->leftchild == p) parent->leftchild = p->rightchild; else parent->rightchild = p->rightchild; } //以上和方法1几乎完全相同 //有左子树和右子树 if (p->leftchild != NULL) { maxpl = p->leftchild; //定位左子树中的最大结点maxpl while (maxpl->rightchild != NULL) maxpl = maxpl->rightchild; maxpl->rightchild = p->rightchild; if (parent == NULL) *bt = p->leftchild; //p是父结点parent的左孩子,则修改父结点的左指针 else if (parent->leftchild == p) parent->leftchild = p->leftchild; //p是父结点parent的右孩子,则修改父结点的右指针 else parent->rightchild = p->leftchild; } free(p); //释放结点p return 1; } /****************************************************************/ /* void BST_Destory(BinSearchTree *bt) */ /* 功能:递归销毁二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BST_Destory(BinSearchTree bt) { if (bt) { BST_Destory(bt->leftchild); BST_Destory(bt->rightchild); free(bt); } } ``` 主函数.c文件 main.c ``` #include <stdio.h> #include <stdlib.h> #include "BSTree.h" //用于测试的二叉树先序序列,-1表示空 //40 10 5 -1 -1 -1 55 45 -1 48 47 -1 -1 52 -1 -1 60 -1 70 -1 -1 void main() { BinSearchTree bt; int n = 0; printf("输入二叉排序树的先序序列:\n"); bt = create(); printf("输入要查找的元素,存在返回1,不存在返回0,插入:"); scanf_s("%d", &n); printf("%d\n", BSTSearch(bt, n)->data); printf("输入要插入的元素,成功插入返回1,否则返回0:"); scanf_s("%d", &n); printf("%d\n", BSTInsert(bt, n)); //printf("二叉排序树的中序遍历序列:\n"); //InOrder(bt); printf("\n第一种删除方法,输入要删除的元素,成功返回1,不成功返回0:"); scanf_s("%d", &n); printf("%d\n", BSTDelete1(&bt, n)); //printf("二叉排序树的中序遍历序列:\n"); //InOrder(bt); printf("\n第二种删除方法,输入要删除的元素,成功返回1,不成功返回0:"); scanf_s("%d", &n); printf("%d\n", BSTDelete2(&bt, n)); //printf("二叉排序树的中序遍历序列:\n"); //InOrder(bt); } ``` **问题:**<br> <br> * [0]生成解决方案的时候有警告,但是我忽略了,因为显示程序生成成功了,感觉这几个警告是最大的问题,第4个问题中我详细列出了这些内容<br> <br> * [1]二叉树的递归创建自己感觉有问题,尤其是内存申请这里<br> <br> <code>bt = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode));</code><br> <br> * [2]中序遍历的内容在搜索到左子树底的时候本应返回上一步时会出现异常,建立断点异常内容如下:<br> 引发了异常: 读取访问权限冲突。<br> **ptree** 是 0xCDCDCDCD。<br> <br> * [3]由于中序遍历有异常,所以我注释掉了所有的相关内容,编译时没什么问题,但是删除结点的函数也会出现类似的异常,异常内容如下:<br> 引发了异常: 读取访问权限冲突。<br> **maxpl** 是 0xCDCDCDCD。<br> <br> <br> * [4]好吧,我就都注释掉了,看看别的代码是不是有问题,重新生成解决方案,熟悉的警告出现了,c语言是速成的结构体这块不是很明了,感觉应该是创建二叉搜索树的代码有问题,或者是结构体创建有问题,以下是警告的内容:<br> */bstree.c(24): warning C4047: “=”:“BinSearchTree”与“BSTreeNode *”的间接级别不同<br> */bstree.c(108): warning C4047: “=”:“BSTreeNode”与“BSTreeNode *”的间接级别不同<br> *\bstree.c(139): warning C4047: “=”:“BSTreeNode”与“BinSearchTree *”的间接级别不同<br> *\bstree.c(160): warning C4047: “=”:“BSTreeNode”与“BinSearchTree *”的间接级别不同<br> <br> 第24行:<br> BinSearchTree create()<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;bt = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode));<br> &nbsp;&nbsp;...<br> }<br> <br> 第108行:<br> int BSTInsert(BinSearchTree bt, DataType key)<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;//申请结点的内存空间<br> &nbsp;&nbsp;&nbsp;&nbsp;p = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode));<br> &nbsp;&nbsp;...<br> }<br> <br> 第139行:<br> void BSTgetMax(BinSearchTree *bt)<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;temp = bt;<br> &nbsp;&nbsp;...<br> }<br> <br> 第160行:<br> void BSTgetMin(BinSearchTree *bt)<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;temp = bt;<br> &nbsp;&nbsp;...<br> }<br> <br> 以上,求各位大佬指点迷津<br>
c语言 free() 需要释放分配结构里面分配的结构内存么-贪吃蛇-链表
![结构如下](https://img-ask.csdn.net/upload/201907/09/1562648615_804996.png) ![这样分配了内存](https://img-ask.csdn.net/upload/201907/09/1562648663_621565.png) ![释放链表](https://img-ask.csdn.net/upload/201907/09/1562648697_654819.png) 这需要释放node中 position 分配的内存么(注释地方); 我 如果释放position 就会报错 有大佬知道么 更新;-> 出链表的时候释放没报错 ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562739918_882454.png) ------ ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562739943_97624.png) ------- 当最后程序结束是清空释放 position 报错 ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562740020_898931.png) -------- ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562740040_80161.png) ---------- ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562740062_890709.png) --------- ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562740074_826811.png) 我认为position位置应该是有效的,程序其他地方也没去变动position地址 代码片段(代码主要是github大佬的代码,https://github.com/mnisjk/snake.git) ``` #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <curses.h> #include <sys/select.h> #include <time.h> #define SRC_WIDTH 70 #define SRC_HEIGHT 20 WINDOW *g_mainwin; int g_oldcur, g_score = 0, g_width, g_height; typedef struct { int x; int y; } pos; pos fruit; bool *spaces; // queue stuff struct s_node { pos *position; struct s_node *prev; struct s_node *next; } *front = NULL,*back =NULL; typedef struct s_node node; pos * peek(){ return front == NULL ? NULL : front->position; } node * dequeue(){ node *oldfront = front; front = front->next; return oldfront; } //queue a position at the back void enqueue(pos position) { pos *newpos = (pos *)malloc(sizeof(position)); node *newnode = (node *)malloc(sizeof(node)); newpos->x = position.x; newpos->y = position.y; newnode->position = newpos; if(front == NULL && back ==NULL) front = back = newnode; else { back->next = newnode; newnode->prev = back; back = newnode; } } //end queue stuff //start snake stuff void snake_write_text(int y,int x,char *str) { mvwaddstr(g_mainwin, y, x, str); } //draw the borders void snake_draw_board() { int i; for (i = 0; i < g_height;i++){ snake_write_text(i, 0, "|"); snake_write_text(i, g_width - 1, "|"); } for (i = 0; i < g_width;i++) { snake_write_text(0, i, "-"); snake_write_text(g_height, i, "-"); } snake_write_text(g_height + 1, 2, "Score:"); } //resets the terminal window and clears up the mem void snake_game_over(int i,pos p) { free(spaces); while (front) { node *n = front; front = front->next; free(n->position); free(n); } endwin(); printf("%d\n", i); printf("%d,%d\n",p.x,p.y); exit(0); } //当前位置是否在界限里面 bool snake_in_bounds(pos position) { return position.y < g_height && position.y > 0 && position.x < g_width - 1 && position.x > 0; } //2d坐标映射1d int snake_cooridinate_to_index(pos position) { return g_width * position.y + position.x; } //1d映射对应的坐标 pos snake_index_to_coordinate(int index) { int x = index % g_width; int y = index / g_width; return (pos){x, y}; } //随机出现水果 void snake_draw_fruit() { attrset(COLOR_PAIR(3)); int idx; do{ idx = rand() % (g_width * g_height); fruit = snake_index_to_coordinate(idx); } while (spaces[idx] || !snake_in_bounds(fruit)); attron(A_REVERSE); snake_write_text(fruit.y, fruit.x, " "); attroff(A_REVERSE); } //handles moving the snake for each iteration bool snake_move_player(pos head) { attrset(COLOR_PAIR(1)); //check if we ran into ourself int idx = snake_cooridinate_to_index(head); if(spaces[idx]){ pos te = {2, 2}; snake_game_over(2,te); } spaces[idx] = true; enqueue(head); //check if we're eating the fruit if(head.x == fruit.x && head.y == fruit.y) { snake_draw_fruit(); g_score += 10; }else{ node *tail = dequeue(); pos tem = *(tail->position); spaces[snake_cooridinate_to_index(tem)] = false; snake_write_text(tem.y, tem.x, " "); //if(tail->position != NULL) free(tail->position); free(tail); tail = NULL; } attron(A_REVERSE); snake_write_text(head.y, head.x, " "); attroff(A_REVERSE); char buffer[25]; sprintf(buffer, "%d", g_score); attrset(COLOR_PAIR(2)); snake_write_text(g_height+1,9,buffer); } void check_move_pos(pos *t_head,pos *head){ pos temp; node t_node = *back; if (&t_node == NULL) return ; else { if(t_node.prev != NULL){ if((t_node.prev)->position != NULL){ temp = *((t_node.prev)->position); if(t_head->x == head->x){ //x方向 if(temp.x == head->x && temp.y == head->y){ if(t_head->y > temp.y) head->y += 2; else head->y -= 2; } }else if(t_head->y == head->y) { //y方向 if(temp.x == head->x && temp.y == head->y){ if(t_head->x > temp.x) head->x += 2; else head->x -= 2; } } } } } } int main(int argc,char *argv[]) { int key = KEY_RIGHT; if((g_mainwin = initscr()) == NULL) { perror("error initialising ncursess"); exit(EXIT_FAILURE); } srand(time(NULL)); noecho(); curs_set(2); halfdelay(1); keypad(g_mainwin, TRUE); g_oldcur = curs_set(0); start_color( ); init_pair( 1, COLOR_RED, COLOR_BLACK ); init_pair( 2, COLOR_GREEN, COLOR_BLACK ); init_pair( 3, COLOR_YELLOW, COLOR_BLACK ); init_pair( 4, COLOR_BLUE, COLOR_BLACK ); init_pair( 5, COLOR_CYAN, COLOR_BLACK ); init_pair( 6, COLOR_MAGENTA, COLOR_BLACK ); init_pair( 7, COLOR_WHITE, COLOR_BLACK ); getmaxyx( g_mainwin, g_height, g_width ); g_width = g_width < SRC_WIDTH ? g_width : SRC_WIDTH; g_height = g_height < SRC_HEIGHT ? g_height : SRC_HEIGHT; // Set up the 2D array of all spaces spaces = (bool*) malloc( sizeof( bool ) * g_height * g_width ); snake_draw_board( ); snake_draw_fruit( ); pos head = { 5,5 }; enqueue( head ); // Event loop while( 1 ) { pos t_head = head; int in = getch(); if( in != ERR ) key = in; switch (key) { case KEY_DOWN: case 'k': case 'K': head.y++; break; case KEY_RIGHT: case 'l': case 'L': head.x++; break; case KEY_UP: case 'j': case 'J': head.y--; break; case KEY_LEFT: case 'h': case 'H': head.x--; break; } //禁止反向 check_move_pos(&t_head, &head); if (!snake_in_bounds(head)) snake_game_over(3, head); else snake_move_player(head); } pos te = {4, 4}; snake_game_over(4,te); } ``` 调试了 越来混乱了,一运行蛇啥不吃,链表里面应该只有一个地址才对,出链表也对应的释放了地址.可调试出现了最后出现了3个 ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562744544_820667.png) 更新-> 搞好了, ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562750107_36874.png) 新建节点 node *newnode = (node *)malloc(sizeof(node));时候,莫名 newnode 中 next 指针指向了未知 地址,按原本意思应该指向 0x0空地址 所有 newnode->next = newnode->prev = NULL; 初始化一下,不然结束的释放链表 就会找到这个 0x20 的地址 ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562750298_228211.png) --- ![图片说明](https://img-ask.csdn.net/upload/201907/10/1562750311_263565.png) 一切正常了 ,高兴
C语言求大神帮忙看看写的二叉树删除,为什么我的这道程序执行顺序异常
写的一道数据结构树二叉树删除的作业 关于数据结构的正确与否不需要大神考虑,只要帮我看看为什么这道程序执行顺序这么奇怪 **代码比较长:请关注main函数里面出现的几个函数就行了,其他不用管** ``` #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> typedef struct aaa { int key; char name[20]; char address[100]; } element; typedef struct node *nodePointer; typedef struct node { nodePointer leftChild; element data; nodePointer rightChild; }node; node* add( nodePointer *q ); void printall( struct node *q ); void searchSmallestAmongLargerNodes( nodePointer search, nodePointer* parentSmall, nodePointer *searchSmall ) { nodePointer temp = search->rightChild; if ( temp->rightChild = NULL ) { *parentSmall = search; *searchSmall = temp; }else { *parentSmall = temp; *searchSmall = temp->rightChild; } } /* nodePointer root = NULL; */ int searchParentToInsert( struct node *root, int key, struct node **parentPtr ) { int found = 0; struct node *parent = NULL, *search = root; while ( search != NULL ) { if ( key == search->data.key ) { found = 1; break; }else { parent = search; if ( key < search->data.key ) search = search->leftChild; else search = search->rightChild; } } *parentPtr = parent; return(found); } void insertBST( struct node **rootPtr, element x ) { struct node *ptr, *parent; int found = 0; found = searchParentToInsert( *rootPtr, x.key, &parent ); if ( found == 1 ) { printf( "The key already exists in the tree!\n" ); } else{ ptr = (node *) malloc( sizeof(node) ); ptr->data = x; ptr->leftChild = ptr->rightChild = NULL; if ( *rootPtr == NULL ) { *rootPtr = ptr; } else { if ( x.key < parent->data.key ) parent->leftChild = ptr; else parent->rightChild = ptr; } } } int deleteBST( struct node **rootPtr, int key ) { int find1 = 0; struct node **root, **parent, *search, *parentSmall, *searchSmall; root = (struct node * * ) malloc( sizeof(struct node*) ); *root = *rootPtr; parent = (struct node * * ) malloc( sizeof(struct node*) ); search = (struct node * ) malloc( sizeof(struct node) ); searchSmall = (struct node * ) malloc( sizeof(struct node) ); find1 = searchParentToInsert( *root, key, parent ); if ( find1 == 0 ) { return(0); } /* NOT FOUND} */ /* case 1. Deletion of a leaf node. */ if ( (search->leftChild == NULL) && (search->rightChild == NULL) ) free( search ); if ( (search->leftChild == NULL) || (search->rightChild == NULL) ) { { if ( search->leftChild != NULL ) (*parent) = (*parent)->leftChild; else (*parent) = (*parent)->rightChild; } if ( (search->leftChild != NULL) && (search->rightChild != NULL) ) { /* find the smallest among the larger than the key */ searchSmallestAmongLargerNodes( search, &parentSmall, &searchSmall ); search->data.key = searchSmall->data.key; if ( search == parentSmall ) parentSmall->rightChild = searchSmall->rightChild; else parentSmall->leftChild = searchSmall->rightChild; free( searchSmall ); } } return(0); } int main( void ) { int cc; nodePointer q; q = (struct node *) malloc( sizeof(struct node) ); q = add( &q ); cc = deleteBST( &q, 3 ); printall( q ); } nodePointer add( nodePointer *q ) { int coun = 0; while ( 1 ) { struct node *newnode = NULL; newnode = (struct node *) malloc( sizeof(struct node) ); scanf( "%d,", &newnode->data.key ); if ( newnode->data.key == -1 ) { return(*q); } newnode->leftChild = NULL; newnode->rightChild = NULL; scanf( "%[^,]%[^\n]", newnode->data.name, newnode->data.address ); fflush( stdin ); /* gets_s(newnode->add); */ if ( coun == 0 ) { *q = newnode; coun++; }else { insertBST( q, newnode->data ); } } return(*q); } void printall( struct node *q ) /* inorder */ { struct node *temp = q; if ( temp ) { printall( temp->leftChild ); printf( "%d %s %s\n", temp->data.key, temp->data.name, temp->data.address ); printall( temp->rightChild ); } } ``` 我输入了测试代码是 1,asdf,sdf 2,dsf,sdf 3,sdf,sdf -1 首先看下 nodePointer add(nodePointer *q) 函数(add函数建立二叉树) 循环输入知道输入-1结束 但是当我输入第一行1,asdf,sdf结束的时候,就会main函数从上到下过一下(我用了断点调试) 输入第二行第三行也是这样 输入-1结束输入的时候 cc=deleteBST(&q, 3);这一行直接跳过 (按照顺序执行,这一行应该执行啊) (deleteBST删除二叉树中的 3 ) ![图片说明](https://img-ask.csdn.net/upload/201804/10/1523345379_64368.png) **请大神输入我的测试代码调试一下** **20分等解决问题的大神来拿哦**
txt文件信息读不进去 c语言
``` #include <stdio.h> #include <stdlib.h> #include<string.h> #include <Windows.h> #define MAXN 10000 #define max 10 #define p 23 int Work(); int Delete(); void insert(int adr); void Number(int key); void Departure(char temp[]); void Terminal(char temp[]); void Start(float temp); void Arrival(float temp); void FileOutput(); void Output(int adr); int hashlen = 0; typedef struct { char departure[6]; char terminal[6]; float start; float arrive; int num; float date; }flight; flight line; typedef struct { flight data; int cnt; }Hash; Hash ha[MAXN]; int main() { Work(); FileOutput(); return 0; } int Work() { while (1) { printf("********欢迎使用航班信息查询和检索系统********\n"); printf("1.清屏\t\n"); printf("2.航班号\t3.起点站\t\n"); printf("4.终点站\t5.起飞时间\t\n"); printf("6.到达时间\t7.退出系统\t\n"); printf("**********************************************\n"); printf("请选择将要使用的功能\n"); int t, temp; char temp2[5]; float temp3; scanf("%d", &t); switch (t) { case 1:Delete(); break; case 2: { printf("请输入航班号"); scanf("%d", &temp); Number(temp); break; } case 3: { printf("请输入起点站"); getchar(); gets_s(temp2); Departure(temp2); break; } case 4: { printf("请输入终点站"); getchar(); gets_s(temp2); Terminal(temp2); break; } case 5: { printf("请输入起飞时间"); scanf("%f", &temp3); Start(temp3); break; } case 6: { printf("请输入到达时间"); scanf("%f", &temp3); Arrival(temp3); break; } case 7: { exit(0); break; } } } } int Delete() { system("cls"); return 0; } void Number(int key) { int i=0, adr; int k = key; adr = k % p; insert(adr); if (ha[adr].data.num == key) { Output(adr);//在屏幕上显示 } else printf( "对不起,查无此航班!\n" ); } void Departure(char temp[]) { int i=0, flag = 0; for (i = 0; i < MAXN; ++i)//顺序查找 { if (flag) break; else if (strcmp(ha[i].data.departure,temp)==0) { Output(i); flag = 1;//标记是否查询到相关信息 } } if (!flag) printf( "对不起,查无此航班!\n" ); } void Terminal(char temp[]) { int i, flag = 0; for (i = 0; i < MAXN; ++i) { if (flag) break; else if (strcmp(ha[i].data.terminal,temp)== 0) { Output(i); flag = 1; } } if (!flag) printf("对不起,查无此航班!\n"); } void Start(float temp) { int i, flag = 0; i = temp / p; if (ha[i].data.start==temp) { Output(i); flag = 1; } if (!flag) printf( "对不起,查无此航班!\n" ); } void Arrival(float temp) { int i, flag = 0; i = temp / p; if (ha[i].data.arrive==temp) { Output(i); flag = 1; } if (!flag) printf ( "对不起,查无此航班!" ); } void Output(int adr) { printf("航班号\t起点站\t到达站\t班期\t起飞时间\t到达时间\t\n"); printf("%d\t%s\t%s\t%.2f\t",ha[adr].data.num , ha[adr].data.departure ,ha[adr].data.terminal,ha[adr].data.date ); printf("%.2f\t%.2f\t",ha[adr].data.start , ha[adr].data.arrive ); printf("\n"); } void FileOutput() { FILE* fp; fp= fopen("data.txt", "a+"); while (!feof(fp)) { fscanf(fp, "%d,%s,%s,%f,%f,%f", &line.num, line.departure, line.terminal, &line.start,&line.arrive, &line.date); } fclose(fp); } void insert(int adr) { ha[adr].data.num = line.num; ha[adr].data.start = line.start; strcpy(ha[adr].data.terminal, line.terminal); ha[adr].data.arrive = line.arrive; strcpy(ha[adr].data.departure, line.departure); } ``` ![图片说明](https://img-ask.csdn.net/upload/201905/17/1558107664_730495.png)
想在这里面添加一个增加学生信息的功能
#include <stdio.h> #include <string.h> #include <stdlib.h> //宿舍管理软件 //结构体,主题是学生,包括 struct students{ char name[10]; int id; int dorm_id; int building_id; }student[5]={ {"张三",2019,01,0003}, {"李四",2020,02,0002}, {"王五",2001,03,0001}, {"马六",2003,04,0002}, {"赵七",2018,05,0001} }; void sort_id(); void sort_name(); void sort_drom_id(); typedef struct students stuinfo; //函数体模块 //操作功能页面 void display(){ printf("---------------------------------------\n"); printf("----------请输入要选择的值-------------\n"); printf("----------1:存储学生信息---------------\n"); printf("----------2:排序学生信息---------------\n"); printf("----------3:查找学生信息---------------\n"); printf("----------4:显示学生信息---------------\n"); } //排序 //按照姓名 //按照学号 //按照宿舍号 void display_sort(){ printf("1:按照学号"); printf("2:按照姓名"); printf("3:按照宿舍号"); } void sort(){ char str[5]; int i,j,m; stuinfo temp; //进行排序 printf("1:按照学号"); printf("2:按照姓名"); printf("3:按照宿舍号"); scanf("%d",&m); switch(m){ case 1:{ sort_id(); break; } case 2:{ sort_name(); break; } case 3:{ sort_drom_id(); break; } default :printf("请输入1,2,3中的数字"); } printf("\n 排序已经完成,请按任意键继续\n"); } void sort_id(){ int i,j,m; stuinfo temp; //进行排序 for(i=0;i<5-1;i++) for(j=0;j<5-1-i;j++) if(student[j].id>student[j+1].id) { temp=student[j]; student[j]=student[j+1]; student[j+1]=temp; } printf("按照学号排序完成"); } void sort_name(){ int i,j,m; stuinfo temp; //进行排序 for(i=0;i<5-1;i++) for(j=0;j<5-1-i;j++) if(strcmp(student[j].name,student[j+1].name)>0) { temp=student[j]; student[j]=student[j+1]; student[j+1]=temp; } printf("按照姓名排序完成"); } void sort_drom_id(){ int i,j,m; stuinfo temp; //进行排序 for(i=0;i<5-1;i++) for(j=0;j<5-1-i;j++) if(student[j].dorm_id>student[j+1].dorm_id) { temp=student[j]; student[j]=student[j+1]; student[j+1]=temp; } printf("按照宿舍号排序完成"); } //查找学生信息 int found(){ int low,high,mid,m; low=0; high=5-1; printf("1:按照学号查找"); printf("2: 按照姓名查找"); printf("3: 按照宿舍号查找"); scanf("%d",&m); switch(m){ case 1: { sort_id(); int key; int flag=0; printf("请输入要查找的学号"); scanf("%d",&key); while(low<=high) { mid=(low+high)/2; //计算中间元素序号 if(student[mid].id==key) //中间元素与关键字相等 {return mid; flag=1; } else if(student[mid].id>key) //中间元素大于关键字 high=mid-1; else low=mid+1; } if(flag==0){ return 100; } break; } case 2:{ sort_name(); char key[10]; printf("请输入要查找的姓名");int flag=0; gets(key); while(low<=high) { mid=(low+high)/2; //计算中间元素序号 if(strcmp(student[mid].name,key)==0) //中间元素与关键字相等 {return mid; flag=1; } else if(strcmp(student[mid].name,key)>0) //中间元素大于关键字 high=mid-1; else low=mid+1; } if(flag==0){ return 100; } break; } case 3:{ sort_drom_id(); int key; printf("请输入要查找的宿舍号"); scanf("%d",&key);int flag=0; while(low<=high) { mid=(low+high)/2; //计算中间元素序号 if(student[mid].dorm_id==key) //中间元素与关键字相等 {return mid; flag=1; } else if(student[mid].dorm_id>key) //中间元素大于关键字 high=mid-1; else low=mid+1; } if(flag==0){ return 100; } break; } } } int savetofile() { FILE *fp; if((fp=fopen("stu_info.txt","wb+"))==NULL) //打开文件失败 { printf("无法打开文件!\n"); printf("请按任意键继续\n"); getchar(); return 0; } printf("\n 存文件...\n"); fwrite(student,sizeof(stuinfo)*5,1,fp); //写入文件 fclose(fp); printf("5条记录已经存入文件,请按任意键继续。\n"); //savedflag=0;//更新是否已保存的标记 getchar(); return 1; } int loadfromfile(void) { FILE *fp; int i; if((fp=fopen("stu_info.txt","rb"))==NULL) //打开文件失败 { printf("无法打开文件!\n"); printf("请按任意键继续\n"); getchar(); return 0; } printf("\n 读取文件...\n"); int applicantnum=0; //重新计算员工数 while(!feof(fp)) //读取文件内容 { fread(&student[applicantnum],sizeof(stuinfo),1,fp); applicantnum++; } applicantnum--; fclose(fp); printf("共从文件中读入%d 条记录\n",applicantnum); //p=records; printf("读出的文件内容为:\n"); //showtitle(); //先显示原信息 for(i=0;i<=applicantnum;i++) { printf("姓名:%s 学号:%d 宿舍号:%d 楼号:%d\n",student[i].name,student[i].id,student[i].dorm_id,student[i].building_id); } printf("请按任意键继续!\n"); getchar(); return 1; } //排序 //按照姓名 //按照学号 //按照宿舍号 //打印学生信息 //建立数据文件 //数据文件按照关键字(姓名,学号,宿舍号) //按姓名查询 //按学号查询 //按宿舍号查询 void main(){ int m,n; m=1; int w; while(m){ display(); scanf("%d",&n); switch(n){ case 1:{ printf("存储c语言的文件"); int s=savetofile(); if(s=1){ printf("存储完成"); } break; } case 2:{ sort(); break; } case 3:{ w=found(); if(w==100){ printf("没有查找到"); }else{ printf("查找出来的学生为/n"); printf("姓名:%s 学号:%d 宿舍号:%d 楼号:%d",student[w].name,student[w].id,student[w].dorm_id,student[w].building_id); } break; } case 4:{ loadfromfile(); int i; for(i=0;i<5;i++){ // printf("姓名:%s 学号:%d 宿舍号:%d 楼号:%d",student[i].name,student[i].id,student[i].dorm_id,student[i].building_id); } break; } default:printf("请输入正确的值"); } } } 帮忙可有偿
c语言 大量数据在写入文件时会崩溃 急求问题所在和解决办法
想实现的功能是建立一堆文本文件的索引,但是现在已经成功创建了一个索引表,但把索引表存入文件的时候就会进行到一半然后崩溃 需要在目录下创建一个book文件夹储存信息 现在的问题 信息太多时候写入最后save_index 崩溃 释放内存好像不行 代码如下 头文件 ``` #ifndef Searchengine_H #define Searchengine_H #include <stdio.h> #include <windows.h> #include<stdlib.h> struct word_place //保存单词的地址 { int book_id; char book_name[30]; long int location; }; typedef struct word_place place; typedef struct key* key_node; struct key //为每个关键词创造一个节点 { int id; char key[20]; int find_number; place *places; }; key_node key_information[1000000]; struct file_inf //搜索文件的序号 { int number; char name[100]; }file_information[10000]; void find(char * lpPath); int find_word(char* word); void add_key(char* word,int num,long int place) ; int is_letter(char c) ; void index_a_book(int num) ; void kuaipai(int left,int right,key_node a[]) ; void save_index(int x); #endif ``` 遍历文件夹获取文件信息的文件 ``` #include"search_engine.h" void find(char * lpPath) //读取一个文件夹的文件名 { int i=0; char szFind[MAX_PATH],szFile[MAX_PATH]; WIN32_FIND_DATA FindFileData; HANDLE hFind; strcpy(szFind,lpPath); strcat(szFind,"\\*.*"); hFind = FindFirstFile(szFind,&FindFileData); if(INVALID_HANDLE_VALUE == hFind) return; while(TRUE) { if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(FindFileData.cFileName[0]!='.') { strcpy(szFile,lpPath); strcat(szFile,"\\"); strcat(szFile,FindFileData.cFileName); find(szFile); } } else { // printf("%s\n",FindFileData.cFileName); file_information[i].number=i; strcpy(file_information[i].name,FindFileData.cFileName); i++; } if(!FindNextFile(hFind,&FindFileData)) { file_information[i].name[0]='\0'; break; } } } void save_filenum()//储存文件序列 { int i=0; FILE *fp; if((fp=fopen("book index.txt","r+"))==NULL) {printf("open error\n"); exit(0); } char* is_write="0"; fscanf(fp,"%s",&is_write); printf("%c\n",is_write); if (is_write=='0') fclose(fp); else { is_write="1"; fseek(fp,0,0); fprintf(fp,"%s\n",is_write); } for(i=0;file_information[i].name[0];i++) { fprintf(fp,"%d ",file_information[i].number); fprintf(fp,"%s\n",file_information[i].name); } fclose(fp); } ``` 创建和储存索引的函数 ``` #include"search_engine.h" int find_word(char* word) //判断是否为已有的关键词 { int i; for(i=0;key_information[i];i++) { if(strcmp(key_information[i]->key,word)==0) break; } return i; }//少一个储存查找的算法 void add_key(char* word,int num,long int place) //把关键词添加到索引中 { int i=find_word(word); if(!key_information[i]) { key_information[i]=(key_node)malloc(sizeof(struct key)); strcpy(key_information[i]->key,word); key_information[i]->find_number=1; key_information[i]->places=(struct word_place*)malloc(100*sizeof(struct word_place)) ; } else key_information[i]->find_number++; int temp=key_information[i]->find_number-1; if(temp%98==0) key_information[i]->places=(struct word_place*)realloc(key_information[i]->places,(temp+100)*sizeof(struct word_place)); strcpy(key_information[i]->places[temp].book_name,file_information[num].name); key_information[i]->places[temp].book_id=num; key_information[i]->places[temp].location=place; } int is_letter(char c) //判断一个字符是否是特殊字符 { if(c >='0' && c<='9') return 1; else if(c >='a' && c<='z' || c >='A' && c<='Z') return 2; else return 0; } void index_a_book(int num) //为一本书中的单词建立索引 { FILE *fp; char* name=file_information[num].name; char way[100]="book\\"; strcat(way,name); printf("%s\n",way); if((fp=fopen(way,"r+"))==NULL) {printf("open error\n"); exit(0); } char* read; read=(char*)malloc(sizeof(char)*100); long int place=0; fseek(fp,0L,SEEK_SET); while(!feof(fp)) { fscanf(fp,"%s",read); if(is_letter(read[strlen(read)-1])==0) read[strlen(read)-1]=0; if(is_letter(read[0])==2)//首为必须为字母 { printf("%s\n",read); add_key(read,num,place); place++; } } fclose(fp); } void kuaipai(int left,int right,key_node a[]) //对列表快速排序 { int i,j; char* middle; key_node temp; i=left; j=right; middle=a[(i+j)/2]->key; do{ while(strcmp(a[i]->key,middle)<0&&i<right) i++; while(strcmp(a[j]->key,middle)>0&&j>left) j--; if(i<=j) { temp=a[i],a[i]=a[j],a[j]=temp; j--; i++; } }while(i<=j); if(left<j) kuaipai(left,j,a); if(right>i) kuaipai(i,right,a); } void save_index(int x)//储存索引 { FILE *fp; if((fp=fopen("word index.txt","w+"))==NULL) {printf("open error\n"); exit(0); } printf("open success\n"); printf("%d",x); int i,j; fprintf(fp,"%d\n",x); i=0; printf("%d %s %d \n",i,key_information[i]->key,key_information[i]->find_number); printf("%c %d",key_information[i]->key[0],is_letter(key_information[i]->key[0])); fprintf(fp,"%d %s %d ",i,key_information[i]->key,key_information[i]->find_number); /* for(i=0;i<100;i++) { fprintf(fp,"%d %s %d ",i,key_information[i]->key,key_information[i]->find_number); for(j=0;j<key_information[i]->find_number;j++) { fprintf(fp,"%d %d ",key_information[i]->places[j].book_id,key_information[i]->places[j].location); } fprintf(fp,"ok\n"); }*/ fclose(fp); } ``` 主函数 ``` #include"search_engine.h" //void add index() int main() { char filepath[MAX_PATH]="book"; //可自己输入文件夹绝对路径 find(filepath); int i=0; /* for(i=0;file_information[i].name[0];i++) { printf("%d %s\n",file_information[i].number,file_information[i].name); }*/ save_filenum(); for(i=0;file_information[i].name[0];i++) { index_a_book(i); } /*for(i=0;key_information[i];i++) { printf("%s\n",key_information[i]->key); } printf("%s\n",key_information[1]->places[0].book_name);*/ int word_num; for(i=0;key_information[i];i++) ; word_num=i-1; kuaipai(0,word_num,key_information); printf("ok\n"); save_index(word_num); system("PAUSE"); for(i=0;key_information[i];i++) { free(key_information[i]); } return 0; } ``` 很急,求大佬解答
如何将以下C代码转译成MIPS 32
``` int load(int arr[], int max_len) { int input, i = 0; while (i <= max_len) { scanf("%d", &input); if (input < 0 ) { break; } arr[i] = input; i++; } return i; } void sort(int arr[], int len) { int i = 1; while (i < len) { int j = i; while (j > 0 && arr[j-1]> arr[j]) { int temp = arr[j-1]; arr[j-1] = arr[j]; arr[j] = temp; j--; } i++; } } int bsearch(int arr[], int low, int high, int key) { if (high < low) { return -1; } int mid = (low + high) / 2; if (arr[mid] > key) { return bsearch(arr, low, mid-1, key); } else if (arr[mid] < key) { return bsearch(arr, mid+1, high, key); } else { return mid; } } void find(int arr[], int len) { int key; while (1) { scanf("%d", &key); if (key < 0) { break; } int position = bsearch(arr, 0, len-1, key); if (position == -1) { printf("%s", "Not found\n"); } else { printf("Found at index %d\n", position); } } } int main() { int arr[10], max_len = 10; int len = load(arr, max_len); sort(arr, len); find(arr, len); return 0; } ```
将两个递增的双向链表合并问题
将两个排好序的双向链表合并成一个,不允许有重复数据,链表1为1 2 3 4 6 链表2为5 6 8 9 10,合并后为1 2 3 4 6 8 9 10缺少了5,麻烦各位看一下是为什么啊? ``` // shiyan.cpp : 定义控制台应用程序的入口点。 // /* C program to insetail nodes in doubly linked list such that list remains in ascending order on printing from left to right */ #include "stdafx.h" #include <iostream> using namespace std; #include<stdio.h> #include<stdlib.h> #include<fstream> // A linked list node struct Node { int data; struct Node *prior; struct Node *next; }; // Function to insetail new node void nodeInsetail(struct Node **head, struct Node **tail,int key) { struct Node *p = new Node; p->data = key; p->next = NULL; // If first node to be insetailed in doubly linked list if ((*head) == NULL) { (*head) = p; (*tail) = p; (*head)->prior = NULL; return; } // If node to be insetailed has value less than first node if ((p->data) < ((*head)->data)) { p->prior= NULL; (*head)->prior = p; p->next = (*head); (*head) = p; return; } // If node to be insetailed has value more than last node if ((p->data) > ((*tail)->data)) { p->prior = (*tail); (*tail)->next = p; (*tail) = p; return; } // Find the node before which we need to insert p. struct Node *temp = new Node; temp = (*head)->next; while ((temp->data) < (p->data)) temp = temp->next; // Insert new node before temp (temp->prior)->next = p; p->prior= temp->prior; temp->prior = p; p->next = temp; } // Function to print nodes in from left to right void printList(struct Node *temp) { while (temp != NULL) { printf("%d ", temp->data); temp = temp->next; } } // Driver program to test above functions struct Node *head1=NULL; struct Node *tail1=NULL; struct Node *head2=NULL; struct Node *tail2=NULL; int _tmain(int argc, _TCHAR* argv[]) { int num[10]; int datalen=0; ifstream file("linklist.txt"); while( ! file.eof() ) file>>num[datalen++]; file.close(); for(int i=0;i<5;i++) { nodeInsetail(&head1, &tail1,num[i]); } printf("Doubly linked list1 is:"); printList(head1); printf("\n"); for(int j=5;j<10;j++) { nodeInsetail(&head2, &tail2,num[j]); } printf("Doubly linked list2 is:"); printList(head2); printf("\n"); Node *phead =head1;//最终返回的头数据节点 Node *p=head1->next;//p循环的是链表1 Node *q=head2;//q循环的是链表2 if(p->data > q->data) { phead = head2; p = head2->next; q = head1; } Node* s=phead;//记录新链表的最后一个节点,方便下一次接上新节点 while(p!=NULL && q!=NULL) { if(p->data < q->data) { s->next = p; p->prior=s; p = p->next; s = s->next; } else if(p->data = q->data) { s->next= p; p->prior=s; p=p->next; Node *x=q->next;//备用元素指向 free(q); q=x; } else if(p->data > q->data) { s->next = q; q->prior=s; q = q->next; s = s->next; } } if(p == NULL)//链表1先遍历完,说明另一链表还有数据得接过来 { s->next = q; q->prior=s; } if(q == NULL)//链表2先遍历完,因为此时主链表的结构已经发生变化,所以仍需拼接过来 { s->next = p; p->prior=s; } while(phead) { printf("%d ",phead->data); phead=phead->next; } return 0; } ``` ![图片说明](https://img-ask.csdn.net/upload/201912/11/1576048566_174264.png)
C文件怎么改写成java文件?
最近遇到一个棘手的问题,老板给了几个.unl格式的文件,文本打开全是乱码,说是要求用java读取解析,给了个C写的解析过程,可我不懂C语言。虽然有格式文档但是怎么解都解不出正确的内容来,哪位大神有能将C语言翻译成java呢? 或者说那位大神能使用java按照格式解析出二进制的内容,可以联系我哦,可以付钱买源码。 ``` #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <time.h> #include <string.h> #include "billBinToAsc.h" #define BILL_VERSION "2017/07/03" #define BILL_SIZE 337 #define BILL_ASC_SIZE 2048 #define MAX_BILL_COUNT 10000 void getNowTime(char * strNow,size_t size) { time_t Now; struct tm * tm_time; Now = time(NULL); tm_time = localtime(&Now); strftime(strNow,size,"%Y-%m-%d %H:%M:%S",tm_time); } void printBill(const tag_bill * billdata,char * strBuf) { char temp[BILL_ASC_SIZE]; time_t t_time; struct tm * tm_time; *strBuf = 0; //话单ID sprintf((char *)&temp,"%d-%d|",billdata->call_id1,billdata->call_id2); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->call_num); strcat(strBuf,temp); //主被叫 sprintf((char *)&temp,"%s",billdata->caller_no); int len = strlen(temp); for (int j=0;j<len;j++) { //if(temp[j] == '\r' || temp[j] == '\n') if(temp[j] == '\r'||temp[j] == '\n') { temp[j] = '\0'; } } len = strlen(temp); //temp[len] ='|'; char temp2[2]="|"; strcat(temp,temp2); strcat(strBuf,temp); sprintf((char *)&temp,"%s|",billdata->callee_no); strcat(strBuf,temp); //时间 t_time = billdata->wait_begin; tm_time = localtime(&t_time); strftime(temp,BILL_ASC_SIZE,"%Y-%m-%d %H:%M:%S|",tm_time); strcat(strBuf,temp); t_time = billdata->wait_end; tm_time = localtime(&t_time); strftime(temp,BILL_ASC_SIZE,"%Y-%m-%d %H:%M:%S|",tm_time); strcat(strBuf,temp); t_time = billdata->ack_begin; tm_time = localtime(&t_time); strftime(temp,BILL_ASC_SIZE,"%Y-%m-%d %H:%M:%S|",tm_time); strcat(strBuf,temp); t_time = billdata->ack_end; tm_time = localtime(&t_time); strftime(temp,BILL_ASC_SIZE,"%Y-%m-%d %H:%M:%S|",tm_time); strcat(strBuf,temp); t_time = billdata->call_begin; tm_time = localtime(&t_time); strftime(temp,BILL_ASC_SIZE,"%Y-%m-%d %H:%M:%S|",tm_time); strcat(strBuf,temp); t_time = billdata->call_end; tm_time = localtime(&t_time); strftime(temp,BILL_ASC_SIZE,"%Y-%m-%d %H:%M:%S|",tm_time); strcat(strBuf,temp); //模块信息 sprintf((char *)&temp,"%d|",billdata->serviceno); //operation_type_id strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->trkno); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->trunkgroup_no); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->module_no); strcat(strBuf,temp); //设备信息 sprintf((char *)&temp,"%d|",billdata->device_type); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->device_no); strcat(strBuf,temp); sprintf((char *)&temp,"%s|",billdata->devicein); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->call_type_id); strcat(strBuf,temp); //原因信息 sprintf((char *)&temp,"%d|",billdata->waitcause); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->releasecause); strcat(strBuf,temp); //呼叫中心信息 sprintf((char *)&temp,"%d|",billdata->subccno); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->vdn); strcat(strBuf,temp); //杂项 sprintf((char *)&temp,"%d|",billdata->mediatype); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->uvid); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->orgccno); strcat(strBuf,temp); sprintf((char *)&temp,"%u-%u|",billdata->org_call_id1,billdata->org_call_id2); strcat(strBuf,temp); //原始呼叫信息 sprintf((char *)&temp,"%s|",billdata->orgcalleeno); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->orgserviceno); strcat(strBuf,temp); //级别信息 sprintf((char *)&temp,"%d|",billdata->serccno); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->serservice); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->userlevel); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->usertype); strcat(strBuf,temp); //杂项 sprintf((char *)&temp,"%d|",billdata->callincause); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->enterreason); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->leavereason); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo1); strcat(strBuf,temp); //上个设备信息 sprintf((char *)&temp,"%d|",billdata->preserviceno); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->predevicetype); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->predeviceno); strcat(strBuf,temp); sprintf((char *)&temp,"%s|",billdata->predevicein); strcat(strBuf,temp); //技能 sprintf((char *)&temp,"%d|",billdata->mediainfotype); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->skillid); strcat(strBuf,temp); //int billinfo2; //int billinfo3; //int billinfo4; //char str1[31]; //char str2[25]; //int billinfo5; //int billinfo6; //后为添加的部分字段: sprintf((char *)&temp,"%d|",billdata->locationid); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo2); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo3); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo4); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo5); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->str1); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->str2); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo6); strcat(strBuf,temp); sprintf((char *)&temp,"%d|",billdata->billinfo7); strcat(strBuf,temp); // sprintf((char *)&temp,"%d|",billdata->billinfo8); //strcat(strBuf,temp); // sprintf((char *)&temp,"%d|",billdata->billinfo9); //strcat(strBuf,temp); // sprintf((char *)&temp,"%d|",billdata->billinfo10); //strcat(strBuf,temp); //转换结束 strcat(strBuf,"\n"); } int main(int argc,char * argv[]) { const char * strSourceFileName; const char * strTargetFileName; const char * strLogFileName = "billConvt.log"; char strBillAsc[BILL_ASC_SIZE]; char strNowDate[1000]; FILE * fd_s,* fd_t,* fd_log; tag_bill tagBillData; int iReadCount; getNowTime(strNowDate,sizeof(strNowDate)); //command handle if(argc != 3){ printf("%d command error: [usuage] command sourcefilename targetfilename\n",argc); return -1; } //strSourceFileName = argv[1]; //strTargetFileName = argv[2]; strSourceFileName = "H:\\UNL\\Prm20190716_0101_000361.unl";//argv[1]; strTargetFileName = "H:\\parseData\\Prm20190716_0101_000361.dat";// argv[2]; //fprintf("%s=",argv[0]); //open Source file fd_log = fopen(strLogFileName,"a"); if(fd_s == NULL){ fprintf(fd_log,"[%s]Cannot Open SourceFileName:%s\n",strNowDate,strSourceFileName); return -1; } //key parameter check /* if(sizeof(tag_bill) < BILL_SIZE){ fprintf(fd_log,"[%s][error] tag_bill size error![%d][%d]\n",strNowDate,sizeof(tag_bill),BILL_SIZE); return -1; } */ //open Source file fd_s = fopen(strSourceFileName,"r"); if(fd_s == NULL){ fprintf(fd_log,"[%s]Cannot Open SourceFileName:%s\n",strNowDate,strSourceFileName); return -1; } //open Target file fd_t = fopen(strTargetFileName,"w"); if(fd_s == NULL){ fprintf(fd_log,"[%s]Cannot Open TargetFileName:%s\n",strNowDate,strTargetFileName); return -1; } //读数据 int i = 0; for(i=0;i<=MAX_BILL_COUNT && fread((tag_bill*)&tagBillData,BILL_SIZE,1,fd_s) == 1;i++) { printBill(&tagBillData,(char *)&strBillAsc); fprintf(fd_t,"%d|",i); fputs(strBillAsc,fd_t); } //写日志 fprintf(fd_log,"[%s] Convert SourceFile:%s into TargetFile:%s OK! record:%d\n",\ strNowDate,strSourceFileName,strTargetFileName,i); //关闭文件 if(fd_s != NULL) fclose(fd_s); if(fd_t != NULL) fclose(fd_t); if(fd_log != NULL) fclose(fd_log); return 0; } (下面是定义的集合文件) #pragma pack(push,1) typedef struct { int head; int call_id1; int call_id2; int call_num; char caller_no[26]; char callee_no[26]; int wait_begin; int wait_end; int ack_begin; int ack_end; int call_begin; int call_end; int serviceno; int trkno;// int module_no;//------14 int device_type; int device_no; char devicein[26]; int call_type_id; int waitcause; int releasecause; short subccno; short vdn; short mediatype; int uvid; short trunkgroup_no; char orgcalleeno[26]; short orgccno; int org_call_id1; int org_call_id2;//14 int orgserviceno; short serccno; short serservice; unsigned char userlevel;//一字节整形 unsigned char usertype;//一字节整形 short callincause; unsigned char enterreason;//一字节整形 unsigned char leavereason;//一字节整形 int billinfo1; int preserviceno; int predevicetype; int predeviceno; char predevicein[26]; int mediainfotype; short skillid; short locationid; int billinfo2; int billinfo3; int billinfo4; int billinfo5; char str1[31]; char str2[25]; short billinfo6; unsigned char billinfo7; //short billinfo8; //unsigned char billinfo9; //short billinfo10; }tag_bill; #pragma pack(pop) ```
提示内存不足+++++++++++
我测试的时候上传了很多图片进行测试,但是出现内存不足的情况, 我猜测应该是数据流的问题,请教大神们可以帮我看一下么? ``` using Google.Cloud.Vision.V1; using Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction; using Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction.Models; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Runtime.Serialization.Json; using System.Text; using System.Threading.Tasks; using System.Web; namespace MealAnalysis { public class MealAnalysis { //------------------------------ // 固定値 //------------------------------ // 文字列解析用(QRコードを採用したため、今回は利用しない) const string cstrsubscriptionkey = "8f59b9dcca164bada9935a0ecb71e843"; // 富士フイルム様用に作成したAPI const string cstrUri = "https://japaneast.api.cognitive.microsoft.com/vision/v1.0/recognizeText?"; // 文字解析呼び出しUri const string cstrHeaderKey = "Ocp-Apim-Subscription-Key"; // API呼び出し時必ず指定するHeaderKey const string cstrQuantityUri = "https://japaneast.api.cognitive.microsoft.com/vision/v1.0/recognizeText?"; // 文字解析呼び出しUri // CustomVision const string cstrEndPoint = "https://japaneast.api.cognitive.microsoft.com/"; // Azure Custom Vision Prediction Key const string cstrMealPredictionId = "XXXXXXXXXXX"; const string cstrAmountOfStapleFoodPredictionId = "XXXXXXXXXXX"; const string cstrAmountOfMainDishPredictionId = "XXXXXXXXXXX"; const string cstrAmountOfSideDishPredictionId = "XXXXXXXXXXX"; const string cstrAmountOfSteapleMainPredictionId = "XXXXXXXXXXX"; // Azure Custom Vision Project Key //const string cstrMealProjectId = "XXXXX"; const string cstrMealProjectId = "XXXXXd"; const string cstrAmountOfStapleFoodProjectId = "XXXXXdd"; const string cstrAmountOfMainDishProjectId = ""; const string cstrAmountOfSideDishProjectId = ""; const string cstrAmountOfSteapleMainProjectId = ""; // Azure Custom Vision PublishedName const string cstrMeal = "Iteration5"; const string cstrAmountOfStapleFood = "Iteration5"; const string cstrAmountOfMainDish = "Iteration4"; const string cstrAmountOfSideDish = "Iteration3"; const string cstrAmountOfSteapleMain = "Iteration2"; //============================================================ // 【説明】 // 画像を読み込んで、オブジェクトの位置を特定し、返却する関数 // // 【引数】 // JSON // 画像ファイルパス // 【戻り値】 // JSON // result:true/false // true:正常 // false:異常 // errorMessage:string // エラーの内容 // code:#から始まる取得した結果 //============================================================ public static string GetTableWare(string strImageJsonData) { //------------------------------ // 変数宣言 //------------------------------ string strResultData = ""; string strFilePath = ""; //------------------------------ // 通常処理 //------------------------------ try { // パラメータで渡されたJSONデータからデータの取得 var objImageJsonData = JObject.Parse(strImageJsonData); // 判定処理 strFilePath = objImageJsonData.GetValue("filename").ToString(); // 秘密鍵のファイルパス(必ず登録されている必要がある。) Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", @"C:\key\FCompany2babd1355150.json", EnvironmentVariableTarget.Process); // イメージファイルをメモリに読み込む var image = Image.FromFile(strFilePath); // Google Vision Ai 呼び出し ImageAnnotatorClient client = ImageAnnotatorClient.Create(); IReadOnlyList<LocalizedObjectAnnotation> DetectLocalizedObjects = client.DetectLocalizedObjects(image); // 戻り値の返却 strResultData = DetectLocalizedObjects.ToString(); // JSON形式にして、取得できたオブジェクトの数をカウントする var jsonData = JArray.Parse(strResultData); int MealCount = jsonData.Count; // 戻り値のデータ作成 strResultData = "{\"Result\":\"true\",\"NumberOfObject\":\""+ MealCount.ToString() +"\",\"DataOfObject\":" + strResultData + ",\"ErrorMessage\":\"\"}"; return strResultData; } //------------------------------ // エラー処理 //------------------------------ catch (Exception ex) { strResultData = "{\"Result\":\"false\",\"NumberOfObject\":\"0\",\"DataOfObject\":{},\"ErrorMessage\":\"" + ex.Message + "\"}"; } //------------------------------ // 後処理 //------------------------------ finally { } // 戻り値を返却 return strResultData; } //============================================================ // 【説明】 // オブジェクトを解析して、解析結果を返却する関数 // // 【引数】 // JSON // (正面データ)画像ファイルパス // (正面データ)GetTabelWareで取得したDataOfObject Jsonの値(解析結果) // (斜めデータ)画像ファイルパス // (斜めデータ)GetTabelWareで取得したDataOfObject Jsonの値(解析結果) // 【戻り値】 // JSON // result:true/false // true:正常 // false:異常 // Staplefood :double(割合の値) // MainDish :double(割合の値) // SideDish :double(割合の値) // errorMessage:string(エラーの内容) //============================================================ public static string QuantityAnalysis(string strImageJsonData) { //------------------------------ // 変数宣言 //------------------------------ string strResultData = ""; string strFilePathA = ""; string strFilePathB = ""; string strJsonfileDataA = ""; string strJsonfileDataB = ""; //------------------------------ // 通常処理 //------------------------------ try { // パラメータで渡されたJSONデータからデータの取得 var objImageJsonData = JArray.Parse(strImageJsonData); if (objImageJsonData.Count < 2){ // 2以下は、データがそろっていないため、エラー strResultData = "{\"Result\":\"false\",\"Staplefood\":\"\",\"MainDish\":\"\",\"SideDish\":\"\",\"ErrorMessage\":\"該当データが見つかりませんでした。\"}"; } else { // 判定処理 JToken objTokenA = objImageJsonData[0]; var objImageJsonDataA = objTokenA as JObject; strFilePathA = objImageJsonDataA.GetValue("filename").ToString(); strJsonfileDataA = objImageJsonDataA.GetValue("DataOfObject").ToString(); JToken objTokenB = objImageJsonData[1]; var objImageJsonDataB = objTokenB as JObject; strFilePathB = objImageJsonDataB.GetValue("filename").ToString(); strJsonfileDataB = objImageJsonDataB.GetValue("DataOfObject").ToString(); // ABの画像イメージを分解し、ローカルに切り抜いた画像をStreamで読み取り、解析を実行 // Aの画像を読み込ませ、解析結果を取得 QuantityAnalysisData objDataA = ImageAnalysis(strFilePathA, strJsonfileDataA); //// ②の画像を読み込ませ、解析結果を取得 QuantityAnalysisData objDataB = ImageAnalysis(strFilePathB, strJsonfileDataB); // 結果をマージする // 足して2で割る string Staplefood = ""; string MainDish = ""; string SideDish = ""; double returnA = 0; double returnB = 0; if( double.TryParse( objDataA.Staplefood,out returnA) == true){ if( double.TryParse( objDataB.Staplefood,out returnB) == true){ if( returnA < returnB ){ Staplefood = returnB.ToString(); } else{ Staplefood = returnA.ToString(); } } else{ Staplefood = returnA.ToString(); } } else{ if( double.TryParse( objDataB.Staplefood,out returnB) == true){ Staplefood = returnB.ToString(); } else{ Staplefood = "-"; } } if( double.TryParse( objDataA.MainDish,out returnA) == true){ if( double.TryParse( objDataB.MainDish,out returnB) == true){ if( returnA < returnB ){ MainDish = returnB.ToString(); } else{ MainDish = returnA.ToString(); } } else{ MainDish = returnA.ToString(); } } else{ if( double.TryParse( objDataB.MainDish,out returnB) == true){ MainDish = returnB.ToString(); } else{ MainDish = "-"; } } if( double.TryParse( objDataA.SideDish,out returnA) == true){ if( double.TryParse( objDataB.SideDish,out returnB) == true){ if( returnA < returnB ){ SideDish = returnB.ToString(); } else{ SideDish = returnA.ToString(); } } else{ SideDish = returnA.ToString(); } } else{ if( double.TryParse( objDataB.SideDish,out returnB) == true){ SideDish = returnB.ToString(); } else{ SideDish = "-"; } } // 結果を返却 strResultData = "{\"Result\":\"true\",\"Staplefood\":\"" + Staplefood + "\",\"MainDish\":\"" + MainDish + "\",\"SideDish\":\"" + SideDish + "\",\"ErrorMessage\":\"\"}"; } } //------------------------------ // エラー処理 //------------------------------ catch (Exception ex) { strResultData = "{\"Result\":\"false\",\"Staplefood\":\"\",\"MainDish\":\"\",\"SideDish\":\"\",\"ErrorMessage\":\"" + ex.Message + "\"}"; } //------------------------------ // 後処理 //------------------------------ finally { } // 戻り値を返却 return strResultData; } //============================================================ // 【説明】 // 文字列を解析して、解析結果を返却する関数 // // 【引数】 // JSON // 読み込む画像のPath // 【戻り値】 // JSON // result:true/false // true:正常 // false:異常 // errorCode:string // 01:文字列解析不能(#の文字列が取得できなかった) // 02:上記以外 // errorMessage:string // エラーの内容 // code:#から始まる取得した結果 //============================================================ public string CodeAuth(string strfilePath){ //------------------------------ // 変数宣言 //------------------------------ string strResultData =""; //------------------------------ // 通常処理 //------------------------------ try { // 文字解析用API関数を実行 var task = CodeAuthAsync(strfilePath); // APIからの実行結果を返却 task.Wait(); // 7.取得した結果contextをJson文字列に変換 var serializer = new DataContractJsonSerializer(typeof(PersonCodeAuth)); using (MemoryStream returnData = new MemoryStream(Encoding.UTF8.GetBytes(task.Result))) { returnData.Position = 0; PersonCodeAuth deserialized = (PersonCodeAuth)serializer.ReadObject(returnData); // 8.Json文字列のうちrecognitionResult.lines.text[]を取得 string recognitionStatus = deserialized.Status; string[] recognitionResult = deserialized.recognitionResult; string strNumber = ""; // 9.⑧で取得した文字列をトリム(間もすべて) char[] checkChar = new char[' ']; foreach (string data in recognitionResult) { string trimRecognitionResult = data.Trim(checkChar); // 10.先頭が[#]の文字列を取得 if (trimRecognitionResult.StartsWith("#") == true) { // ①⑩が取得できたら、以降は取得しない strNumber = trimRecognitionResult.Replace("#", ""); break; } else { // ②⑩が取得できるまで処理を繰り返す } } if (strNumber == "") { // 取得できなかった strResultData = "{\"Result\":\"false\" ,\"Number\":\"\",\"ErrorMessage\":\"#を含む値が取得できませんでした。\"}"; } else { // 取得できた // 11.#付きの番号を返却(取得できなかった場合は、エラーで戻す) strResultData = "{\"Result\":\"" + recognitionStatus + "\" ,\"Number\":\"" + strNumber + "\",\"ErrorMessage\":\"\"}"; } } strResultData = "{\"Result\":\"true\" ,\"Number\":\"#01\",\"ErrorMessage\":\"\"}"; } //------------------------------ // エラー処理 //------------------------------ catch (Exception ex) { strResultData = "{\"Result\":\"false\" ,\"Number\":\"\",\"ErrorMessage\":\"" + ex.Message + "\"}"; } //------------------------------ // 後処理 //------------------------------ finally { } // 戻り値を返却 return strResultData; } //============================================================ // 【説明】 // Computer Vision AI呼び出し、解析結果を返却する関数 // // 【引数】 // 読み込む画像のPath // 【戻り値】 // JSON // result:true/false // true:正常 // false:異常 // errorCode:string // 01:文字列解析不能(#の文字列が取得できなかった) // 02:上記以外 // errorMessage:string // エラーの内容 // code:#から始まる取得した結果 //============================================================ public async Task<string> CodeAuthAsync(string strFilePath) { //------------------------------ // 変数宣言 //------------------------------ var client = new HttpClient(); // API呼び出し用オブジェクト var queryString = HttpUtility.ParseQueryString(string.Empty); // URLパラメータ // 初期化 var strResult = ""; // Request headers client.DefaultRequestHeaders.Add(cstrHeaderKey, cstrsubscriptionkey); // Request parameters queryString["handwriting"] = "true"; var Uri = cstrUri + queryString; HttpResponseMessage response; //ファイルを開く System.IO.FileStream fs = new System.IO.FileStream(strFilePath,System.IO.FileMode.Open,System.IO.FileAccess.Read); //ファイルを読み込むバイト型配列を作成する byte[] byteData = new byte[fs.Length]; //ファイルの内容をすべて読み込む fs.Read(byteData, 0, byteData.Length); //閉じる fs.Close(); using (var content = new ByteArrayContent(byteData)) { content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); response = await client.PostAsync(Uri, content); if (response.Headers.Contains("Operation-Location") == true) { var contentString = ""; string Operation = response.Headers.GetValues("Operation-Location").FirstOrDefault(); var clientdata = new HttpClient(); clientdata.DefaultRequestHeaders.Add(cstrHeaderKey, cstrsubscriptionkey); bool getresult = true; while (getresult) { HttpResponseMessage responsedata = await clientdata.GetAsync(Operation); contentString = await responsedata.Content.ReadAsStringAsync(); if (contentString.ToLower().Contains("succeeded") == true) { // 正常 getresult = false; } else if (contentString.ToLower().Contains("running") == true) { // 待機 } else { // エラー // 該当メッセージを出力して終了 getresult = false; } // 無限ループにならないように気を付ける } strResult = contentString; } } return strResult; } //============================================================ // 【説明】 // 画像を解析する関数 // // 【引数】 // 読み込む画像のPath // Googleから取得したJSONデータ // 【戻り値】 // JSON // // //============================================================ private static QuantityAnalysisData ImageAnalysis(string strFilePath,string strJsonData) { //======================================== // 変数 //======================================== QuantityAnalysisData objResult = new QuantityAnalysisData(); // ファイル単位で使用する、オブジェクトの初期化 List<QuantityData> listData = new List<QuantityData>(); // 取得したオブジェクトの各割合を保存 //======================================== // 処理 //======================================== try { //---------------------------------------- // ファイルを開き、Gogole Vision AIから取得したJSONデータをもとに、画像を取得する。 //---------------------------------------- // ファイルを開く var image = Google.Cloud.Vision.V1.Image.FromFile(strFilePath); ImageAnnotatorClient client = ImageAnnotatorClient.Create(); IReadOnlyList<LocalizedObjectAnnotation> DetectLocalizedObjects = client.DetectLocalizedObjects(image); int imagew; int imageh; //image size 読み込む using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read)) { imagew = System.Drawing.Image.FromStream(fs).Width; //幅さ imageh = System.Drawing.Image.FromStream(fs).Height; //高さ } foreach (LocalizedObjectAnnotation text in DetectLocalizedObjects) { //JSONを取得 string jsonstr = text.ToString(); JObject normalizedVertices = JObject.Parse(jsonstr); var Zahyo = normalizedVertices["boundingPoly"]["normalizedVertices"]; //vertex 座標 var x0 = Convert.ToDouble(Zahyo[0]["x"]) * imagew; var y0 = Convert.ToDouble(Zahyo[0]["y"]) * imageh; var xW = (Convert.ToDouble(Zahyo[1]["x"]) - Convert.ToDouble(Zahyo[0]["x"])) * imagew; var xH = (Convert.ToDouble(Zahyo[3]["y"]) - Convert.ToDouble(Zahyo[0]["y"])) * imageh; float Fx0 = (float)Math.Round((double)x0, 15)-10; float Fy0 = (float)Math.Round((double)y0, 15)-10; float FxW = (float)Math.Round((double)xW, 15)+50; float FxH = (float)Math.Round((double)xH, 15)+50; //画像を分解します string baseFilePath = strFilePath; System.Drawing.Bitmap bmpBase = new System.Drawing.Bitmap(baseFilePath); // 画像を切り抜く System.Drawing.RectangleF rect = new System.Drawing.RectangleF(Fx0, Fy0, FxW, FxH); System.Drawing.Bitmap bmpNew = bmpBase.Clone(rect, bmpBase.PixelFormat); bmpNew.Save("C:\\temp\\test.Jpeg", ImageFormat.Jpeg); bmpNew.Dispose(); //Stream streamS = new MemoryStream(); //bmpNew.Save(streamS, ImageFormat.Jpeg); using (FileStream streamS = new FileStream("C:\\temp\\test.Jpeg", FileMode.Open, FileAccess.Read)) { //---------------------------------------- // 変数宣言 //---------------------------------------- string strType = ""; // オブジェクトの種類(AmountOfStapleFood / AmountOfMainDish / AmountOfSiteDish / AmountOfSteaple&Main) double objDouble = 0; // 選択されたオブジェクトの割合 double ProbalilitySum = 0; // 解析結果の合計値(オブジェクトの種類) double objAmountDouble = 0; // 解析結果の量の判定 //---------------------------------------- // ①オブジェクトの判定 //---------------------------------------- // 分割したオブジェクトを渡して、何のオブジェクトか判断する(MealVision) var listMailVisions = QuantityAnalysisyAsync(cstrMealPredictionId, cstrMealProjectId, cstrMeal, streamS); foreach (PredictionModel objItem in listMailVisions) { // 0.001以下は無視する if (0.001 < objItem.Probability) { // 合計を足す ProbalilitySum += objItem.Probability; // 戻り値によって、分析データをもとに、次の呼び出し関数を変更する // 割合が一番大きいものを採用(でも判定結果は大きいもの順のようなので、チェックする必要はないかも。) if (objDouble < objItem.Probability) { strType = objItem.TagName; objDouble = objItem.Probability; } } } QuantityData objData = new QuantityData(); //---------------------------------------- // ②分量の判定 //---------------------------------------- // 解析した結果が、80%以上150未満の場合は分量を測定する処理を実行(それ以外はその他のオブジェクトとして処理を行わない) // ハンさんのサンプルから実際データを取得し、この割合を考える if (0.8 <= ProbalilitySum && ProbalilitySum <= 1.5) { string strPredictionId = ""; string strProjectId = ""; string strPublishedName = ""; // 分割したオブジェクトを渡して、分量を判断する(AmountOfStapleFood / AmountOfMainDish / AmountOfSideDish / AmountOfSteaple&Main) switch (strType) { case "StapleBowl": strPredictionId = cstrAmountOfStapleFoodPredictionId; strProjectId = cstrAmountOfStapleFoodProjectId; strPublishedName = cstrAmountOfStapleFood; break; case "MainDishPlate": strPredictionId = cstrAmountOfMainDishPredictionId; strProjectId = cstrAmountOfMainDishProjectId; strPublishedName = cstrAmountOfMainDish; break; case "SubFoodPlate": strPredictionId = cstrAmountOfSideDishPredictionId; strProjectId = cstrAmountOfSideDishProjectId; strPublishedName = cstrAmountOfSideDish; break; case "Bowl": strPredictionId = cstrAmountOfSteapleMainPredictionId; strProjectId = cstrAmountOfSteapleMainProjectId; strPublishedName = cstrAmountOfSteapleMain; break; default: break; } if(string.IsNullOrEmpty(strPredictionId) == false) { objData.Type = strType; var listItem = QuantityAnalysisyAsync(strPredictionId, strProjectId, strPublishedName, new FileStream("C:\\temp\\test.Jpeg", FileMode.Open, FileAccess.Read)); // 初期化 double ProbalilityItemSum = 0; foreach (PredictionModel objItem in listItem) { // 0.001以下は無視する if (0.01 < objItem.Probability) { // 合計を足す ProbalilityItemSum += objItem.Probability; // 割合が一番大きいものを採用 if (objAmountDouble < objItem.Probability) { switch (objItem.TagName) { case "0段階": objAmountDouble += 0 * objItem.Probability; break; case "1段階": case "2段階": objAmountDouble += 25 * objItem.Probability; break; case "3段階": objAmountDouble += 50 * objItem.Probability; break; case "4段階": objAmountDouble += 75 * objItem.Probability; break; case "5段階": objAmountDouble += 100 * objItem.Probability; break; } } } } // 食事の種類と、食事量を配列に格納する。 objData.Quantity = objAmountDouble.ToString(); listData.Add(objData); } } else { // 主食、主菜、副菜以外のオブジェクトと見直し、判断材料としない。 } } } //-------------------------------------------------------------------------------- // ③すべての分類が完了したら、主食、副食(主菜)、副食(副菜)単位で割合を計算する //-------------------------------------------------------------------------------- // 初期化 objResult.Staplefood = "-"; objResult.MainDish = "-"; objResult.SideDish = "-"; foreach (QuantityData objData in listData) { double dblResult = 0; if (objData.Quantity == "-") { //何もしない } else { switch (objData.Type) { case "StapleBowl": if (double.TryParse(objResult.Staplefood, out dblResult) == false) { objResult.Staplefood = objData.Quantity; } else { // 結果のほうが大きい時だけ値を設定する if (dblResult < double.Parse(objData.Quantity)) { objResult.Staplefood = objData.Quantity; } } break; case "MainDishPlate": if (double.TryParse(objResult.MainDish, out dblResult) == false) { objResult.MainDish = objData.Quantity; } else { // 結果のほうが大きい時だけ値を設定する if (dblResult < double.Parse(objData.Quantity)) { objResult.MainDish = objData.Quantity; } } break; case "SubFoodPlate": if (double.TryParse(objResult.SideDish, out dblResult) == false) { objResult.SideDish = objData.Quantity; } else { // 結果のほうが大きい時だけ値を設定する if (dblResult < double.Parse(objData.Quantity)) { objResult.SideDish = objData.Quantity; } } break; case "Bowl": if (double.TryParse(objResult.Staplefood, out dblResult) == false) { objResult.Staplefood = objData.Quantity; } else { // 結果のほうが大きい時だけ値を設定する if (dblResult < double.Parse(objData.Quantity)) { objResult.Staplefood = objData.Quantity; } } if (double.TryParse(objResult.MainDish, out dblResult) == false) { objResult.MainDish = objData.Quantity; } else { // 結果のほうが大きい時だけ値を設定する if (dblResult < double.Parse(objData.Quantity)) { objResult.MainDish = objData.Quantity; } } break; default: break; } } } // 戻り値を返却する return objResult; } //======================================== // エラー処理 //======================================== catch (Exception ex){ throw new Exception("ImageAnalysis Error." + ex.Message,ex); } finally { } } //============================================================ // 【説明】 // Custom Vision AI呼び出し、解析結果を返却する関数 // // 【引数】 // 読み込む画像のPath // 【戻り値】 // JSON // List<PredictionModel> Cognitiveの戻り値 // //============================================================ private static IList<PredictionModel> QuantityAnalysisyAsync(string strApiKey, string strProjectId,string strPublishedName, Stream filestream) { //------------------------------ // 変数宣言 //------------------------------ try{ // izumozaki ok st CustomVisionPredictionClient endpoint = new CustomVisionPredictionClient() { ApiKey = strApiKey, // PredictionKey Endpoint = cstrEndPoint // EndPoint }; // 分析開始 var objImagePrediction = endpoint.ClassifyImage(Guid.Parse(strProjectId), strPublishedName, filestream); // Project Id,PublishedName return objImagePrediction.Predictions; // izumozaki ed } catch(Exception ex){ throw new Exception("QuantityAnalysisAsync" + ex.Message,ex); } finally { } } public class PersonCodeAuth { public string Status { get; set; } public string[] recognitionResult { get; set; } } public class GoogleAIVisionJson { public string Result { get; set; } public string NumberObObject { get; set; } public string[] DataOfObject { get; set; } } // CustomVisionから取得したオブジェクトの種類ごとのデータ public class QuantityAnalysisData { public string Staplefood { get; set; } public string MainDish { get; set; } public string SideDish { get; set; } } // CustomVisionから取得した個々のデータ public class QuantityData { public string Type { get; set; } public string Quantity { get; set; } } } } ```
对计算机专业来说学历真的重要吗?
我本科学校是渣渣二本,研究生学校是985,现在毕业五年,校招笔试、面试,社招面试参加了两年了,就我个人的经历来说下这个问题。 这篇文章很长,但绝对是精华,相信我,读完以后,你会知道学历不好的解决方案,记得帮我点赞哦。 先说结论,无论赞不赞同,它本质就是这样:对于技术类工作而言,学历五年以内非常重要,但有办法弥补。五年以后,不重要。 目录: 张雪峰讲述的事实 我看到的事实 为什么会这样 ...
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
小白学 Python 爬虫(25):爬取股票信息
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Linux基础入门 小白学 Python 爬虫(4):前置准备(三)Docker基础入门 小白学 Python 爬虫(5):前置准备(四)数据库基础 小白学 Python 爬虫(6):前置准备(...
小知识:浅谈二维码的生成和识别原理
目录 前言 条形码 静态二维码 二进制生成图形码 二维码的定位 前言 不知不觉中,我们的生活到处充满了二维码。登录账户需要二维码;加好友需要二维码;共享单车需要二维码;商品包装上也有二维码;甚至连楼下卖水果的阿姨手里都拿张二维码收款。那么,有没有想过这个二维码到底是什么东西呢?那么这个二维码的图案会不会多到不小心重合了呢? 条形码 在二维码出现之前,大行其道的...
[享学Jackson] 一、初识Jackson -- 世界上最好的JSON库
Jackson是一个简单的、功能强大的、基于Java的**应用库**。它可以很方便完成**Java对象**和**json对象(xml文档or其它格式)**进行互转。Jackson社区相对比较活跃,更新速度也比较快。Jackson库有如下几大特性: - 高性能,稳定:低内存占用,对大/小JSON串,大/小对象的解析表现均很优秀 - 流行度高:是很多流行框架的默认实现 - 容易使用:提供高层次的API,极大简化了日常使用 - 无需自己手动创建映射:内置了绝大部分序列化时和Java类型的映射关系 - 干净的JSO
卸载 x 雷某度!GitHub 标星 1.5w+,从此我只用这款全能高速下载工具!
作者 | Rocky0429 来源 | Python空间 大家好,我是 Rocky0429,一个喜欢在网上收集各种资源的蒟蒻… 网上资源眼花缭乱,下载的方式也同样千奇百怪,比如 BT 下载,磁力链接,网盘资源等等等等,下个资源可真不容易,不一样的方式要用不同的下载软件,因此某比较有名的 x 雷和某度网盘成了我经常使用的工具。 作为一个没有钱的穷鬼,某度网盘几十 kb 的下载速度让我...
世界上最牛的网络设备,价格低廉,其貌不扬......
夜深人静,电视和电脑都已经关机休息,但是我还在默默工作,我安静地趴在你家中的某个地方,7*24小时不眠不休,任劳任怨,目的只有一个,能让你舒服地躺在床上,畅快地刷手机!没错,这就是我,...
《面试宝典》2019年springmvc面试高频题(java)
前言 2019即将过去,伴随我们即将迎来的又是新的一年,过完春节,马上又要迎来新的金三银四面试季。那么,作为程序猿的你,是否真的有所准备的呢,亦或是安于本职工作,继续做好手头上的事情。 当然,不论选择如何,假如你真的准备在之后的金三银四跳槽的话,那么作为一个Java工程师,就不可不看了。如何在几个月的时间里,快速的为即将到来的面试进行充分的准备呢? 1、什么是Spring MVC ?简单...
一名大专同学的四个问题
【前言】   收到一封来信,赶上各种事情拖了几日,利用今天要放下工作的时机,做个回复。   2020年到了,就以这一封信,作为开年标志吧。 【正文】   您好,我是一名现在有很多困惑的大二学生。有一些问题想要向您请教。   先说一下我的基本情况,高考失利,不想复读,来到广州一所大专读计算机应用技术专业。学校是偏艺术类的,计算机专业没有实验室更不用说工作室了。而且学校的学风也不好。但我很想在计算机领...
复习一周,京东+百度一面,不小心都拿了Offer
京东和百度一面都问了啥,面试官百般刁难,可惜我全会。
轻松搭建基于 SpringBoot + Vue 的 Web 商城应用
首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算、API ...
Python+OpenCV实时图像处理
目录 1、导入库文件 2、设计GUI 3、调用摄像头 4、实时图像处理 4.1、阈值二值化 4.2、边缘检测 4.3、轮廓检测 4.4、高斯滤波 4.5、色彩转换 4.6、调节对比度 5、退出系统 初学OpenCV图像处理的小伙伴肯定对什么高斯函数、滤波处理、阈值二值化等特性非常头疼,这里给各位分享一个小项目,可通过摄像头实时动态查看各类图像处理的特点,也可对各位调参、测试...
2020年一线城市程序员工资大调查
人才需求 一线城市共发布岗位38115个,招聘120827人。 其中 beijing 22805 guangzhou 25081 shanghai 39614 shenzhen 33327 工资分布 2020年中国一线城市程序员的平均工资为16285元,工资中位数为14583元,其中95%的人的工资位于5000到20000元之间。 和往年数据比较: yea...
为什么猝死的都是程序员,基本上不见产品经理猝死呢?
相信大家时不时听到程序员猝死的消息,但是基本上听不到产品经理猝死的消息,这是为什么呢? 我们先百度搜一下:程序员猝死,出现将近700多万条搜索结果: 搜索一下:产品经理猝死,只有400万条的搜索结果,从搜索结果数量上来看,程序员猝死的搜索结果就比产品经理猝死的搜索结果高了一倍,而且从下图可以看到,首页里面的五条搜索结果,其实只有两条才是符合条件。 所以程序员猝死的概率真的比产品经理大,并不是错...
害怕面试被问HashMap?这一篇就搞定了!
声明:本文以jdk1.8为主! 搞定HashMap 作为一个Java从业者,面试的时候肯定会被问到过HashMap,因为对于HashMap来说,可以说是Java集合中的精髓了,如果你觉得自己对它掌握的还不够好,我想今天这篇文章会非常适合你,至少,看了今天这篇文章,以后不怕面试被问HashMap了 其实在我学习HashMap的过程中,我个人觉得HashMap还是挺复杂的,如果真的想把它搞得明明白...
毕业5年,我问遍了身边的大佬,总结了他们的学习方法
我问了身边10个大佬,总结了他们的学习方法,原来成功都是有迹可循的。
推荐10个堪称神器的学习网站
每天都会收到很多读者的私信,问我:“二哥,有什么推荐的学习网站吗?最近很浮躁,手头的一些网站都看烦了,想看看二哥这里有什么新鲜货。” 今天一早做了个恶梦,梦到被老板辞退了。虽然说在我们公司,只有我辞退老板的份,没有老板辞退我这一说,但是还是被吓得 4 点多都起来了。(主要是因为我掌握着公司所有的核心源码,哈哈哈) 既然 4 点多起来,就得好好利用起来。于是我就挑选了 10 个堪称神器的学习网站,推...
这些软件太强了,Windows必装!尤其程序员!
Windows可谓是大多数人的生产力工具,集娱乐办公于一体,虽然在程序员这个群体中都说苹果是信仰,但是大部分不都是从Windows过来的,而且现在依然有很多的程序员用Windows。 所以,今天我就把我私藏的Windows必装的软件分享给大家,如果有一个你没有用过甚至没有听过,那你就赚了????,这可都是提升你幸福感的高效率生产力工具哦! 走起!???? NO、1 ScreenToGif 屏幕,摄像头和白板...
(总结)阿里面试问了ArrayList,都问了啥?
我是真的没想到,面试官会这样问我ArrayList。
曾经优秀的人,怎么就突然不优秀了。
职场上有很多辛酸事,很多合伙人出局的故事,很多技术骨干被裁员的故事。说来模板都类似,曾经是名校毕业,曾经是优秀员工,曾经被领导表扬,曾经业绩突出,然而突然有一天,因为种种原因,被裁员了,...
大学四年因为知道了这32个网站,我成了别人眼中的大神!
依稀记得,毕业那天,我们导员发给我毕业证的时候对我说“你可是咱们系的风云人物啊”,哎呀,别提当时多开心啦????,嗯,我们导员是所有导员中最帅的一个,真的???? 不过,导员说的是实话,很多人都叫我大神的,为啥,因为我知道这32个网站啊,你说强不强????,这次是绝对的干货,看好啦,走起来! PS:每个网站都是学计算机混互联网必须知道的,真的牛杯,我就不过多介绍了,大家自行探索,觉得没用的,尽管留言吐槽吧???? 社...
2020年1月中国编程语言排行榜,python是2019增长最快编程语言
编程语言比例 排名 编程语言 最低工资 工资中位数 最低工资 最高工资 人头 人头百分比 1 rust 20713 17500 5042 46250 480 0.14% 2 typescript 18503 22500 6000 30000 1821 0.52% 3 lua 18150 17500 5250 35000 2956 0.84% 4 go 17989 16...
看完这篇HTTP,跟面试官扯皮就没问题了
我是一名程序员,我的主要编程语言是 Java,我更是一名 Web 开发人员,所以我必须要了解 HTTP,所以本篇文章就来带你从 HTTP 入门到进阶,看完让你有一种恍然大悟、醍醐灌顶的感觉。 最初在有网络之前,我们的电脑都是单机的,单机系统是孤立的,我还记得 05 年前那会儿家里有个电脑,想打电脑游戏还得两个人在一个电脑上玩儿,及其不方便。我就想为什么家里人不让上网,我的同学 xxx 家里有网,每...
史上最全的IDEA快捷键总结
现在Idea成了主流开发工具,这篇博客对其使用的快捷键做了总结,希望对大家的开发工作有所帮助。
阿里程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
谁是华为扫地僧?
是的,华为也有扫地僧!2020年2月11-12日,“养在深闺人不知”的华为2012实验室扫地僧们,将在华为开发者大会2020(Cloud)上,和大家见面。到时,你可以和扫地僧们,吃一个洋...
Idea 中最常用的10款插件(提高开发效率),一定要学会使用!
学习使用一些插件,可以提高开发效率。对于我们开发人员很有帮助。这篇博客介绍了开发中使用的插件。
AI 没让人类失业,搞 AI 的人先失业了
最近和几个 AI 领域的大佬闲聊 根据他们讲的消息和段子 改编出下面这个故事 如有雷同 都是巧合 1. 老王创业失败,被限制高消费 “这里写我跑路的消息实在太夸张了。” 王葱葱哼笑一下,把消息分享给群里。 阿杰也看了消息,笑了笑。在座几位也都笑了。 王葱葱是个有名的人物,21岁那年以全额奖学金进入 KMU 攻读人工智能博士,累计发表论文 40 余篇,个人技术博客更是成为深度学习领域内风向标。 ...
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆每天早上8:30推送 作者|Mr.K 编辑| Emma 来源|技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯...
立即提问