寫了一個簡單的讀電路網表的程序,把每個互聯網絡的網絡名和結點提取出來,得到的信息用於邊界掃描互連網絡測試。
不同軟件公司的網表文件格式不同,以下代碼僅能讀protel的電路網表。
protel的電路網表後綴是.NET,格式如下圖:
器件信息:
網絡信息:
#include <iostream>
#include <fstream>
#include <sstream>
#include <regex>
#include <vector>
#include <string>
#include <list>
using namespace std;
int main()
{
// 一個網絡全部信息存在一個vector<string>中
vector<vector<string>> netListInfo;
// 存放器件名稱及類型
vector<vector<string>> componentName;
// 實現把網表文件一次全部讀入到string裏:
// 把網表文件讀入文件流對象
// 把文件流對象的內容給string流
// 把string流對象所保存的內容的拷貝賦給netListFileContent
ifstream inFile_NetList("C:/Users/10057/Desktop/BStest.NET");
//ifstream inFile_NetList("C:/Users/10057/Desktop/STM32.NET");
ostringstream temp;
temp << inFile_NetList.rdbuf();
string netListFileContent = temp.str();
// 定義正則表達式
regex bracketBeg("\\(");
// regex bracketEnd("\\)");
regex squareBracketBeg("\\[");
//regex squareBracketEnd("\\]");
// 結點:網絡名-引腳
//regex netInfo("^[[:alpha:]]{1,2}[[:digit:]]{1,2}-[[:digit:]]{1,2}");
// 提取器件信息
for (sregex_iterator it(netListFileContent.begin(), netListFileContent.end(), squareBracketBeg), end_it; it != end_it; ++it)
{
// 把 [ 後的200個char放入temp中
auto pos = it->suffix().str().length();
pos = pos > 200 ? 200 : pos;
string temp = it->suffix().str().substr(1, pos);
string::iterator it_str = temp.begin();
// 如果迭代器it還沒指向 ] ,就說明這個器件信息還沒讀完
vector<string> temp_vector;
int i = 0;
while (*it_str != ']')
{
string temp_string;
while (*it_str != '\n')
{
// 第0行是器件名,最後一行(第二行)是產品類型
if ((i == 0) | (i == 2))
{
char temp_char = *it_str;
temp_string = temp_string + temp_char;
}
++it_str;
}
// 如果是0、2行,就存下來
if ((i == 0) | (i == 2))
{
temp_vector.push_back(temp_string);
}
// 跳出循環,此時 *it_str = '\n',需要讓迭代器指向下一個char
++it_str;
// 行數+1
++i;
}
// 第i個器件信息已存完
componentName.push_back(temp_vector);
// 讓迭代器指向temp末尾,免得它亂跑
it_str = temp.end();
}
// 輸出器件信息
for (int i = 0; i != componentName.size(); ++i)
{
for (int j = 0; j != componentName[i].size(); ++j)
{
cout << componentName[i][j] << " ";
}
cout << endl;
}
// 提取網絡信息
for (sregex_iterator it(netListFileContent.begin(), netListFileContent.end(), bracketBeg), end_it; it != end_it; ++it)
{
// 把 ( 後的500個char放入temp中
auto pos = it->suffix().str().length();
pos = pos > 500 ? 500 : pos;
string temp = it->suffix().str().substr(1, pos);
string::iterator it_str = temp.begin();
// 如果迭代器it還沒指向 ) ,就說明這個網絡的結點還沒讀完
vector<string> temp_vector;
while (*it_str != ')')
{
// 第0行是網絡名,後面一行是一個結點
string temp_string;
while (*it_str != '\n')
{
char temp_char = *it_str;
temp_string = temp_string + temp_char;
++it_str;
}
temp_vector.push_back(temp_string);
// 跳出循環,此時 *it_str = '\n',需要讓迭代器指向下一個char
++it_str;
}
// 第i個網絡信息已存完
netListInfo.push_back(temp_vector);
// 讓迭代器指向temp末尾,免得它亂跑
it_str = temp.end();
}
// 輸出
for (int i = 0; i != netListInfo.size(); ++i)
{
for (int j = 0; j != netListInfo[i].size(); ++j)
{
cout << netListInfo[i][j] << " ";
}
cout << endl;
}
system("pause");
}
在寫這個這麼簡單的程序的時候遇到了如下問題(寫這部分就是想記錄一下調試的時候遇到的問題):
(1) vector subscript out of range(容器下標越界)。
比如:
// 初始化二維容器,沒有給容器設定初始大小,因爲我想動態往裏面添元素
vector<vector<string>> netListInfo;
// 我得到字符串之後,直接用下標訪問方式給容器賦值。
// 這句當然是錯的,因爲容器初始大小爲0,
// 直接用下標[0][0]訪問,是給一個不存在的地方賦值,是下標越界。
netListInfo[0][0]="abc";
// 解決方法:用.push_back()函數吧。
// 二維容器的話,可以先用一個一維容器vector<string>暫存你的內容,
// 然後再把這個一維容器push_back到二維容器中去。
(2)string是可以動態改變大小的(但好多博客說不可以,我覺得可以的吖)。
比如:
// 定義一個string
string temp_string ;
// 定義並初始化一個char
char temp_char = 'a';
// 把'a'添加進string
temp_string = temp_string + temp_char;
// 定義並初始化一個char
char temp_char2 = 'b';
// 把'b'添加進string
// 這不就是可以動態改變string大小嗎,
// 定義string的時候沒有初始化大小,然後再一點一點往裏面添元素
temp_string = temp_string + temp_char2;
// 注意這裏寫成temp_string += temp_char2;編譯不通過,
// 但 temp_string = temp_string + temp_char2;就是對的,我也不知道爲什麼
運行結果: