C++中如何把一個變數的值作為另一個變數的名?
剛開始自學的c++,IDE為Qt,版本為5.4.2…別說我蠢…
————————————————————8-11修改:不知道我這樣理解的需求對不對,我最近也碰到了差不多的變態需求如下:RELATION結構如下:業務需求輸入A11後對RELATION關係進行遍歷,查出如下格式的表單:查到的RELATION樹結構不一樣,輸出的表單列數還要相應變化,簡直有毒,完全不知道該怎麼做。 求大佬指點迷津。
這其實是一個好問題。Perl語言入門那本書里提到:當你問到這個問題的時候,說明你有了一些進步;而當你明白為什麼通常都不需要這個特性的時候,說明你又有了一些進步。
如果你想在運行時把一個變數的字元串內容當做另一個變數的名字,說明語言真的在運行時是通過字元串的名字來訪問變數的。而C、C++、Fortran、Rust之類的高性能語言都不這麼做,因為這相當於運行時進行查找,非常耗計算力。他們在編譯時就把變數轉換成了「固定」的地址調用,運行時並不存在變數名這個東西。
即使對於能夠這麼做的語言,也通常不鼓勵你這麼做。這是因為變數名是程序的一部分,這麼做相當於在用數據去修改程序,不但非常容易混亂,而且在大程序里這是潛在的安全性問題。
實際上你需要的是另一種東西:鍵值對的查找表,鍵是字元串,值是你需要的東西。在C++里,你可以簡單地用標準庫的std::map或者std::unordered_map。
==========
補充:允許你這麼做的語言,通常都:
- 很古老;
- 缺乏變數引用的能力,必須這麼做;
- 自己放棄治療,不打算用來構建大型程序。
我知道的有shell腳本、CMake、Perl。這裡面,shell很古老;CMake是構建腳本,不是通用語言;Perl並不鼓勵你這麼做,use strict之後也不允許你這麼做。
================
繼續補充:
現在很多語言通過在解釋器里增加優化步驟、中間代碼編譯到native code一類的技術,可以極大地改善運行效率。
不過即使如此,你原本就需要付出的代價是不能被減少的。比如這個題目里提到的運行時符號查找,即使你用C++做,也依然不能免除一次字元串hash查找。
===================
對於題目增加內容的補充:
多層不定連接的問題,顯然需要使用圖來解決。首先自己定義好節點對象和邊對象,然後也許需要一些全局的單步關係映射表(比如簡單的誰的父是誰、誰的子是誰)。剩下的事情,基本就是一些圖論的演算法問題。
反正無論如何,你也不應當使用動態產生變數來搞這種事,實際上僅僅這樣也搞不定這種事。
如果你不需要在後台解決這個問題,可以接受交互程序,那你可以使用cytoscape。這個軟體可以從兩兩關係的列表生成網路,帶有一些分析和排版功能,常用於生物學代謝調控網路的可視化和分析。
對,那是不可能的
只能用map模擬你的動態對象
要變成語言上的變數是不可能的
C++?那是不可能的,除非你有預處理程序,就像 Qt 里的 moc。
既然題主用了 Qt,那可以嘗試深入研究一下 QObject 和 Qt 的 Meta-Object System,應該可以滿足你的需求。
既然用的Qt,你可知道QObject obj;obj.setProperty("name", "hello world");QJsonObject obj;obj["name"]="hello world"QMap&
.....
裡面的name都可以換成運行時變數的值。個人比較傾向用QJson*,因為常用的數據結構都能用json來描述,配上QVariant簡直太好用了。名字在編譯後就可以給扔掉了。
不過你可以修改符號表把別的名字改成你想要的,就當那個符號原來就叫你這名字就好了。曲線救國。
只能用map模擬
感覺反射就是有點像這個特性啊。
當然這裡有個先後的問題。反射是現有成員名稱再有變數值。
不過很多可以反射的語言都是可以動態載入的。
或者也可以這樣,用C#+scriptcs 之類的腳本語言相結合。? 至少語言語法層面就及其接近一種語言了?
PhP能,它是全世界最好的語言!誰敢反駁我我打爆他的dog頭!
並沒有這樣的支持,但是不代表做不到。
我的想法是,在c編譯器上套一層預處理,利用map來實現如下功能:
- 當你在某個作用域 定義變數時,
int a = 1;
預處理器的結果是
- 如果 中第一次定義該類型變數
則先在全局作用域定義
std::map A&
然後在對應為止把代碼替換為
A["a"] = 1;
- 否則 直接替換代碼為
A["a"] = 1;
那麼如果你的變數是以下string類型的,你的問題就能得到解決。需要你實現的功能如下
2. 對於代碼片段
${var}
替換為
A["var"]
這樣做的確是很簡單的事情,但是其實會出現很多問題,基本是不可能拿來通用的,要通用得像下面這樣。
1. 命名衝突
建議把管理作用域的有關變數A進行某種編碼。比如clang可以支持UTF8,那麼你可以把A的改成某個值大於255的Unicode碼。直接加一個固定常數就可以了。
但我們還是把這個變數說成A。
這樣一來還有一個好處,我們可以用這樣的變數名。
A_(a)_b
A_(a_b)
2. 如何讓預處理識別定義變數時的作用域?
你可以根據是否處於大括弧中。根據大括弧之前的標誌(類定義,函數定義,空),來決定作用域的名字以及從屬結構。
3. 作用域要分類型。
畢竟 std :: map &
A_type_a ["a"] = ...
否則在全局變數里定義一個
A_type_a = std::map&
後再定義變數a。
索引一個變數a時,首先看變數類型 A["a"],而且有 ${A["a"]} = type_a,然後索引
A_ ${A["a"]} ["a"]
即可。
4. 作用域的從屬結構
這也會導致問題。
對於 ${var}, 你要如何去尋找它的作用域?比如說var的值是"val",我們有兩個作用域,一個是A,它是一個函數a的作用域,一個是B,是 函數a內部的一個子作用域,預處理代碼 ${var} 時,正位於在B里。你的預處理程序只能判斷當前處於作用域B中,但是如果B沒有鍵"val",那你的程序又不能往上去找A作用域以及更頂層的全局作用域了。所以你需要寫一個管理作用域的數據結構,就是一個樹狀圖,每個節點都是一個作用域,在尋找某個變數時,當前節點找不到,那麼回到上一代直系那裡繼續找,如果根節點也找不到,那麼就報錯,"Error: Variable not found"。5. 如何處理類似下面這樣的定義方式。
int *a;
const int* a;
const *int a;
首先任意類型的指針要作為一種單獨類型,比如 *int是一種,放到
//前面說過,有關作用域的變數都編碼了,現在A_(*int)應該變成幾個unicode字元。
A_(*int) : std::map&
里去,對**int,放到
A_(**int) : std::map&
但是const這個怎麼處理呢?這樣吧。
我們對於作用域A中存儲類型type_i的map,定義兩個,一個叫A_type_i,一個叫A_type_i_immutable。
舉例子, 對變數a : const int,放到
A_int_immutable : std::map&
里,而類型表則是需要註冊一下,A["a"] = "const int"。
如果是 const type_i * var, 放到A_*(type_i_immutable)
里, 類型註冊為 const type_i * 。
如果是 const * type_i var, 放到
A_(*type_i)_immutable
里, 類型註冊為 const * type_i 。
這裡也揭示了const 的本質。嘛,以上就是我針對你這個問題的一個解法。
雖然還有一些問題沒解決,比如多文件關聯導致的衝突,都需要你手動搞定,但是如果你把上面那5點都解決了,相信剩下的不會非常困難。至於預處理器,隨便拿個腳本語言跑就行了,比如Julia什麼的。
Javascript能,它是全世界最好的語言!誰敢反駁我我打爆他的dog頭!
基本上不可能,畢竟運行時不知道各個函數的入口在哪。不過可以定義函數指針搞這種騷操作。
C++不熟,下邊是C的方式
typedef void(*FuncType)(int);
FuncType A;
FuncType B;
enum {
FUNCA,
FUNCB,
};
FuncType funcArray[] = {
[FUNCA] = A,
[FUNCB] = B
};
...
int funcNumber = xxx;
funcArray[funcNumber];
顯而易見的看起來很蛋疼
嗯,這也許是一個典型:我根本就不是要把一個變數的值作為另一個變數的名,而只是想實現某個功能需求。
所以,不懂的情況下,應該問:我有一個這樣這樣的需求,應該怎麼做?而不是問:我這麼這麼做可以么?
std::map&
在程序裡面,用文件打開源文件,把所有的代碼讀入到字元串裡面,然後在字元串的main函數裡面加入一個用需要的字元串命名的變數的聲明。然後把修改好的源代碼寫入一個新的cpp文件(名字不一樣的),用system命令調用命令行g++編譯新的cpp文件。得到exe,搞定。
用 map 啊,用 map 啊,用 map 啊。
py 和 js 的變數其實也是存在類似 map 的東西里的。這個需求為什麼要實現「一個變數值是另一個變數的名?」這種東西?
可以用個map對你輸入的東西進行查找,對應的pair的第二項可以裡面可以找到指向父項的指針,或者你可以弄個hash都可以(C++ 11以上叫unorderedmap),每一個項暴露遍歷的介面就可以了,做個迭代器啥的
把變數的值列印出來,然後寫到程序里,輕鬆實現
假如說是int變數的話嘛,可以建立一個map
map&假如說第一個變數的值 cjy=」cjyyy」
那麼通過使用 a [cjy ]=2333相當於是對cjy的值對應的變數賦值啦 不知道題主是不是想實現這種功能|_?)變數值是動態運行時,變數名是靜態編譯期,C++是靜態編程語言,你說的一般是實現不了的,只能在運行時模擬,或者使用編譯期的匿名類對象(進入到了C++的魔法地帶了)。
推薦閱讀:
※如果程序語言的賦值變為左值賦予右值會更好嗎?
※想從事遊戲製作/設計行業,需要學哪些編程語言?
※C 語言程序變數作用域的實現機制是什麼?
※哪些字體適合程序員用來維護代碼?
※達到什麼樣的程度才算精通 Android開發?