2015年7月16日 星期四

[C] 二維陣列(char)




1) you can use 2D char array in this way
char name[5][100];
each line in the 2D array is an array of char with size = 100
for(i=0;i<5;i++)  
{
    printf(" Enter a name which you want to register\n");  
    scanf("%99s",names[i]);
}
2) You can use array of pointers in this way
char *name[5];
each element in the array is a pointer to a string (char array). you have to assign each pointer in the array to a memory space before you call scanf()
for(i=0;i<5;i++)  
{
    names[i]=malloc(100);  
    printf(" Enter a name which you want to register\n");  
    scanf("%99s",names[i]);
}
3) if you compile with gcc and gcc version >2.7 then your scanf() can allocate memory by using "%ms" instead of "%s"
char *name[5];
for(i=0;i<5;i++)  
{
    printf(" Enter a name which you want to register\n");  
    scanf("%ms",&names[i]);
}

文章出處:http://stackoverflow.com/questions/17466563/two-dimensional-array-of-characters-in-c





2015年6月7日 星期日

[C] %s 的使用



當使用 %s 於 printf 和 scanf 時,  對應的argument 必須是 char * , 如下列例子:

char *str_constant = "I point to a string literal";
char str_buf[] = "I am an array of char initialized with a string literal";

printf("string literal = %s\n", "I am a string literal");
printf("str_constant = %s\n", str_constant);
printf("str_buf = %s\n", str_buf);

scanf("%55s", str_buf);

值得注意的是, 看以下小程序,

#define  max  5
----------------------
        char *name[max];

int i;
for (i = 0; i < max; i++){
name[i] = malloc(3);
scanf("%3s", name[i]);
printf("%s\n", name[i]);
                free(name[i]);
}

// 使用scanf前必須用使用 malloc 為每個char * pointer 動態分配位置記存字符
// %3s , 即指只讀取讀入字串的前3個字符





2015年6月1日 星期一

[C] auto 與 register

C語言變數儲存等級(storage class),一共有四種:auto、extern、register、static,我們最常用的是auto,然而卻很少人用它來宣告變數,怎麼說起來很奇怪?因為編譯器自動把我們宣告的變數自動設成auto,只是我們都忽略有這回事。看個例子:
1
2
int i;
auto int i;
以上兩者的意義相同,auto變數在程式執行的時候,OS配置記憶體空間給這個變數。
現在我們來討論register變數,跟auto變數一樣,register變數在程式執行的時候,OS會配置記憶體空間給此變數,但跟auto變數不一樣的是,register變數會被配置到CPU中的暫存器(register),而auto變數會被配置到RAM中,它們的差異在於存取速度,前者(register)快於後者(RAM),那到底快多少呢?我看到網路上都說「快」,但到底有多快?我們實際來測試看看吧~
1
for(register int i=0;i<1000000000;i++);
我舉我們最常使用的for迴圈,讓它空轉10的9次方次,我的電腦執行時間為:
2.98905059209784340000
請按任意鍵繼續 . . .
而去掉register宣告,結果則為:
3.03692563877645630000
請按任意鍵繼續 . . .
雖然看起來只有差0.05秒左右,但你若宣告long long的話,差異就更明顯了。不過當今電腦速度這麼快,誰會在乎這麼一點時間呢?
結論就是驗證了儲存裝置的層級:register存取速度優於RAM。前者量少而貴但相對較快,後者則相反。

文章出處 : https://cg2010studio.wordpress.com/2011/04/08/register-variable/

[C] static 與 extern



static變數,當變數有宣告時加上static限定時,一但變數生成,它就會一直存在記憶體之中,即使函式執行完畢,變數也不會消失,例如: 


#include <stdio.h>

void count(void);

int main(void) {
    int i;
    for(i = 0; i < 10; i++) {
        count();     
    }

    return 0;
}

void count(void) { 
    static int c = 1; 
    printf("%d\\n", c); 
    c++; 
}

執行結果:
1
2
3
4
5
6
7
8
9
10

雖然變數c是在count()函式中宣告的,但是函式結束後,變數仍然存在,它會直到程式執行結束時才消失,雖然變數一直存在,但由於它是被宣告在函式之 中,所以函式之外仍無法存取static變數。 

您可以宣告全域static變數,其在程式執行期間一直存在,但在一個原始程式文件中宣告全域static變數,還表示其可以存取的範圍僅限於該原始程式文件之中,您也可以將函式宣告為static:
static void some() {
    ...
}

一個static函式表示,其可以呼叫的範圍限於該原始碼文件之中,如果您有一些函式僅想在該原始程式文件之中使用,則可以宣告為static,這也可以避免與其他人寫的函式名稱衝突的問題。

extern可以聲明變數會在其它的位置被定義,這個位置可能是在同一份文件之中,或是在其它文件之中,例如: 
  • some.c
double someVar = 1000;
// 其它定義 ...


  • main.c
#include <stdio.h>

int main(void) {
    extern double someVar;
    
    printf("%f\\n", someVar);
    
    return 0;
}

在main.c中實際上並沒有宣告someVar,extern指出someVar是在其它位置被定義,編譯器會試圖在其它位置或文件中找出 someVar的定義,結果在some.c中找到,因而會顯示結果為1000,要注意的是,extern聲明someVar在其它位置被定義,如果您 在使用extern時同時指定其值,則視為在該位置定義變數,結果就引發重覆定義錯誤,例如:
#include <stdio.h>

int main(void) {
  extern double someVar = 100;
 // error, `someVar' has both `extern' and initializer     
    ...
    return 0;
}

您必須先聲明extern找到變數,再重新指定其值,這麼使用才是正確的:


#include <stdio.h>

int main(void) {
    extern double someVar;
    
someVar = 100;
    ...
    return 0;
}

文章出處 :http://openhome.cc/Gossip/CGossip/Scope.html

[C] 可視範圍(scope)


在C中,談到可視範圍(scope)可分為許多層次,也可以談到很複雜,在這邊先談談

-「全域變數」(Global variable)
-「區域變數」(Local variable)
-「區塊變數」(Block variable)。 

全域變數是指直接宣告在(主)函式之外的變數,這個變數在整個程式之中都「看」得它的存在,而可以呼叫使用,例如:
const double PI = 3.14159; 

doule area(double r) { 
    return r * r * PI; 
}

int main(void) { 
    // ..... 
    return 0; 
} 

在這個例子中,PI這個變數可以被主函式main()與副函式area()來使用,通常全域變數是用來定義一些常數,初學者不應為了方便而將所有的變數都 設定為全域變數,否則將來一定會發生變數名稱管理上的問題,全域變數的生命週期始於程式開始之時,終止於程式結束之時。 

區域變數是指宣告在函式之內的變數,或是宣告在參數列之前的變數,它的可視範圍只在宣告它的函式區塊之中,其它的函式不可以使用該變數,例如在上例的主函 式中,您不可以直接對area()函式中的變數r作出存取的動作,區域變數的生命週期開始於函式被呼叫之後,終止於函式執行完畢之時。 

區塊變數是指宣告在某個陳述區塊之中的變數,例如while迴圈區塊中,或是for迴圈區塊,例如下面的變數i在迴圈結束之後,就會自動消失:
while(...) {
    int i = 0;
    // ....
}

當一可視範圍大的變數與可視範圍小的變數發生同名狀況時,可視範圍小的變數會暫時覆蓋可視範圍大的變數,稱之為「變數覆蓋」,例如: 
int num = 10;
int i;
for(i = 0; i < 100; i++)  {
    int num = 20;
    // ...
}
printf("%d", num);

這個程式最後顯示的 num 值仍是10,當執行迴圈時,迴圈內的 num 變數作用將覆蓋迴圈外的 num 變數;同樣的作用發生於全域變數與區域變數發生同名的時候。 



文章來源:http://openhome.cc/Gossip/CGossip/Scope.html

[C] 列舉(enum)


  • 列舉型態(enumeration)是一種特殊的常數定義方式。
  • 列舉型態可使我們定義自己的資料型態,及設定其值。
  • 程式的可讀性提高。
  • 列舉型態的定義及宣告方式格式如下:


定義1:

  1. enum color
  2. {
  3.   red,
  4.   blue,
  5.   green,
  6. };
  7. enum color coat, hat;      


定義2:
  1. enum color        /*宣告列舉型態color */
  2. {
  3.   red,
  4.   blue,
  5.   green,
  6. } coat , hat; 


定義3:

使用typedef

  1. typedef enum{
  2.   All,
  3.   January,
  4.   February,
  5.   March,
  6.   April,
  7.   May
  8. }month;

  9. month Month;


============================================================

Example 1 :




===================================================================

Remark:

enum 是英文 enumerate(列舉,枚舉) 的縮寫
效果是列舉出多個'常數',並設定數值。
例子:
  enum{
    stop,   
    stand,
    
    run
  };
大括號中每一個元素稱為列舉元,每個列舉元其實儲存著一個整數。
如果沒設定數值,預設是從0開始遞增。(stop=0 ; stand=1 ; run=2)
如果要設定數值,可以這樣打
  enum{
    stop=5,  
    stand,
 
    run
 };
這樣就會變成 (stop=5 ; stand=6 ; run=7)
也可以這樣用
  enum{
    stop=5,
    stand,
    run=2
  };
這樣會變成 (stop=5 ; stand=6 ; run=2)

參考網址: http://bodscar.pixnet.net/blog/post/61204511-%E8%AA%AA%E6%98%8E-typedef-enum