windows程序移植到linux的方式和会遇到的问题
怎么移植
写一个makefile文件足矣解决这些问题,执行make在结果中去找问题,外加修改即可,所以就不过多的赘述了
移植时可能遇到的问题
以下是我在移植时遇到的问题
1.sleep函数
2.getch()和getche()函数在linux下不兼容
3.头文件包含不同
4.乱码问题
5.对于缓冲区的控制
6.如该程序需要输入密码,linux如何控制回显和退格删除错误字符
7.gets函数的危险性
1.sleep函数
- 在windows中
Sleep(2*1000); //睡眠两秒
- 在linux中
sleep(2); //睡眠两秒
所以一定要注意在不同系统下函数参数有可能不一样,移植到linux中一定要修改,否则很难查找
2.getch()和getche()函数在linux下不兼容
-
函数功能:getch()函数不将读入的字符回显在显示屏幕上, 而
getche() 函数却将读入的字符回显到显示屏幕上。 -
在windows下,头文件#include<stdio.h>中既有这两个函数,可以直接调用
-
在linux下,没有这两个函数,所以需要自己手写这两个函数
我们可以写一个conio.h 和conio.c 文件
//conio.c
#include "conio.h"
#include<stdio.h>
char getch()
{
char c;
system("stty -echo"); //不回显
system("stty -icanon");//设置一次性读完操作,如使用getchar()读操作,不需要按enter
c=getchar();
system("stty icanon");//取消上面的设置
system("stty echo");//回显
return c;
}
char getche()
{
char c;
system("stty -icanon");
c=getchar();
system("stty icanon");
return c;
}
//conio.h
#ifndef _CONIO_H
#define _CONIO_H
#include <stdio.h>
#include <stdlib.h>
char getch();
char getche();
#endif
在运行程序的时候把conio.h这个头文件包含进去就可以了
3.头文件包含不同
- 比如sleep函数,在windows下要求的头文件是#include<windows.h>
在linux下要求的头文件是#include<unistd.h>
access函数,在windows下要求的头文件是#include<io.h>
在linux下要求的头文件是#include<unistd.h> - 所以一定要注意特定函数在不同系统下的使用,但其实利用makefile检错会自动显示出错误
4.乱码问题
- windows下默认的中文编码方式是GBK
而linux下的默认的中文编码方式是UTF-8
所以可以在终端下修改编码方式解决这一问题 - 乱码问题确实足够的让人头疼,在windows下明明可以正常输出,但是转到linux下突然不能正常显示了,这问题搞了一中午,还是没能很好的解决
暂时只能借助终端改变不同的编码方式
改好了所有的问题,最终运行程序显示的结果是这样
在终端下点击右键,选择编码方式,找到需要的结果
这下终于好了
虽然还没完美解决,以后有了更好的方式再更新吧
5.对于缓冲区的控制,具体见7
- 在输入密码的时候要特别注意缓冲区,例如下面的代码部分
//这是该系统刚进入去输入账户和密码的代码
for (i = 0; i < 3; i++) {
printf("\n\n\n\n\t\t\t\t\t");
printf("\n\n\t\t\t\t\t 南波万剧院票务管理系统\n");
printf("\n\n\t\t\t\t\t\t账号: ");
scanf("%[^\n]",usrname); //读取账户
fflush(stdin);
printf("\n\t\t\t\t\t\t密码: ");
int ret = GetPassword(passwd); //获取密码
用scanf去读取账户名,回车结束输入账户名,这时回车就会被加入到缓冲区,当利用GetPassword获取密码时,第一个字符就成了回车,所以需要用fflush去冲刷缓冲区,利用getch也可以
6.如该程序需要输入密码,linux如何控制回显和退格删除错误字符
int GetPassword(char password[])
{
char ch;
int i;
for(i=0;i<20;i++){
ch=getch();
if(ch== 8){
if((i-1)>=0){
i-=2;
printf("\b\b \b\b");
}
else
i--;
continue;
}
if(ch == '\n')
break;
password[i]=ch;
printf("*");
}
password[i]='\0';
return i;
}
在windows下,这是可以正常执行删除的,但是在linux下会正常读取退格键,并输入密码,
//解决不能使用退格键的方案
int GetPassword(char* passwd)
{
int c;
int n = 0;
do
{
c=getch();
if (c != '\n'&& c!='\r' && c!=127)
{
passwd[n] = c;
printf("*");
n++;
}
else if ((c != '\n'|c!='\r')&&c==127)//判断是否是回车或者是退格
{
if(n>0)
{
n--;
printf("\b \b");//输出退格
}
}
}while(c != '\n' && c !='\r' );
passwd[n] = '\0'; //消除一个多余的回车
return n;
}
7.gets函数的危险性,scanf读数据不干净!!!
scanf在读完之后空格还在缓冲区中
gets函数能够接收字符串和空格, 而且不把回车符号留在缓存区中。
#include<stdio.h>
int main(void)
{
char a1[10],a2[10],a3[10];
scanf("%s",a1);
gets(a2);
gets(a3);
puts(a1);
puts(a2);
puts(a3);
printf("end...");
return 0;
}
输入: |输入:
qwe asd |abc
zxc |def
结果: |ghi
qwe |abc
asd |
zxc |def
end... |end...
//因为scanf把回车 / 空格 扔进了缓冲区,所以在第二次输入ghi被丢弃
由于gets不会检查越界,所以不安全,gets 函数里面输入的字符串过长也会出现直接崩溃的情况。
一般换做更为安全的fgets函数或scanf函数(格式改为可接受空格)
char buf[30];
scanf("%[^\n]",buf); //读入一行字符串带空格的字符
fgets(buf,30,stdin);