[C/C++] 計算二進位任意數含有多少個位元為1?

今天看到一個有趣的題目,就是計算二進位任意數值,其中包含了幾個1,這非常有趣,利用每個 bit 做&就可以解出這個問題了: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> #include <stdlib.h> int bitcount(unsigned int); int main(){ int count = 0, a; a = 1023; count = bitcount(a); printf("%d有%d個位元為1\n\n", a, count); system("pause"); return 0; } int bitcount(unsigned int n) { int count = 0 ; while (n) { count++ ; n &= (n - 1) ; //關鍵演算之處 } return count ; } 關鍵解法是在 n &= (n - 1) ; 這個地方,為什麼會是這樣寫呢,大家可以想看看,為什麼要 (n-1),其實可以帶數字進去跑看看就知道程式為什麼會這樣寫,這個 case 可以分作兩種,數值可能會有兩種狀況,一種是奇數,另一種就是偶數,8 代表 1000,9 代表 1001,最右邊 bit 是 1 代表奇數,剩下的都是偶數,拿9當例子帶入 while 迴圈試試看,首先將 count + 1,接下來 1001 會跟 1000 做相乘動作,就會變成 1000,接下來跑另一次 while 會變成 1000 & 0111 就會變成 0 了,退出 while 迴圈,所以結論是 (n -1) 的用意是去掉一個 1 位元 bit,就像 [xxxx10 … 0] -1 = [xxxx01 … 1] …. [Read More]

[C/C++] 指標相加 = ?or 相減 = offset

最近看到網路上討論 C/C++ 題目,某公司主管給新進人員面試的 C/C++ 考題,如下: 1 2 3 4 5 6 7 8 int main(void) { int *a,*b; a=1; b=1; printf("%d\n",a+b); return 0; } 請問上面這個題目,哪裡有出問題,這是面試官問新進人員的題目之一,看也知道這程式丟到 Dev-C++ 是不會過的,a b 都是宣告為整數指標型態,可是在 a=1 或 b=1 在 Dev-C++ 裡面是編譯不過的,但是那寫法是沒有錯的,就像你設定 a=0 或者是 a=NULL 是一樣意思,不過最好是不要這樣寫,assignment 這樣寫不太好,可以改成 a = (int )1; b = (int )1; 這樣就可以順利編譯通過,再來 printf("%d\n",a+b); 這行錯很大,指標相加會爆炸吧,如果程式這樣寫,不把 OS 搞掛,那我還會覺得懷疑呢,正確寫法是指標加上 offset(位移),這樣才是可以正確執行的,所以我們把程式改成下面: 1 2 3 4 5 6 7 8 int main(void) { int *a,*b; a = (int *)1; b = (int *)1; printf("%d\n",a+(int)b); return 0; } 最後的執行結果是 5,(int) b 就相當於 sizeof(b) 也等於 sizeof(int ) 答案都是四,所以就是 1+4 =5,指標是不能相加的,只能透過 offset 方式來讓指標指向不同 base,但是如果是指標相減,那就是求 offset 的意思喔,看一下底下例子 [Read More]

[C/C++] 實做 C 語言 substr 功能,模擬計算機功能

前天在幫學弟寫程式,寫一個計算機程式,題目如下:

寫一程式模擬簡單的計算機 每個資料列含下列的運算子中的一個及其右運算元 假設左運算元存在累加器中(初值為0) 需要函式scan_data 有2個輸出參數回傳 從資料列讀入的運算子元和右運算元 亦需函式do_next_op 執行運算子的功能 此函式有2個輸入參數(運算子和運算元) 及一個輸入/輸出參數(累加器) 有效運算子有 + 加 – 減 * 乘 / 除 ^ 次方 q 結束 此計算器在每次運算後要顯示累加器之值 一個執行範例如下 +5.0 result so far is 5.0 ^2 result so far is 25.0 /2.0 result so far is 12.5 q0 final ressult is 12.5 上面是我學弟的題目,不過他有傳一份他朋友的作業給我看,我本身不太喜歡用 scanf,我比較喜歡用 fgets,但是後來遇到要切割文字的問題,也就是 C 語言沒有 substr 取字串的函式,所以利用底下來實做:

[Read More]

[C/C++] 判斷字串是否為數字

常常在寫 C 語言,有時候想判斷輸入的是否為數字,如果不是的話,要重新輸入,所以寫一下怎麼判斷的,ptt提供了下面很多函式

isalnum ctype.h 測試某一整數值是否為’A’-‘Z’,’a’-‘z’,’0′-‘9’等文數字之一。 isalpha ctype.h 測試某一整數值是否為’A’-‘Z’,’a’-‘z’,等字母之一。 isascii ctype.h 如果ch的值判於0-127,則傳回非零整數(0x00-0x7F)。 iscntrl ctype.h 如果ch是一刪除字元或一般控制字元,則傳回非零整數(0x7F或0x00-0x1F)。 isdigit ctype.h 如果ch是一數字,則傳回非零整數。 isgraph ctype.h 如果ch是為可列印字元,則傳回非零整數。 islower ctype.h ch若為小寫字母,則傳回非零整數。 isprint ctype.h ch若為可列印字元,則傳回非零整數。其功能與isgraph相似。 ispunct ctype.h ch若為標點符號,則傳回非零整數。 isspace ctype.h ch若為空白字元或定位字元(Tab),歸位字元(Enter鍵),新列字元,垂直定位字元,換頁字元,則傳回非零整數。 isupper ctype.h ch若為大寫字母,則傳回非零整數。 isxdigit ctype.h ch若為一個十六進位數字,則傳回非零整數 用程式去判斷會更快,因為上面的函式,都是要單一字元去檢查,非常不方便,所以就寫了底下的程式

[Read More]

[C/C++] 判斷年份是否閏年

無聊幫同學寫作業,其實這還蠻簡單的,判斷閏年的方法如下 1、可以被4整除但不可以被100整除。 2、可以被400整除。 程式碼如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <stdio.h> #include <string.h> #include <stdlib.h> int leap(int year); int leap(int year) { if((year%4)==0 && (year%100)!=0 || (year%400) ==0) { printf ("%d是閏年\n",year); } else { printf ("%d不是閏年\n",year); } } int main(int argc,char *argv[]) { char *p; char year[20]; printf("請輸入您要查詢的年份『輸入exit離開』: "); while(fgets(year, sizeof(year), stdin)) { if ((p = strchr(year, '\n')) ! [Read More]

[C/C++] 如何計算陣列大小/個數

最近在寫 BCB 的時候遇到的,不過忘記之前怎麼寫的,所以又上去找了一下,發現可以利用 sizeof 這個函式,來計算陣列的個數,我去查了一下 BCB 的 manual,裡面寫的還蠻詳細的,如下 Example for sizeof operator / USE THE sizeof OPERATOR TO GET SIZES OF DIFFERENT DATA TYPES. / 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> struct st { char *name; int age; double height; }; struct st St_Array[]= { /* AN ARRAY OF structs */ { "Jr. [Read More]