一个C语言开源练手项目

李肖遥 2025-01-12 22:13
    关注、星标公众号,直达精彩内容



账号登录系统在很多系统设计时都时必不可少的,今天这个登录系统功能较全,可以注册,登录,找回密码,修改密码,以及在输入密码时会有*将密码掩盖,还有完善地登录选择界面,废话不多,上代码!

目录

  • 1.头文件&结构体&大概函数实现

  • 2.主函数&登录界面

  • 3.注册系统

  • 4.登录系统

  • 5.找回密码(更改密码)

  • 6.密码输入获取&密码掩盖

7.完整代码!!!!!

!!!!首先需要在和.c文件同个目录下新建一个文件储存数据,命名users.dat  如图!!

img

!!!!!!!!!!!!!!!!!!!!

也可以命名别的,后缀dat是我自己随便取的,喜欢就行!但是记得在代码中将文件名改过来!

1.头文件&结构体&大概函数实现

//引头文件
#include 
#include 
#include 
#include //用于反应意外情况的,下面会讲到
#include 

//定义宏常量
#define MAX_ID 11//ID的最大长度
#define MAX_PWD 20//密码的最大长度
#define MAX_NAME 15//名字的最大长度
#define MAX_SEX 5//性别的最大长度
#define MAX_PHONE 12//电话的最大长度


//创建用户的结构体
typedef struct Users
{

 char id[MAX_ID];//id 即登录的账号
 char pwd[MAX_PWD];//密码
 char name[MAX_NAME];//姓名
 char sex[MAX_SEX];//性别
 char phone[MAX_PHONE];//电话
}Users;

//声明函数

//打印菜单
void menu();

//用户注册
void Register();

//登录
void Login();

//找回密码
void Reback();

 

//定位光标
void gotoxy();

//获取x的位置
int posx();

//获取y的位置
int posy();

//密码输入(含掩盖功能)
void Getpwd(char* pwd);

这里定义了很多宏常量,可以看情况修改合适的数值,比较快捷方便,不用到代码里一个个改

2.主函数&登录界面

void menu()
{
 printf("************************************\n");
 printf("************************************\n");
 printf("*****1.Register         2.Login*****\n");
 printf("*****3.Reback           0.exit *****\n");
 printf("************************************\n");
 printf("************************************\n");
}

int main()
{
 char input;
 do
 {
  menu();
  setbuf(stdinNULL);//清空输入缓冲区,避免下面getchar读到上一次输入缓冲区剩下的东西
  input = getchar();
  switch (input)
  {
  case '1':
   Register();
   break;
  case '2':
   Login();
   break;
  case '3':
   Reback();
   break;
  case '0':
   printf("退出成功!\n");
   break;
  default:
   printf("选择错误,请重新选择!\n");
   break;
  }
 } while (input!='0');//如果输入了0,就exit退出咯
}

这里用到字符去当作switch的判断依据,是因为如果用整形去做判断依据的话,若向input中输入的东西不是整形而是字符或者字符串,switch在循环中就会陷入死循环,具体情况大家去试试就知道,这里不多讲解,用单个字符判断到现在是没试出什么bug。

3.注册系统

void Register()
{
 Users a, b;//创建用户结构体临时变量,a是用来接收用户输入的,b是用来从文件中读取的,来和a作比较

 char tmp[20]="";//用着下面判断的
  
 printf("欢迎来到注册界面!\n");
 FILE* pf = fopen("users.dat""rb");//"rb"是以二进制只读方式打开文件的意思
 fread(&b, sizeof(Users), 1, pf);//将数据读入b中
 if (!pf)//如果打开失败
 {
  printf("%s", strerror(errno));//errno可以理解是报的错误对应的编号,strerror可以把这个编号翻译出来,输出在屏幕上
  return;
 }
 Sleep(800);
  
 printf("请输入您的账号>>");
 scanf("%s", a.id);
 while (1)
 {
  if (strcmp(a.id, b.id))//两个用户名不相等
  {
   if (!feof(pf))//没读到文件末尾
   {
    fread(&b, sizeof(Users), 1, pf);//继续读取文件中的用户到b中
   }
   else//读到文件末尾了,确认没有重复的id
   {
    break;
   }
  }
  else//有两个用户名相等
  {
   printf("此用户名已存在在,请重新输入!\n");
   Sleep(1000);
   fclose(pf);//关闭文件
   pf = NULL;//pf置空,避免野指针
   return;
  }
 }
 printf("请输入您的姓名>>");
 scanf("%s", a.name);
 printf("请输入您的性别>>");
 scanf("%s", a.sex);
 printf("请输入您的电话号码>>");
 scanf("%s", a.phone);
 printf("请输入您的密码>>");
 Getpwd(a.pwd);//输入密码的函数,有掩盖功能,下面会介绍
 printf("\n请再次确认您的密码>>");
 Getpwd(tmp);
 do
 {
  if (!strcmp(a.pwd, tmp))//两次密码相等
  {
   pf = fopen("users.dat""ab");
   fwrite(&a, sizeof(Users), 1, pf);
   printf("\n账号注册成功,请登录!\n");
   Sleep(500);
   fclose(pf);
   pf = NULL;
   return;
  }
  else
  {
   printf("\n两次密码不匹配!请重新输入>>");
   Getpwd(a.pwd);
   printf("\n请再次确认>>");
   Getpwd(tmp);
  }
 } while (1);

}

文件都是以二进制打开以二进制写入的,没别的原因,就是觉得帅!

关注公众号:C语言中文社区,免费领取300G编程资料

4.登录系统

void Login()
{
 Users a, b;//同理,a是用来给用户输入的,b是用来是水的(从文件中读取到b中,用b和a匹配比较)

 FILE* pf = fopen("users.dat""rb");//以只读的方式打开文件
 if (!pf)//如果读取失败
 {
  printf("%s\n", strerror(errno));//上面有讲过~
  return;
 }
 printf("欢迎来到登录界面!\n");
 Sleep(1000);
  
 fread(&b, sizeof(Users), 1, pf);//先从文件中读取一个用户试试水
  
 printf("请输入账号>>");
 scanf("%s", a.id);
  
 while (1)
 {
  if (!strcmp(a.id, b.id))//在文件中找到了与用户输入相同的id
  {
   break;
  }
  else
  {
   if (!feof(pf))//没读到文件末尾,继续读取文件中的id到b中
   {
    fread(&b, sizeof(Users), 1, pf);//继续从文件中读取用户信息进b,直到在文件中找到一个和a的信息相同的
   }
   else//读到文件末尾了,没有找到与用户输入相同的账号
   {
    printf("此账号不存在!请重新输入!\n");
    Sleep(500);
    fclose(pf);
    pf = NULL;
    return;
   }
  }
 }
 do
 {
  printf("请输入密码>>");
  Getpwd(a.pwd);//获取密码,在下面会讲
  if (!strcmp(a.pwd, b.pwd))//输入的密码与文件中的相同
  {
   printf("\n登录成功!欢迎使用!\n");
   Sleep(500);
   fclose(pf);//用完当然要把文件关啦
   pf = NULL;//置空,避免野指针
   return;
  }
  else
  {
   printf("\n密码输入错误,请重新输入\n");
  }
 } while (strcmp(a.pwd, b.pwd));

}

大概思路就是用户先输入账号(id),接着b从文件中读取用户,直到找到与用户输入id相同的,然后就是输入密码判断密码对不对咯。  里面用到了一个库函数strcmp,判断字符串是不是一样的,如果一样则返回0,不一样则返回一个非0值。

5.找回密码(更改密码)

void Reback()
{
 char tmp[20] = "";//密码匹配用的
 Users a, b;

 FILE* pf = fopen("users.dat""rb+");//"rb+"是为了读和写以二进制打开文件的意思
  
 if (!pf)//老样子,先判断能不能顺利打开
 {
  printf("%s", strerror(errno));
  return;
 }
  
 fread(&b, sizeof(Users), 1, pf);//照样,读一个试试水
  
 printf("请输入您的账号>>");
 Sleep(800);
  
 scanf("%s", a.id);
  
 while (1)//在文件中找到与用户输入相同的id
 {
  if (!strcmp(a.id, b.id))//如果读取到了相同的id(在文件中找到了和用户输入一样的)
  {
   break;
  }
  else
  {
   if (!feof(pf))//没读到文件尾,继续读
   {
    fread(&b, sizeof(Users), 1, pf);
   }
   else
   {
    printf("您输入的账号不存在!请重新输入!\n");
    Sleep(500);
    fclose(pf);
    pf = NULL;
    break;
   }
  }
 }
  
 //下面是信息匹配验证
 do//匹配姓名
 {
  printf("请输入您的姓名>>");
  scanf("%s", a.name);
  if (!strcmp(a.name, b.name))
  {
   break;
  }
  else
  {
   printf("输入错误,请重新输入!\n");
  }
 } while (strcmp(a.name, b.name));
  
 do//匹配性别
 {
  printf("请输入您的性别>>");
  scanf("%s", a.sex);
  if (!strcmp(a.sex, b.sex))
  {
   break;
  }
  else
  {
   printf("输入错误,请重新输入!\n");
  }
 } while (strcmp(a.sex, b.sex));
 do//匹配电话号码
 {
  printf("请输入您的电话号码>>");
  scanf("%s", a.phone);
  if (!strcmp(a.phone, b.phone))
  {
   break;
  }
  else
  {
   printf("输入错误,请重新输入!\n");
  }
 } while (strcmp(a.phone, b.phone));
  
 //更改密码
 printf("验证成功!请修改您的密码!\n");
 printf("请输入您的密码>>");
 Getpwd(a.id);
 printf("请再次确认您的密码>>");
 Getpwd(tmp);
 if (!pf)
 {
  printf("%s", strerror(errno));
  return;
 }
 //将原来的密码覆盖掉
 do
 {
  if (!strcmp(a.pwd, tmp))//两次密码相等
  {
   fseek(pf,-((int)(sizeof(Users)-MAX_ID)), SEEK_CUR);//将文件流调回到要修改的密码的位置
   fprintf(pf, "%s", a.pwd);//覆盖原来的密码
   printf("密码修改成功,请登录!\n");
   Sleep(500);
   fclose(pf);
   pf = NULL;
   return;
  }
  else
  {
   printf("两次密码不匹配!请重新输入>>");
   scanf("%s", a.pwd);
   printf("请再次确认>>");
   scanf("%s", tmp);
  }
 } while (1);

}

大概思路是输入账号->匹配信息->修改密码,修改密码时要将文件流调回要修改的密码的前面,这里用到了fseek,-((int)(sizeof(Users)-MAX_ID))是要调回的范围。

6.密码输入获取&密码掩盖

void gotoxy(int x, int y)
{
 //更新光标位置
 COORD pos;
 HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle是一个Windows API函数。
 pos.X = x;
 pos.Y = y;
 SetConsoleCursorPosition(hOutput, pos);
}

int posx()
{
 CONSOLE_SCREEN_BUFFER_INFO ptr;
 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
 return (ptr.dwCursorPosition.X);
}

int posy()
{
 CONSOLE_SCREEN_BUFFER_INFO ptr;
 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
 return (ptr.dwCursorPosition.Y);
}


void Getpwd(char* pwd)
{
 int i = 0;
 int x, y;
 while (1)
 {
  pwd[i] = getch();//获取单个密码(字符)
  if (pwd[i] == VK_BACK && i >= 0)//如果输入的是回退键,VK_BACK是键盘的键值,ASCII码值为8
  {
   if (i > 0)//i>0说明有输入东西了,则回退前一格
   {
    i--;
    x = posx() - 1;//定位x并回退一格
    y = posy();//定位y
    gotoxy(x, y);//定位光标
    printf(" ");//将*用空格掩盖
    x = posx() - 1;//再次回退,下次输入时光标才会显示在正确的位置
    y = posy();//定位y
    gotoxy(x, y);
    continue;//然后跳过此次循环
   }
   else if (i == 0)//i==0说明没输入东西,直接跳过此次循环即可
   {
    continue;
   }
  }
  if (i >= 0 && pwd[i] != VK_RETURN && pwd[i] != VK_BACK)//输入东西了
  {
   x = posx();
   y = posy();
   gotoxy(x, y);
   printf("*");
  }
  if (i == 0 && pwd[i] == VK_RETURN)//如果没输入东西直接按回车,直接跳过此次循环,避免程序把回车当密码了
  {
   continue;
  }
  if (pwd[i] == VK_RETURN||i==MAX_PWD-2)//输入回车了或者到上限了
  {
   i++;
   pwd[i] = '\0';//结尾放'\0'
   break;
  }
  i++;
 }
}

那几个长长的都是windows控制台的API函数,这里不多讲解

7.完整代码!!!!!

//引头文件
#include 
#include 
#include 
#include 
#include 

//定义宏常量
#define MAX_ID 11
#define MAX_PWD 20
#define MAX_NAME 15
#define MAX_SEX 5
#define MAX_PHONE 12


//创建用户的结构体
typedef struct Users
{

 char id[MAX_ID];
 char pwd[MAX_PWD];
 char name[MAX_NAME];
 char sex[MAX_SEX];
 char phone[MAX_PHONE];
}Users;

 

//声明函数

//打印菜单
void menu();

//用户注册
void Register();

//登录
void Login();

//找回密码
void Reback();

//定位光标
void gotoxy();

//获取x的位置
int posx();

//获取y的位置
int posy();

//密码输入(含掩盖功能)
void Getpwd(char* pwd);

int main()//主函数 ,
{
 char input;
 do
 {
  menu();
  setbuf(stdinNULL);
  input = getchar();
  switch (input)
  {
  case '1':
   Register();
   break;
  case '2':
   Login();
   break;
  case '3':
   Reback();
   break;
  case '0':
   printf("退出成功!\n");
   break;
  default:
   printf("选择错误,请重新选择!\n");
   break;
  }
 } while (input!='0');
}

//打印菜单
void menu()
{
 printf("************************************\n");
 printf("************************************\n");
 printf("*****1.Register         2.Login*****\n");
 printf("*****3.Reback           0.exit *****\n");
 printf("************************************\n");
 printf("************************************\n");
}

//注册系统
void Register()
{
 Users a, b;//创建用户结构体临时变量,a是用来接收用户输入的,b是用来从文件中读取的,来和a作比较

 char tmp[20]="";//用着下面判断的
  
 printf("欢迎来到注册界面!\n");
 FILE* pf = fopen("users.dat""rb");//"rb"是以二进制只读方式打开文件的意思
 fread(&b, sizeof(Users), 1, pf);//将数据读入b中
 if (!pf)//如果打开失败
 {
  printf("%s", strerror(errno));//errno可以理解是报的错误对应的编号,strerror可以把这个编号翻译出来,输出在屏幕上
  return;
 }
 Sleep(800);
  
 printf("请输入您的账号>>");
 scanf("%s", a.id);
 while (1)
 {
  if (strcmp(a.id, b.id))//两个用户名不相等
  {
   if (!feof(pf))//没读到文件末尾
   {
    fread(&b, sizeof(Users), 1, pf);//继续读取文件中的用户到b中
   }
   else//读到文件末尾了,确认没有重复的id
   {
    break;
   }
  }
  else//有两个用户名相等
  {
   printf("此用户名已存在在,请重新输入!\n");
   Sleep(1000);
   fclose(pf);//关闭文件
   pf = NULL;//pf置空,避免野指针
   return;
  }
 }
 printf("请输入您的姓名>>");
 scanf("%s", a.name);
 printf("请输入您的性别>>");
 scanf("%s", a.sex);
 printf("请输入您的电话号码>>");
 scanf("%s", a.phone);
 printf("请输入您的密码>>");
 Getpwd(a.pwd);//输入密码的函数,有掩盖功能,下面会介绍
 printf("\n请再次确认您的密码>>");
 Getpwd(tmp);
 do
 {
  if (!strcmp(a.pwd, tmp))//两次密码相等
  {
   pf = fopen("users.dat""ab");
   fwrite(&a, sizeof(Users), 1, pf);
   printf("\n账号注册成功,请登录!\n");
   Sleep(500);
   fclose(pf);
   pf = NULL;
   return;
  }
  else
  {
   printf("\n两次密码不匹配!请重新输入>>");
   Getpwd(a.pwd);
   printf("\n请再次确认>>");
   Getpwd(tmp);
  }
 } while (1);

}

//登录系统
void Login()
{
 Users a, b;//同理,a是用来给用户输入的,b是用来是水的(从文件中读取到b中,用b和a匹配比较)

 FILE* pf = fopen("users.dat""rb");//以只读的方式打开文件
 if (!pf)//如果读取失败
 {
  printf("%s\n", strerror(errno));//上面有讲过~
  return;
 }
 printf("欢迎来到登录界面!\n");
 Sleep(1000);
  
 fread(&b, sizeof(Users), 1, pf);//先从文件中读取一个用户试试水
  
 printf("请输入账号>>");
 scanf("%s", a.id);
  
 while (1)
 {
  if (!strcmp(a.id, b.id))//在文件中找到了与用户输入相同的id
  {
   break;
  }
  else
  {
   if (!feof(pf))//没读到文件末尾,继续读取文件中的id到b中
   {
    fread(&b, sizeof(Users), 1, pf);//继续从文件中读取用户信息进b,直到在文件中找到一个和a的信息相同的
   }
   else//读到文件末尾了,没有找到与用户输入相同的账号
   {
    printf("此账号不存在!请重新输入!\n");
    Sleep(500);
    fclose(pf);
    pf = NULL;
    return;
   }
  }
 }
 do
 {
  printf("请输入密码>>");
  Getpwd(a.pwd);//获取密码,在下面会讲
  if (!strcmp(a.pwd, b.pwd))//输入的密码与文件中的相同
  {
   printf("\n登录成功!欢迎使用!\n");
   Sleep(500);
   fclose(pf);//用完当然要把文件关啦
   pf = NULL;//置空,避免野指针
   return;
  }
  else
  {
   printf("\n密码输入错误,请重新输入\n");
  }
 } while (strcmp(a.pwd, b.pwd));

}

//找回密码
void Reback()
{
 char tmp[20] = "";//密码匹配用的
 Users a, b;

 FILE* pf = fopen("users.dat""rb+");//"rb+"是为了读和写以二进制打开文件的意思
  
 if (!pf)//老样子,先判断能不能顺利打开
 {
  printf("%s", strerror(errno));
  return;
 }
  
 fread(&b, sizeof(Users), 1, pf);//照样,读一个试试水
  
 printf("请输入您的账号>>");
 Sleep(800);
  
 scanf("%s", a.id);
  
 while (1)//在文件中找到与用户输入相同的id
 {
  if (!strcmp(a.id, b.id))//如果读取到了相同的id(在文件中找到了和用户输入一样的)
  {
   break;
  }
  else
  {
   if (!feof(pf))//没读到文件尾,继续读
   {
    fread(&b, sizeof(Users), 1, pf);
   }
   else
   {
    printf("您输入的账号不存在!请重新输入!\n");
    Sleep(500);
    fclose(pf);
    pf = NULL;
    break;
   }
  }
 }
  
 //下面是信息匹配验证
 do//匹配姓名
 {
  printf("请输入您的姓名>>");
  scanf("%s", a.name);
  if (!strcmp(a.name, b.name))
  {
   break;
  }
  else
  {
   printf("输入错误,请重新输入!\n");
  }
 } while (strcmp(a.name, b.name));
  
 do//匹配性别
 {
  printf("请输入您的性别>>");
  scanf("%s", a.sex);
  if (!strcmp(a.sex, b.sex))
  {
   break;
  }
  else
  {
   printf("输入错误,请重新输入!\n");
  }
 } while (strcmp(a.sex, b.sex));
 do//匹配电话号码
 {
  printf("请输入您的电话号码>>");
  scanf("%s", a.phone);
  if (!strcmp(a.phone, b.phone))
  {
   break;
  }
  else
  {
   printf("输入错误,请重新输入!\n");
  }
 } while (strcmp(a.phone, b.phone));
  
 //更改密码
 printf("验证成功!请修改您的密码!\n");
 printf("请输入您的密码>>");
 Getpwd(a.id);
 printf("请再次确认您的密码>>");
 Getpwd(tmp);
 if (!pf)
 {
  printf("%s", strerror(errno));
  return;
 }
 //将原来的密码覆盖掉
 do
 {
  if (!strcmp(a.pwd, tmp))//两次密码相等
  {
   fseek(pf,-((int)(sizeof(Users)-MAX_ID)), SEEK_CUR);//将文件流调回到要修改的密码的位置
   fprintf(pf, "%s", a.pwd);//覆盖原来的密码
   printf("密码修改成功,请登录!\n");
   Sleep(500);
   fclose(pf);
   pf = NULL;
   return;
  }
  else
  {
   printf("两次密码不匹配!请重新输入>>");
   scanf("%s", a.pwd);
   printf("请再次确认>>");
   scanf("%s", tmp);
  }
 } while (1);

}

//定位光标
void gotoxy(int x, int y)
{
 //更新光标位置
 COORD pos;
 HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle是一个Windows API函数。
 pos.X = x;
 pos.Y = y;
 SetConsoleCursorPosition(hOutput, pos);
}
//获取光标x坐标
int posx()
{
 CONSOLE_SCREEN_BUFFER_INFO ptr;
 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
 return (ptr.dwCursorPosition.X);
}
//获取光标y坐标
int posy()
{
 CONSOLE_SCREEN_BUFFER_INFO ptr;
 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
 return (ptr.dwCursorPosition.Y);
}

//输入密码
void Getpwd(char* pwd)
{
 int i = 0;
 int x, y;
 while (1)
 {
  pwd[i] = getch();//获取单个密码(字符)
  if (pwd[i] == VK_BACK && i >= 0)//如果输入的是回退键,VK_BACK是键盘的键值,ASCII码值为8
  {
   if (i > 0)//i>0说明有输入东西了,则回退前一格
   {
    i--;
    x = posx() - 1;//定位x并回退一格
    y = posy();//定位y
    gotoxy(x, y);//定位光标
    printf(" ");//将*用空格掩盖
    x = posx() - 1;//再次回退,下次输入时光标才会显示在正确的位置
    y = posy();//定位y
    gotoxy(x, y);
    continue;//然后跳过此次循环
   }
   else if (i == 0)//i==0说明没输入东西,直接跳过此次循环即可
   {
    continue;
   }
  }
  if (i >= 0 && pwd[i] != VK_RETURN && pwd[i] != VK_BACK)//输入东西了
  {
   x = posx();
   y = posy();
   gotoxy(x, y);
   printf("*");
  }
  if (i == 0 && pwd[i] == VK_RETURN)//如果没输入东西直接按回车,直接跳过此次循环,避免程序把回车当密码了
  {
   continue;
  }
  if (pwd[i] == VK_RETURN||i==MAX_PWD-2)//输入回车了或者到上限了
  {
   i++;
   pwd[i] = '\0';//结尾放'\0'
   break;
  }
  i++;
 }
}
编译之后的仿真运行结果如下图所示:


版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“星球”加入知识星球,有问必答。


点击“阅读原文”查看知识星球详情,欢迎点分享、收藏、点赞、在看。

李肖遥 公众号“技术让梦想更伟大”,作者:李肖遥,专注嵌入式,只推荐适合你的博文,干货,技术心得,与君共勉。
评论
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 196浏览
  • 随着AI大模型训练和推理对计算能力的需求呈指数级增长,AI数据中心的网络带宽需求大幅提升,推动了高速光模块的发展。光模块作为数据中心和高性能计算系统中的关键器件,主要用于提供高速和大容量的数据传输服务。 光模块提升带宽的方法有两种:1)提高每个通道的比特速率,如直接提升波特率,或者保持波特率不变,使用复杂的调制解调方式(如PAM4);2)增加通道数,如提升并行光纤数量,或采用波分复用(CWDM、LWDM)。按照传输模式,光模块可分为并行和波分两种类型,其中并行方案主要应用在中短距传输场景中成本
    hycsystembella 2025-01-25 17:24 73浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 211浏览
  • 前篇文章中『服务器散热效能不佳有解吗?』提到气冷式的服务器其散热效能对于系统稳定度是非常重要的关键因素,同时也说明了百佳泰对于散热效能能提供的协助与服务。本篇将为您延伸说明我们如何进行评估,同时也会举例在测试过程中发现的问题及改善后的数据。AI服务器的散热架构三大重点:GPU导风罩:尝试不同的GPU导风罩架构,用以集中服务器进风量,加强对GPU的降温效果。GPU托盘:改动GPU托盘架构,验证出风面积大小对GPU散热的影想程度。CPU导风罩:尝试封闭CPU导风罩间隙,集中风流,验证CPU降温效果。
    百佳泰测试实验室 2025-01-24 16:58 60浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 276浏览
  • 书接上回:【2022年终总结】阳光总在风雨后,启航2023-面包板社区  https://mbb.eet-china.com/blog/468701-438244.html 总结2019,松山湖有个欧洲小镇-面包板社区  https://mbb.eet-china.com/blog/468701-413397.html        2025年该是总结下2024年的喜怒哀乐,有个好的开始,才能更好的面对2025年即将
    liweicheng 2025-01-24 23:18 108浏览
  • 不让汽车专美于前,近年来哈雷(Harley-Davidson)和本田(Honda)等大型重型机车大厂的旗下车款皆已陆续配备车载娱乐系统与语音助理,在路上也有越来越多的普通机车车主开始使用安全帽麦克风,在骑车时透过蓝牙连线执行语音搜寻地点导航、音乐播放控制或免持拨打接听电话等各种「机车语音助理」功能。客户背景与面临的挑战以本次分享的客户个案为例,该客户是一个跨国车用语音软件供货商,过往是与车厂合作开发前装车机为主,且有着多年的「汽车语音助理」产品经验。由于客户这次是首度跨足「机车语音助理」产品,因
    百佳泰测试实验室 2025-01-24 17:00 61浏览
  • 故障现象 一辆2007款日产天籁车,搭载VQ23发动机(气缸编号如图1所示,点火顺序为1-2-3-4-5-6),累计行驶里程约为21万km。车主反映,该车起步加速时偶尔抖动,且行驶中加速无力。 图1 VQ23发动机的气缸编号 故障诊断接车后试车,发动机怠速运转平稳,但只要换挡起步,稍微踩下一点加速踏板,就能感觉到车身明显抖动。用故障检测仪检测,发动机控制模块(ECM)无故障代码存储,且无失火数据流。用虹科Pico汽车示波器测量气缸1点火信号(COP点火信号)和曲轴位置传感器信
    虹科Pico汽车示波器 2025-01-23 10:46 143浏览
  • 飞凌嵌入式基于瑞芯微RK3562系列处理器打造的FET3562J-C全国产核心板,是一款专为工业自动化及消费类电子设备设计的产品,凭借其强大的功能和灵活性,自上市以来得到了各行业客户的广泛关注。本文将详细介绍如何启动并测试RK3562J处理器的MCU,通过实际操作步骤,帮助各位工程师朋友更好地了解这款芯片。1、RK3562J处理器概述RK3562J处理器采用了4*Cortex-A53@1.8GHz+Cortex-M0@200MHz架构。其中,4个Cortex-A53核心作为主要核心,负责处理复杂
    飞凌嵌入式 2025-01-24 11:21 159浏览
  • 项目展示①正面、反面②左侧、右侧项目源码:https://mbb.eet-china.com/download/316656.html前言为什么想到要做这个小玩意呢,作为一个死宅,懒得看手机,但又想要抬头就能看见时间和天气信息,于是就做个这么个小东西,放在示波器上面正好(示波器外壳有个小槽,刚好可以卡住)功能主要有,获取国家气象局的天气信息,还有实时的温湿度,主控采用ESP32,所以后续还可以开放更多奇奇怪怪的功能,比如油价信息、股票信息之类的,反正能联网可操作性就大多了原理图、PCB、面板设计
    小恶魔owo 2025-01-25 22:09 141浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦