【 聲明:版權所有,歡迎轉載,請勿用於商業用途。 聯系信箱:feixiaoxing @163.com】
可變參數是C語言編程的一個特色。在我們一般編程中,函數的參數個數都是確定的,事先定下來的。然而就有那麼一部分函數,它的個數是不確定的,長度也不一定,這中間有什麼秘密嗎?
其實,我們可以回憶一下哪些函數是可變參數的函數?其實也就是sprintf、printf這樣的函數而已。那麼這些函數有什麼規律嗎?關鍵就是在這個字符串上面。我們可以舉一個例子看看,
void test()
{
printf("%s, value = %d\n", "hello", 10);
}
void test()
{
printf("%s, value = %d\n", "hello", 10);
}
test函數裡面也就是一個簡單的打印函數。那麼這個函數有什麼特別的地方呢,那就是%s、%d和後面的字符是一一對應的,所以有多少個這樣的字符,首參數後面就會剩下多少個參數。那麼後面參數的地址怎麼獲取呢?我們可以回想一下,堆棧一般是怎麼壓棧處理的,
/*
* stack space:
*
* 參數3 | up
* 參數2 |
* 參數1 v down
*/
/*
* stack space:
*
* 參數3 | up
* 參數2 |
* 參數1 v down
*/ 因為參數是按照從右向左依次壓入的,所以後面參數的地址依次根據“%”處理即可。下面我們就可以自己寫一個PrintInt打印int數據的函數,首先創建一個框架,
void PrintInt(char* buffer, int data, ...)
{
return;
}
void PrintInt(char* buffer, int data, ...)
{
return;
} 然後驗證buffer參數中是否有%d,如果存在這樣的一個字符,就需要打印一個整數,
void PrintInt(char* buffer, int data, ...)
{
static char space[1024];
char temp[32];
int* start;
int count;
if(NULL == buffer)
return;
memset(space, 0, 1024);
memset(temp, 0, 32);
start = (int*) &buffer;
count = 0;
while(buffer[count]){
if(!strncmp(&buffer[count], "%d", strlen("%d"))){
start ++;
itoa(*start, temp, 10);
strcat(space, temp);
count += 2;
continue;
}
space[strlen(space)] = buffer[count];
count ++;
}
memset(buffer, 0, strlen(buffer));
memmove(buffer, space, strlen(space));
return;
}
void PrintInt(char* buffer, int data, ...)
{
static char space[1024];
char temp[32];
int* start;
int count;
if(NULL == buffer)
return;
memset(space, 0, 1024);
memset(temp, 0, 32);
start = (int*) &buffer;
count = 0;
while(buffer[count]){
if(!strncmp(&buffer[count], "%d", strlen("%d"))){
start ++;
itoa(*start, temp, 10);
strcat(space, temp);
count += 2;
continue;
}
space[strlen(space)] = buffer[count];
count ++;
}
memset(buffer, 0, strlen(buffer));
memmove(buffer, space, strlen(space));
return;
} 為了驗證我們的函數是否正確,可以編寫測試函數驗證一下,
void display()
{
char buffer[32] = {"%d %d %d %d\n"};
PrintInt(buffer, 1, 2, 3, 4);
printf(buffer);
}
void display()
{
char buffer[32] = {"%d %d %d %d\n"};
PrintInt(buffer, 1, 2, 3, 4);
printf(buffer);
}