顯示具有 C程式語言 標籤的文章。 顯示所有文章
顯示具有 C程式語言 標籤的文章。 顯示所有文章

2008年7月22日 星期二

memory address and Little-Endian

最近看了一些有關 Big-Endian 與 Little-Endian 的資料,就寫個小程式觀察一下

編譯環境:Windows XP、minGW

#include <stdio.h>
#include <limits.h>

int main(){

long a,b[6];
printf("int max =%d\tlong max=%d\n\n",INT_MAX,LONG_MAX);
printf("address of variables(a defined first):\n");
printf("b[0]\tb[1]\tb[2]\n%u\t%u\t%u\n\n",&b[0],&b[1],&b[2]);
printf("b[4]\tb[5]\ta\n%u\t%u\t%u\n\n",&b[4],&b[5],&a);

a=0x1234abcd;
printf("about endian:\n\n");
printf("set a's value = %x\n\n",a);
unsigned char *ptr;
ptr=(unsigned char *)&a;
printf("value store in the bytes of a\n1st\t2nd\t3rd\t4th\n");
printf("%x\t%x\t%x\t%x\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+3));

return 0;
}



學到的幾點:
  1. 這個編譯環境下,int 與 long 最大值相同 ( C90 的 INT_MAX 為 32,767),所使用 byte 數也相同。
  2. 變數的記憶體位址是後宣告的在前面,而且有些沒有用到 (可見參考網頁)。
  3. 目前大部分的 CPU 都是使用 Little-Endian
參考網頁
用 C 語言窺探記憶體
http://libai.math.ncu.edu.tw/bcc16/pool/1.33.shtml

2008年6月24日 星期二

scanf("") - 參

input case:存在 input.txt 內
1

RSAEIO
2
5
RTSSKAEAGE

程式碼:
#include <stdio.h>

int main(){

freopen("input.txt","r",stdin);
char input;
while(input!='5'){
scanf("%c",&input);
printf("%d - \t %c\n",input,input);
}
return 0;
}

output:
49 - 1
10 -

10 -

82 - R
83 - S
65 - A
69 - E
73 - I
79 - O
10 -

50 - 2
10 -

53 - 5

如果把 scanf("%c",&input); 改成
  • scanf("%c ",&input); (%c 後面加空白)
  • scanf(" %c",&input); (%c 前面加空白)
  • scanf("%c\n",&input); (%c 後面加 \n )
  • scanf("\n%c",&input); (%c 前面加 \n )
會得到同樣的 output
49 - 1
82 - R
83 - S
65 - A
69 - E
73 - I
79 - O
50 - 2
53 - 5
更有趣的是,如果將 scanf() 與 gets 合用
#include <stdio.h>

int main(){
freopen("input.txt","r",stdin);
char input,line[50];
while(scanf("%c",&input)!=EOF){
printf("%d - \t %c\n",input,input);
gets(line);
printf("gets - %d\t%c\t",line[0],line[0]);
puts(line);
}
return 0;
}

output 變成:
49 - 1
gets - 0
10 -

gets - 82 R RSAEIO
50 - 2
gets - 0
53 - 5
gets - 0
82 - R
gets - 84 T TSSKAEAGE
因為 scanf() 把第一個字讀進去後,下一個字元是 '\n' ,gets() 讀取到 '\n' 就會停止讀取,並且附加一個 null character 在字串尾端,而這個字串又沒有任何字元,才會出現 line[0]=0 的狀況,如果將原本的 scanf() 改成 scanf("%c ",&input); (%c 後面加上空白),output 就會變成

49 - 1
gets - 82 R RSAEIO
50 - 2
gets - 53 5 5
82 - R
gets - 84 T TSSKAEAGE

input 裡面的 '\n' 都會被跳過,直接讀取一般的字母。

嗯,昨天我在這邊卡了將近一個小時...

2008年5月28日 星期三

char *strtok(char *str1, const char *str2)

屬於 string.h 的一個好用函式,可以將一個字串分割成一個一個的 token,第一次將 str1 傳給它以後,接著再呼叫此函式時,使用 NULL 當 str1,會自動接續到前一個 token 後面繼續讀,可以看看第一份參考資料的例子,再讀讀第二份參考資料的解釋,會比較容易瞭解,另外有一點要注意的是,str1 不是 const 型態,strtok 會修改 str1 這個字串裡面的資料,將包含有 str2 的字元改成 ' \0 ',所以接下來只能透過它所回傳的 pointer 來繼續使用這個字串,如果使用上出現問題,可以檢查自己所傳的 str1 有沒有問題 ( 剛剛 Google 時,看到某個人的血尿控訴 XDD~ )。

Example:
char *p_token,input[50]="Hamdy@Cairo Conrado@MexicoCity"
puts(input);
p_token=strtok(input,"@ \0");
strcpy(sender[0],p_token);
puts(input);
p_token=strtok(NULL,"@ \0");
strcpy(sender[1],p_token);
puts(input);
putchar('\n');
puts(sender[0]);
puts(sender[1]);

呼叫兩次 strtok() ,將所得到的 token 分別存進 sender[0] 與 sender[1] 兩個字元陣列,然後印出呼叫前與呼叫後的 input,得到的結果是
Hamdy@Cairo Conrado@MexicoCity
Hamdy
Hamdy

Hamdy
Cairo

參考資料:
http://www.cplusplus.com/reference/clibrary/cstring/strtok.html
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.14.html#strtok

2007年8月19日 星期日

qsort運用(II)

以下範例是將一個 integer 陣列做 qsort:
int compare(const void *pa,const void *pb);

int main(){
qsort(diff,num-1,sizeof(int),compare);
}

int compare(const void *pa,const void *pb){
int a,b;
a=*(int *)pa;
b=*(int *)pb;
if(a < b)
return -1;
}
else if(a==b){
return 0;
}
else{
return 1;
}
}
qsort限制比較函式中,所傳參數必須為(const void *, const void*)也就是一個 void 指標,在 compare 函式中,不能直接拿*pa和*pb來作比較,會出現有關void的blabla...錯誤,因此必須轉為其他型態,先以(int *)強制轉型為 int 指標,再利用 * 運算子來存取儲存於其中的 integer,便可成功編譯。

2007年8月6日 星期一

Using long long with MinGW

long long是 C99的標準,可以處理-((2^63)-1)~(2^63)-1的數字,正常使用方法是 %lld /u/x,但如果使用MinGW來編譯的話,必須用%I64d /u/x 才能正常使用

The printf() implementation used by MinGW (which is provided by msvcrt.dll) uses its own format specifier for 64-bit integers as documented in MSDN: http://msdn.microsoft.com/library/en-us/vccore98/HTML/_crt_size_and_distance_specification.asp. For example, %I64d will format a (decimal) long long and %I64u will format an unsigned long long.

參考資料:http://www.mingw.org/MinGWiki/index.php/long%20long

2007年7月24日 星期二

一些有關 C 語言的連結

C Standard Library:
http://www.utas.edu.au/infosys/info/documentation/C/CStdLib.html

裡面包含了C99才加入的lib,不過說明比較少,平常用的話,我比較喜歡 Eric Huss 1997年寫的

The C Reference Guide:
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/

雖然是比較舊的版本,但是說明比較詳細,有些還會附範例,我直接存到電腦裡,要寫的時候直接開起來看。

FAQ:

http://c-faq.com/

Infrequently Asked Question:
http://www.plethora.net/~seebs/faqs/c-iaq.html


裡面有些問題還挺有趣的,平時不會想到,有空可以研究研究。

2007年6月8日 星期五

qsort與struct指標運用

  1. qsort是stdlib.h裡所包含的一個函式,宣告方式請看參考資料一,qsort需要傳入四個參數,值得一提的是第三和第四個參數,第三個參數是資料型態的大小,可以用sizeof()傳進去比較好,不必手算,第四個參數是比較的函式,要求宣告方式為 int compare(const void *,const void *),傳進的參數必須為void型態,且為const,其他程式無法修改,因此必須在傳進compare後另外宣告兩個原本型態之指標 a與b,再將參數強制轉型指定給 a和b 才能使用,可以看下面的範例程式碼與參考資料中的"函數當作函數的參數"會比較容易瞭解
  2. 若宣告一個 struct abc後,想存取其中的元素時,必須用"."運算子,但如果是 struct 的指標的話,則必須使用"->"來存取裡面的元素,請看參考資料中的pointer
範例程式碼
#include <stdlib.h>

int cmplength(const void *pa,const void *pb);
/*宣告cmplength()*/

struct dics{
char word[26];
int order;
int neworder;
}dictionary[10000];
/*定義srtuct dics並宣告dictionary[10000]為 dic 型態*/

int main(){
qsort(dictionary,N,sizeof(struct dics),cmplength);
return 0;
}
/*呼叫qsort*/

int cmplength(const void *pa,const void *pb){
int la,lb,result;
struct dics *a=(struct dics *)pa;
struct dics *b=(struct dics *)pb;

la=strlen(a->word);
lb=strlen(b->word);
if(la < lb ){
return -1;
}
else{
return 1;
}
}

參考資料


The Clibrary Reference Guide :
qsort-
www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#qsort

pointer-
www.acm.uiuc.edu/webmonkeys/book/c_guide/1.4.html

函數當作函數的參數:
libai.math.ncu.edu.tw/bcc16/C/C/d0.shtml

2007年5月9日 星期三

double 型態 使用 mod 運算子

會出現錯誤,因為 mod 是取餘數(註一)

而 double 因為有小數點,只要是有理數的話,都可以 double 表示

所以一運算之下,結果沒有餘數,因此 gcc 預設會出現錯誤訊息。


本來想用 floor( )這個函數加上一些運算來代替這功能,

但floor( )只能回傳 largest interger value

所以 傳入floor( ) 的值也不能太大...

就算是unsigned long interger 也只大約 4*10^9

比起 double 可到 10^308 可說是小到不行啊...




註一:Wikipedia:Modulo_operation

2007年3月28日 星期三

scanf(" ") - 貳

程式碼貳:
#include <stdio.h>

int main(void)
{
int n=0;
char string[3];

printf("Please input:\n");


scanf("%c ",&string[0]);
/*%c後面有空白*/
scanf("%c",&string[1]);

for(n=0;n<3;n++){
printf("(%d)%c ",n,string[n]);
}

system("PAUSE");
return 0;
}

跑這個程式,兩行scanf()的效果等於scanf("%c %c")
程式會把stdin的資料暫存起來,直到另一段程式碼向它要求input

如果中間加上另一格式的輸入呢?




程式碼參:
#include <stdio.h>

int main(void)
{
int n=0,a;
char string[3];

printf("Please input:\n");


scanf("%c ",&string[0]);
scanf("%d",&a);
/*抓interger*/
scanf("%c %c",&string[1],&string[2]);

for(n=0;n<3;n++){
printf("(%d)%c ",n,string[n]);
}
printf(" a:%d",a);

system("PAUSE");
return 0;
}


Case1:
  • 輸入:a_c_12
  • 輸出:(0)a (1)c (2)1 a:1628696576
Case2:
  • 輸入:a_12_c
  • 輸出:(0)a (1) (2)c a:12
Case3:
  • 輸入:12_a_c
  • 輸出:(0)1 (1) (2)a a:2

scanf(" ") - 壹

之前在mis99板看到助教討論 scanf() 內加上空白之功用,覺得還挺有趣的,自己也來玩玩看,

程式碼壹:
#include <stdio.h>

int main(void)
{
int n=0;
char string[3];

printf("Please input:\n");

scanf("%c %c %c",&string[0],&string[1],&string[2]);
/*%c之間有空白' '*/
for(n=0;n<3;n++){
printf("(%d)%c ",n,string[n]);
}

system("PAUSE");
return 0;
}

Case1:
  • 輸入:abc
  • 輸出:(0)a (1)b (2)c
Case2:
  • 輸入:_a_b_c ( _代表空白 )
  • 輸出:(0) (1)a (2)b
Case3:
  • 輸入:a_______b____c
  • 輸出:(0)a (1)b (2)c
Case4:
  • 輸入:a___ (按enter跳行)
____b
______c
  • 輸出:(0)a (1)b (2)c

因此可以得知,scanf("")內加上空白代表跳過輸入進來的空白字元(whitespace)

直到碰上下一個輸入,Case2中,scanf()首先取得了一個空白字元,並存入陣列內,接

下來便忽略剩餘部分,直到碰上b,c