2009年7月24日 星期五

好用的工具 - Google圖書的使用

應該有很多人常常想要找書但是有懶的去圖書館,但又不知道從何找起,或是該找哪本書比較好

最近我就發現了一個Google提供很有趣的服務 -> Google圖書

他提供了很多書籍的預覽(就是那種完整內頁的掃瞄但有些只有摘錄),有些書甚至是全部都可以看

雖然很多內頁有點斷斷續續的,但是也足夠看看裡面是寫什麼寫的好不好,然後就可以決定去圖書館借閱或購買

其實一開始這服務剛推出時可是跟美國的有的沒的協會槓上了~但是現在好像和解了(BalaBala~~~)

除了基本圖書功能外,在收尋的同時它還會告訴你收尋的關鍵字在書裡的第幾頁找到,點進去時就自動進入那頁,還滿人性化的!

來做個簡單的圖文介紹
首頁
http://books.google.com/books/

右邊的進階收尋可以選收尋繁體中文或其他選項










試著收尋FPGA看看













出現了很多繁體中文的圖書












再試著收尋Perl然後點進去看看
是真的內頁掃描呢!











據說裡面有數百萬的圖書,有興趣的可以看看

http://books.google.com/books/

2009年6月30日 星期二

陣列傳入副函式的筆記(C語言)

2009/7/1

今天完成了矩陣相加的程式練習,學到了如何傳陣列進副函式,下面就來講解

首先,複習一下副函式的標頭

標準格式:回傳值型態 副程式名(傳入值1的型態, 傳入值2的型態, ....)

EX. int test( int, float )

而副函式的主體則是

int test( int a, float b )
{
程式內容
return 回傳值;
}

注意!與標頭不同的地方在於標頭只需要宣告傳入型態,而主體則是要宣告型態與變數名字,才能在副程式裡使用傳進來的東西。

接下來重點來了,要如何傳陣列進入副程式呢?
這邊說明的是利用指標的方式傳入,當然可能有其它方式,但這邊就不多說了

首先要知道陣列本身就是指標的一種,而陣列的第一格就是指標的頭,用範例說明會比較清楚
EX.
A[1] = 1;
*(A+1) = 2;
printf(“%d”, A[0] );

這樣輸出的答案是2,這樣大概了解陣列等於指標的事情了吧!

所以到底該怎麼傳入副程式呢?一樣用範例來說比較容易
EX.
#include"stdio.h"
#include"stdlib.h"
void test(int*); //標頭採用整數指標的方式傳入值

int main()
{
int arr[3] = {0}, i = 0;
test( &arr[0] );
for( i = 0; i < 3 ; i++ )
printf("%d ", arr[i]);
system("pause");
}
void test(int* arr)
{
int i;
for( i = 0; i < 3 ; i++ )
arr[i] = 1;
}

最後印出的結果應該會是
1 1 1

也許有人會問說,這程式是錯的啦!副程式沒有回傳陣列給主程式啊~怎麼可能在主程式印出來會是1 1 1呢?應該是0 0 0才對吧!

聽起來好像很合理,但是別忘記了,指標是個記憶體位置,不論主程式與副程式,他的記憶體位置都是一樣的,所以在副程式裡面修改記憶體位置存的值時,就相當於主程式那邊的值也做了修改,當然這樣就不需要回傳值了。

如果我們要傳的是浮點數的陣列呢?用上面的範例做個修改就OK了
EX.

#include"stdio.h"
#include"stdlib.h"

void test(float*); //標頭採用浮點數指標的方式傳入值

int main()
{
float arr[3] = {0};
int i = 0;

test( &arr[0] );
for( i = 0 ; i < 3 ; i++ )
printf("%.2f ",arr[i]);

system("pause");
}
void test(float* arr)
{
int i;
for( i = 0; i < 3 ; i++ )
arr[i] = 1.5;
}
所以輸出就會是
1.50 1.50 1.50

這邊就要說一個簡單的概念了,記憶體分配是以一格一格來分的,傳入的資料型態會決定記憶體的使用標準格數為多少,這樣才能正確使用。舉例來說

int test[3] = {0};
test[1] = 2;
會相當於 *(test + 1 ) = 2;
這時候 test 後面的[+1]其實是代表+1套標準位元組,因為這邊是整數的型態,所以1套就代表是4bytes,若是將 int 改成 float

double test[3] = {0};
*(test + 1 ) = 2;
這時候的[+1]代表的就是加上8個位元組,因為精準浮點數在記憶體中是8個位元組為一單位

這時候應該有反應快的會想說那float 跟 int 都是4個位元組那能不能混用呢?
答案是不行的,因為浮點數跟整數的判斷方法不一樣,同樣4個位元組裡用整數去判別跟用浮點數去判別會出現不一樣的結果,所以是不能混用的。

但是不要搞混了,指標依然會是一個整數的記憶體位置,前面的資料型態只是代表該怎麼去使用資料辨別方式與記憶體空間的判讀方法。

最後就來說說那多維陣列要怎麼傳進去呢?一樣,先來看看下面矩陣相加的例子
EX.
#include"stdio.h"
#include"stdlib.h"
void arraysum( float*, float*, float* ); // 矩陣相加副程式

int i = 0, j = 0; // 跑for使用

int main()
{
float arr1[3][3] = {1}, arr2[3][3] = {1}, ans[3][3] = {0}; // arr1 2 為輸入 ans為輸出答案
arraysum( &arr1[0][0], &arr2[0][0], &ans[0][0] );

printf("\n答案為:\n");
for( i = 0; i < 3 ; i++ )
{
for( j = 0; j < 3 ; j++ )
printf("%2.1f ", ans[i][j] );//輸出相加結果

printf("\n");
}

system("PAUSE");
return 0;
}
void arraysum( float* arr1, float* arr2, float* ans )
{
for( i = 0; i < 3 ; i++ )
{
for( j = 0; j < 3 ; j++ )
ans[ i*3 + j ] = arr1[ i*3 + j ] + arr2[ i*3 + j]; //兩陣列相加
}
}

最後的輸出結果應該會是
2 2 2
2 2 2
2 2 2

我覺得最需要說明的應該就只有ans[ i*3 + j ] = arr1[ i*3 + j ] + arr2[ i*3 + j];
這句吧!

這裡就要扯到多維陣列的分配方式了

簡單說,多維陣列是為了人類方便所設計的,實際上他仍是一維的陣列。
以三維方塊陣列(int a[3][3])為例子
a[1][2] = 3 實際上會相當於 a[5] = 3的結果,以指標來看就會是*(a + 1*3 + 2 ) = 3
這樣應該可以了解吧~每一列的開始其實是接著上一列的位置繼續的,所以可以說其實它根本就是一維陣列的另外一種表示法而已,現在再回去看看上面的範例應該就可以看懂了^^

今天大概就是學習到這裡...暑假~感覺好多要學喔= =+

記錄網誌

這邊將會是我學習各種東西記錄學習筆記的地方,歡迎指教!謝謝!