编译技术实验三之编译器的构造和设计
一、实验目的:
我们将设计多个不同的综合实验项目提供给学生选择。(如:LL(1)文法自动生成语法分析程序的设计;单词的自动识别与智能纠错;语言的程序编辑器;数学计算式的识别等)学生可在这些项目中选择1个项目,体现了实验技术的全面性和先进性。综合实验将以编译原理、技术为基础,结合前期课程,加上实际需求和学生自己的设计才能完成。这些前期课程接口包括离散数学、数据结构、C++程序设计语言、操作系统、汇编语言、数据库原理等。通过综合实验使学生设计制作出有一定水平的编译程序,使学生更好地掌握编译原理和基本技术
设计一个小型编译器。
二、实验内容及原理
以高级程序设计语言的编译原理和基本技术,加上实际编辑程序过程的需求,把综合实验项目分层次展开,经过小组学生的分工与合作加上创意才能完成。
设计的语言上可以使用编译性语言,也可以使用解释性语言。实验的结果是一个编译器或一个综合编译技术的应用软件。
三、实验过程原始数据记录
主要结构:
char terminal[50]; //终结符
set<string>Noter; //非终结符
vector<string>nt;
vector<string>t;
int tNum;//终结符个数
int nNum;//非终结符个数
string Production[50] = { "" };//产生式
string ReProduction[50] = { "" };//新产生式
int ProNum;//产生式个数
int ReProNum = 0;//新产生式个数
vector<pair<string, string>>I;//所有项目
vector<pair<string, string>>closure;//项目的闭包
vector<pair<string, string>>project;
vector<pair<string, string>>Start;
map<pair<int, string>, int>table;
string str;
unordered_map<int, vector<pair<int, string>>>LRtable;
unordered_map<int, vector<pair<string, int>>>state;
string lrtable[100][100] = { "-1" };
vector<int>sq;//状态栈
vector<char>inputStr, sign;//全体字符以及符号栈
主要函数:
void Gramma()
void GrammaF()
void get_project()
vector<pair<string, string>> get_closure(const vector<pair<string, string>>& pro)
vector<pair<string, string>> Goto(const vector<pair<string, string>>& pro, const string& flag)
vector<vector<pair<string, string>>> get_all_closure(const vector<pair<string, string>>& pro)
int get_num(string s)
int getChar(char ch)
int get_rnext(string s)
void get_LRTable(vector<vector<pair<string, string>>>allclosure)
void init()
string outPut(int i)
void check()
void analyst()
源代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<unordered_map>
#include<iomanip>
#include<map>
using namespace std;char terminal[50]; //终结符
set<string>Noter; //非终结符
vector<string>nt;
vector<string>t;
int tNum; //终结符个数
int nNum; //非终结符个数
string Production[50] = { "" }; //产生式
string ReProduction[50] = { "" }; //新产生式
int ProNum; //产生式个数
int ReProNum = 0; //新产生式个数
vector<pair<string, string>>I; //所有项目
vector<pair<string, string>>closure; //项目闭包
vector<pair<string, string>>project;
vector<pair<string, string>>Start;
map<pair<int, string>, int>table;
string str;
unordered_map<int, vector<pair<int, string>>>LRtable;
string lrtable[100][100] = { "-1" };
unordered_map<int, vector<pair<string, int>>>state;
vector<int>sq;//状态栈
vector<char>inputStr, sign;//全体字符以及符号栈void Gramma() {cout << "--------------------------" << endl;cout << "请输入终结符的个数:";cin >> tNum;cout << "请输入终结符:" << endl;for (int i = 0; i < tNum; i++) {cin >> terminal[i];string st;st.push_back(terminal[i]);t.push_back(st);}cout << "请输入非终结符的个数:";cin >> nNum;cout << "请输入非终结符:" << endl;for (int i = 0; i < nNum; i++) {string s;cin >> s;Noter.insert(s);nt.push_back(s);t.push_back(s);}cout << "请输入产生式的个数:";cin >> ProNum;cout << "请输入产生式:" << endl;for (int i = 0; i < ProNum; i++) {cin >> Production[i];}
}void GrammaF() {int x = 0, z = 1;//x为第z个产生式的第x个字符for (int i = 0; i < ProNum; i++) {x = 3;int k = 0;while (x < Production[i].size()) {for (k = 0; k < 3; k++) {//获取产生式的左部以及箭头ReProduction[z] += Production[i][k];}while (x < Production[i].size() && Production[i][x] != '|') {ReProduction[z] += Production[i][x];x++;}z++;x++;}}string s = ReProduction[1].substr(0, 1) + "'";str = s;ReProduction[0] = s + "->" + ReProduction[1].substr(0, 1);t.push_back(s);Noter.insert(s);nt.push_back(s);nNum++;ReProNum = z;project.push_back({ s,ReProduction[1].substr(0, 1) });for (int i = 1; i < ReProNum; i++) {string fir = ReProduction[i].substr(0, 1);string sec = ReProduction[i].substr(3);project.push_back({ fir,sec });}
}void get_project() {I.push_back({ ReProduction[0].substr(0,2),"." + ReProduction[0].substr(4) });Start.push_back({ ReProduction[0].substr(0,2),"." + ReProduction[0].substr(4) });I.push_back({ ReProduction[0].substr(0,2),ReProduction[0].substr(4) + "." });for (int i = 1; i < ReProNum; i++) {string First = "";First += ReProduction[i][0];string Second = ReProduction[i].substr(3);for (int j = 0; j <= Second.size(); j++) {string tmp = Second;tmp.insert(j, ".");I.push_back({ First,tmp });}}for (int i = 0; i < I.size(); i++) {cout << I[i].first << " " << I[i].second << endl;}
}vector<pair<string, string>> get_closure(const vector<pair<string, string>>& pro) {vector<pair<string, string>>closure = pro;auto Size = closure.size();string first;for (int i = 0; i < Size; i++) {auto pos = closure[i].second.find(".");if (pos == string::npos) {cout << "error" << endl;cout << closure[i].first << "-->>" << closure[i].second << endl;return closure;}auto c = closure[i].second[pos + 1];first.push_back(c);if (Noter.find(first) == Noter.end()) {first.clear();continue;}for (int i = 0; i < project.size(); i++) {if (first == project[i].first) {auto second = project[i].second;second.insert(0, ".");bool flag = 0;for (int j = 0; j < Size; j++) {if (second == closure[j].second) {flag = 1;break;}}if (flag == 0) {closure.push_back({ first,second });}}}first.clear();Size = closure.size();}return closure;
}vector<pair<string, string>> Goto(const vector<pair<string, string>>& pro, const string& f) {vector<pair<string, string>>nextJ;for (int i = 0; i < pro.size(); i++) {auto p = pro[i].second.find(".");if (p == string::npos) {cout << "error" << endl;return nextJ;}else {auto ch = pro[i].second[p + 1];if (ch == '\0')continue;string temp;temp.push_back(ch);if (temp != f)continue;else{auto first = pro[i].first;auto second = pro[i].second;second[p] = second[p + 1];second[p + 1] = '.';nextJ.push_back({ first, second });}}}auto T = nextJ;nextJ = get_closure(T);return nextJ;
}vector<vector<pair<string, string>>> get_all_closure(const vector<pair<string, string>>& pro) {vector<vector<pair<string, string>>>allclosure;allclosure.push_back(pro);auto size = allclosure.size();for (int i = 0; i < size; i++) {set<string>flag;auto len = allclosure[i].size();for (int j = 0; j < len; j++) {auto pos = allclosure[i][j].second.find(".");if (pos == string::npos) {cout << "error" << endl;return allclosure;}else {auto ch = allclosure[i][j].second[pos + 1];if (ch == '\0') {continue;}string str;str.push_back(ch);flag.insert(str);}}for (set<string>::iterator it = flag.begin(); it != flag.end(); it++) {auto closure = Goto(allclosure[i], *it);if (closure.size() == 0)continue;else {bool stop = 0;for (int j = 0; j < size; j++) {if (allclosure[j] == closure) {table.insert({ {i,*it},j });stop = 1;break;}}if (stop == 1) {continue;}allclosure.push_back(closure);int sz = allclosure.size() - 1;table.insert({ {i,*it}, sz });}}size = allclosure.size();}return allclosure;
}int get_num(string s) {for (int i = 0; i < t.size(); i++) {if (t[i] == s) {return i;}}return -1;
}int get_rnext(string s) {for (int i = 0; i < project.size(); i++) {if (s == project[i].second) {return i;}}return -1;
}void get_LRTable(vector<vector<pair<string, string>>>allclosure) {for (int i = 0; i < allclosure.size(); i++) {for (int j = 0; j < t.size(); j++) {lrtable[i][j] = "-1";}}vector<pair<int, int>>nums;bool st[100] = { false };int acc;for (map<pair<int, string>, int>::iterator it = table.begin(); it != table.end(); it++){int from = it->first.first;int next = it->second;string s = it->first.second;auto Inext = allclosure[next];auto Ifrom = allclosure[from];lrtable[from][get_num(s)] = "s" + to_string(next);for (int j = 0; j < Ifrom.size(); j++) {auto pos = Ifrom[j].second.find(".");if (pos == Ifrom[j].second.size() - 1 && Ifrom[j].first != str) {int rnext = get_rnext(Ifrom[j].second.substr(0, Ifrom[j].second.size() - 1));nums.push_back({ from,rnext });}if (pos == Ifrom[j].second.size() - 1 && Ifrom[j].first == str) {acc = from;}}st[from] = true;}lrtable[acc][get_num("#")] = "acc";for (int i = 0; i < allclosure.size(); i++) {if (!st[i]) {for (int j = 0; j < allclosure[i].size(); j++) {auto pos = allclosure[i][j].second.find(".");if (pos == allclosure[i][j].second.size() - 1) {int rnext = get_rnext(allclosure[i][j].second.substr(0, allclosure[i][j].second.size() - 1));nums.push_back({ i,rnext });}}}}for (int i = 0; i < nums.size(); i++) {int f = nums[i].first, rnext = nums[i].second;for (int j = 0; j < tNum; j++) {lrtable[f][j] = "r" + to_string(rnext);}}for (int i = 0; i < allclosure.size(); i++) {for (int j = 0; j < t.size(); j++) {if (lrtable[i][j] != "-1") {LRtable[i].push_back({ j,lrtable[i][j] });}}}
}int getChar(char ch) {string s;s.push_back(ch);for (int i = 0; i < t.size(); i++) {if (t[i] == s)return i;}return -1;
}
void init() {for (map<pair<int, string>, int>::iterator it = table.begin(); it != table.end(); it++){state[it->first.first].push_back({ it->first.second,it->second });}
}string outPut(int i) {char buf[100];int count = 0;if (i == 0) {string str;for (vector<int>::iterator it = sq.begin(); it != sq.end(); it++) {int c = *it;str += to_string(c);}return str;}else if (i == 1) {for (vector<char>::iterator it = sign.begin(); it != sign.end(); it++) {buf[count++] = *it;}}else {for (vector<char>::iterator it = inputStr.begin(); it != inputStr.end(); it++) {buf[count++] = *it;}}buf[count] = '\0';string str(buf);return str;
}
void check() {int step = 1;sign.push_back('#');sq.push_back(0);cout << setw(10) << "步骤" << setw(10) << "状态栈" << setw(10) << "符号栈" << setw(10) << "输入串" << setw(25) << "动作说明" << endl;int s = 0;int oldstatus;char ch = inputStr.front();int c = getChar(ch);if (c == -1) {cout << "error" << endl;return;}while (lrtable[s][getChar(ch)] != "acc") {string sstr = lrtable[s][getChar(ch)];int s1 = 0;for (int i = 1; i < sstr.size(); i++) {s1 = s1 * 10 + (sstr[i] - '0');}s = s1;if (sstr == "-1") {cout << "error" << endl;return;}if (sstr.substr(0, 1) == "s") {cout << setw(10) << step << setw(10) << outPut(0) << setw(10) << outPut(1) << setw(10) << outPut(2) << setw(10) << "A" << "CTION[" << sq.back() << "," << ch << "]=S" << s << "," << "状态" << s << "入栈" << endl;sign.push_back(ch);inputStr.erase(inputStr.begin());sq.push_back(s);}else if (sstr.substr(0, 1) == "r") {string formu = ReProduction[s];string stop = project[s].first;int strlen = formu.size();int popnum = strlen - 3;int i = 0;for (vector<int>::reverse_iterator it = sq.rbegin(); it != sq.rend(); it++) {i++;if (i == popnum + 1) {oldstatus = *it;break;}}int r = s;for (int i = 0; i < state[oldstatus].size(); i++) {if (state[oldstatus][i].first == stop) {s = state[oldstatus][i].second;}}cout << setw(10) << step << setw(10) << outPut(0) << setw(10) << outPut(1) << setw(10) << outPut(2) << setw(10) << "r" << r << (string)":" + Production[r] + (string)"归约,GOTO{" << oldstatus << "," << 'E' << ")=" << s << "入栈" << endl;for (int i = 0; i < popnum; i++) {sq.pop_back();sign.pop_back();}sq.push_back(s);sign.push_back(stop[0]);}step++;s = sq.back();ch = inputStr.front();}cout << setw(10) << step << setw(10) << outPut(0) << setw(10) << outPut(1) << setw(10) << outPut(2) << setw(10) << "A" << "cc:分析成功" << endl;
}
void analyst() {init();string s;cout << "请输入字符串(+,-,*,/,E,i,(,),#):" << endl;cin >> s;for (int i = 0; i < s.size(); i++)inputStr.push_back(s[i]);if (inputStr.back() != '#')inputStr.push_back('#');check();
}int main() {Gramma();GrammaF();get_project();auto S = get_closure(Start);auto allclosure = get_all_closure(S);for (int i = 0; i < allclosure.size(); i++) {cout << "I" << i << ":" << endl;for (int j = 0; j < allclosure[i].size(); j++) {cout << allclosure[i][j].first << "->" << allclosure[i][j].second << endl;}}cout << table.size() << endl;cout << "\n转换关系:" << endl;for (map<pair<int, string>, int>::iterator it = table.begin(); it != table.end(); it++){cout << "[ " << it->first.first << ", " << it->first.second << " ] -> " << it->second << endl;}get_LRTable(allclosure);for (int i = 0; i < project.size(); i++) {cout << ReProduction[i] << endl;}for (int i = 0; i < allclosure.size(); i++) {for (int j = 0; j < t.size(); j++) {cout << lrtable[i][j] << " ";}cout << endl;}analyst();}
结果:
语法分析:
生成项目集
拓广文法
生成LR分析表
四、实验总结
通过这个实验,我认识到编译器的重要性和复杂性。在设计和构造编译器的过程中,我需要考虑语法分析、词法分析、语义分析等多个环节,同时还要处理错误处理、优化等问题。在实验中,我需要将学习到的几个章节的理论知识转化为实际可执行的代码。我学会了如何根据给定的文法和规则构建语法分析树,如何设计和实现词法分析器,如何进行语义分析和中间代码生成等。在设计和构造编译器的过程中,我遇到了很多困难和挑战,需要不断地debug,这有利于巩固了我的编程能力,提高我的设计思维和解决问题的能力。
相关文章:

编译技术实验三之编译器的构造和设计
一、实验目的: 我们将设计多个不同的综合实验项目提供给学生选择。(如:LL(1)文法自动生成语法分析程序的设计;单词的自动识别与智能纠错;语言的程序编辑器;数学计算式的识别等)学生可在这些项目中选择1个项…...

数据挖掘——数据预处理
数据挖掘——数据预处理 数据预处理数据预处理 ——主要任务数据清洗如何处理丢失的数据如何处理噪声数据如何处理不一致数据 数据集成相关分析相关系数(也成为皮尔逊相关系数)协方差 数据规约降维法:PCA主成分分析降数据——抽样法数据压缩 数据预处理 数据预处理…...

ECharts饼图下钻
背景:项目上需要对Echarts饼图进行功能定制,实现点击颜色块,下钻显示下一层级占比说明:饼图实现点击下钻/面包屑返回的功能 数据结构 [{name: a,value: 1,children: [...]},... ]点击下钻 // 为图表绑定点击事件(需要…...

【RK3568笔记】Android修改开机动画
概述 Android 的开机动画是由一系列连续的 PNG 图片作为帧组成的动画形式,不是一张 GIF 图片。将各帧 PNG 图片以压缩方式进行保存(压缩方式要求是存储压缩),并将保存的文件名命名为 bootanimation.zip,这个 bootanim…...

嵌入式技术之Linux(Ubuntu) 一
一、Linux入门 1.硬件和操作系统以及用户的关系 一个传感器,获得数据后,需要向服务器发送数据。传感器传数据给上位机。 上位机需要一个程序来接收数据,那么这个上位机是什么机器? 我们的笔记本电脑就可以当成上位机。 两个手…...
代码随想录day39 动态规划7
打家劫舍 题目:198.打家劫舍 213.打家劫舍II 337.打家劫舍III 需要重做:全部 198.打家劫舍 思路:第i个房子偷与不偷,取决于第i-2个房子和第i-1个房子 注意:注意下标的一致性。现在的下标含义是房子的下标&#x…...
ESP32-S3模组上实现低功耗(5)
接前一篇文章:ESP32-S3模组上实现低功耗(4) 本文内容参考: 系统低功耗模式介绍 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 电源管理 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档...
PDF转文本以及转图片:itextpdf
文章目录 🐒个人主页:信计2102罗铠威🏅JavaEE系列专栏📖前言:🎀 1. itextpdf1.1导入itextpdf的maven依赖1.2 提取文本代码1.3 pdf转换成图片代码(本地图片地址还是线上PDF的URL地址均支持&#…...

AnaConda下载PyTorch慢的解决办法
使用Conda下载比较慢,改为pip下载 复制下载链接到迅雷下载 激活虚拟环境,安装whl,即可安装成功 pip install D:\openai.wiki\ChatGLM2-6B\torch-2.4.1cu121-cp38-cp38-win_amd64.whl...

移动端自动化测试Appium-java
一、Appium的简介 移动端的自动化测试框架 模拟人的操作进行功能自动化常用于功能测试、兼容性测试 跨平台的自动化测试 二、Appium的原理 核心是web服务器,接受客户端的连接,接收客户端的命令,在手机设备上执行命令,收集命令…...

IO: 作业:Day1
思维导图 main.c #include"student.h" int main(int argc, const char *argv[]) { stuPtr hcreat(); int n0; add_node(h); add_node(h); add_node(h); show(h); save(h,"student.txt"); stuPtr ptrc…...

ue5 替换角色的骨骼网格体和动画蓝图
一开始动画蓝图,骨骼网格体都是用的女性角色 现在把它换成男性 编译 保存 运行 把动画类换成ABP_Manny 进入ABP_Manny中 进入到idle 找到这个拖进来 编译 就变成站着端枪 运行一下,没有问题...
el-cascader 树状选择-点击父级禁用子级
背景:项目上需要实现树状选择,点击父级禁用子级的功能,element组件本身没有该配置项说明:需要实现几个功能点:点击父级禁用子级;再次点击取消禁用;仅回填所选级;上下级不关联实现代码…...

AWS re:Invent 的创新技术
本月早些时候,Amazon 于 12 月 1 日至 5 日在内华达州拉斯维加斯举行了为期 5 天的 re:Invent 大会。如果您从未参加过 re:Invent 会议,那么最能描述它的词是“巨大”——不仅从与会者人数(60,000 人)来看&…...

PHP7和PHP8的最佳实践
php 7 和 php 8 的最佳实践包括:使用类型提示以避免运行时错误;利用命名空间组织代码并避免命名冲突;采用命名参数、联合类型等新特性增强可读性;用错误处理优雅地处理异常;关注性能优化,如避免全局变量和选…...
Debian、Ubuntu 22.04和ubuntu 24.04国内镜像源(包括 docker 源)
Debian 更换国内清华源 1、备份原文件mv /etc/apt/sources.list /etc/apt/sources.list.old 2、写入新源,以下是 Debian 11 的: cat > /etc/apt/sources.list << EOF deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib…...

点亮一个esp32 的led
最近入了一个ESP32 兄弟们,这玩意还可以,买来肯定是给它点亮啊对吧 我就是点灯侠🎇 😭千万不要不接天线啊,不然你会一直找不到你的wifi 1.点灯第一步你得有IDE Arduino 就是这个绿东西 可是怎么下载安装呢ÿ…...
C++ shared_ptr进一步认知,为什么引用计数>2退出作用域都可以调用析构
1.使用智能指针需要#include <memeroy> 2.上代码: #include <memory> #include <iostream> using namespace std; struct lifePeriod {lifePeriod():a(1){cout << "无参构造!" << endl;}virtual ~lifePeriod(…...
JavaScript代码片段二
见过不少人、经过不少事、也吃过不少苦,感悟世事无常、人心多变,靠着回忆将往事串珠成链,聊聊感情、谈谈发展,我慢慢写、你一点一点看...... JavaScript统计文字个数、特殊字符转义、动态插入js代码、身份证验证 统计文字个数 f…...

【计算机视觉】单目深度估计模型-Depth Anything-V2
概述 本篇将简单介绍Depth Anything V2单目深度估计模型,该模型旨在解决现有的深度估计模型在处理复杂场景、透明或反射物体时的性能限制。与前一代模型相比,V2版本通过采用合成图像训练、增加教师模型容量,并利用大规模伪标签现实数据进行学…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...

GC1808:高性能音频ADC的卓越之选
在音频处理领域,高质量的音频模数转换器(ADC)是实现精准音频数字化的关键。GC1808,一款96kHz、24bit立体声音频ADC,以其卓越的性能和高性价比脱颖而出,成为众多音频设备制造商的理想选择。 GC1808集成了64倍…...