2017-04-13 66 views
-1

在上一次編程作業中,我們應該實現一個printf而不使用va_list。我無法工作。這裏是我的嘗試:在沒有va_list的情況下實現printf

#include<stdio.h> 
#include<stdarg.h> 
#include <string.h> 
#include <stdlib.h> 

int myprintf(const char * format, ...) 
{ 
void *traverse = &format; 
traverse += sizeof(char*); 
int i,j; 
char k; 
char * str; 


for (i = 0; i < strlen(format); i++) 
{ 
    if (format[i] == '%') 
    { 
       switch (format[i+1]) 
       { 
        case 's': 
         str = *((char**)traverse ); 
         for (j = 0; j < strlen(str); j++) 
         { 
          k = str[j]; 
          putchar(k); 
         } 
        traverse += sizeof(char*); 
        break; 

       case 'd': 
        j = *((int*)traverse); 
        putchar(j); 
        traverse += sizeof(int*); 
        break; 

       case 'c': 
         k = *((char*)traverse); 
         putchar(k); 
         traverse += sizeof(char*); 
         break; 

       case '%' : 
         putchar('%'); 
         break; 
       } 

      i++; 

     } 

    else 
    { 
     putchar(format[i]); 
    } 
} 
} 



int main() 
{ 
char k = 'a'; 
int g = 6; 
myprintf("Hello, this is %d How are You", 6); 

} 

輸出是「你好,這裏是你如何」和INT 6如我所料這將是不打印。任何想法有什麼問題的代碼?謝謝!

+2

「什麼是與代碼糾纏?」 - >代碼需要將'va_list'用於便攜式功能代碼。這些代碼使得正確操作的假設最好是定義了實現,最壞的情況是未定義的行爲。 – chux

+0

不是實際的問題,但是'%d'之後爲什麼按指針的大小而不是'int'的大小?一個'int'被傳遞,而不是一個指針。同樣在'%c'之後,但另一個缺陷是'char'在調用'printf'時被提升爲'int'。 –

+0

假設這並不意味着可移植...什麼平臺? 32位? 64位? – Dmitri

回答

0

要總結一下幾個人都提到:

printf採用可變長度參數列表。要訪問這些參數,您需要知道參數如何傳遞給函數的機制。 C規範避免宣佈這樣的低層次事情應該如何工作;它會因平臺而異。相反,C標準要求所有這些特定於平臺的東西都被封裝在一個標準化的接口後面,並稱之爲stdarg.h

這意味着這裏有兩個可能的結果。無論是你的導師都希望你得出這樣的結論:它不能用標準C來完成,並且對於爲什麼存在stdarg.h有更深的理解,或者他們希望你做一些非常特定於平臺的事情。如果是後者,那麼這不是一個C問題(你會調用大量未定義的行爲,並且在語言規範之外的方式),這是一個關於您的平臺的低級接口的問題。在我們可以幫助您之前,您需要解釋更多關於處理器架構和ABI版本的信息。

0

即使您確定參數將在堆棧中,但沒有對齊且堆棧具有正確的方向,您的代碼也會出現問題。

  1. C有一個值的調用語義。即,對於intchar,該值本身在堆棧上,而不是指針。因此,traverse的增量在格式字母「d」和「c」的情況下不正確。
  2. 在'd'的情況下,您獲取整數參數並將其解釋爲char。但是,您必須將其轉換爲字符串並輸出字符串的字符。
相關問題