[C/C++] C語言切割字串函式 strsep,分析 URL GET 參數

今天來簡介 UNIX 內建的 strsep 函式,這在 Windows Dev-C++ 是沒有支援的,在寫 UNIX 分析字串常常需要利用到此函式,大家可以 man strsep 來看如何使用 strsep,假設我們要分析 URL Get 字串:user_command=appleboy&test=1&test2=2,就可以利用兩次 strsep 函式,將字串全部分離,取的個別的 name, value。strsep(stringp, delim) 第一個參數傳入需要分析的字串,第二個參數傳入 delim 符號,假設 stringp 為 NULL 字串,則函式會回傳 NULL,換句話說,strsep 會找到 stringp 字串第一個出現 delim 符號,並將其取代為 \0 符號,然後將 stringp 更新指向到 \0 符號的下一個字串,strsep() function 回傳原來的 stringp 指標。看上面文字敘述,好像不太瞭解,沒關係,底下是 UNIX strsep.c 的原始碼:

 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
36
37
38
39
/*
 * Get next token from string *stringp, where tokens are possibly-empty
 * strings separated by characters from delim.
 *
 * Writes NULs into the string at *stringp to end tokens.
 * delim need not remain constant from call to call.
 * On return, *stringp points past the last NUL written (if there might
 * be further tokens), or is NULL (if there are definitely no more tokens).
 *
 * If *stringp is NULL, strsep returns NULL.
 */
char *
strsep(stringp, delim)
    char **stringp;
    const char *delim;
{
    char *s;
    const char *spanp;
    int c, sc;
    char *tok;

    if ((s = *stringp) == NULL)
        return (NULL);
    for (tok = s;;) {
        c = *s++;
        spanp = delim;
        do {
            if ((sc = *spanp++) == c) {
                if (c == 0)
                    s = NULL;
                else
                    s[-1] = 0;
                *stringp = s;
                return (tok);
            }
        } while (sc != 0);
    }
    /* NOTREACHED */
}
[Read More]

[C/C++] strpbrk 在字串中找尋指定的符號或字母

繼上一篇:『[C/C++] 切割字串函數:strtok, Network mac address 分割』,內容寫到 Microsoft 用到 strpbrk 來找尋字串中特定符號,並且回傳該符號的位址,用法如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include "string.h" #include "stdlib.h" #include "stdio.h" int main () { char str[] = "This is a sample string"; char key[] = "aeiou"; char * pch; printf ("Vowels in '%s': ",str); pch = strpbrk (str, key); while (pch != NULL) { printf ("%c " , *pch); /* 也可以直接輸出字串 */ printf("\noutput=%s\n", pch); pch = strpbrk (pch+1,key); } printf ("\n"); system("pause"); return 0; } 輸出結果: 我們看一下 /usr/src/lib/libc/string/strpbrk. [Read More]

[C/C++] 切割字串函數:strtok, Network mac address 分割

今天寫了 strtok 的範例:『如何分離網路 mac address』程式碼如下,大家一定會有疑問 strtok 第一次呼叫,第一參數輸入愈分離的字串,在 while 迴圈,則是輸入 NULL 呢?底下就來解析 strtok.c 的程式碼。 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 /* * * Author : appleboy * Date : 2010.04.01 * Filename : strtok.c * */ #include "string.h" #include "stdlib.h" #include "stdio.h" int main() { char str[]="00:22:33:4B:55:5A"; char *delim = ":"; char * pch; printf ("Splitting string \"%s\" into tokens:\n",str); pch = strtok(str,delim); while (pch ! [Read More]

[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]