2017-04-13 3 views
-1

最後のプログラミングの宿題では、va_listを使用せずにprintfを実装することになっていました。私は私の仕事を得ることができませんでした。ここに私の試みだった: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'の後には、' printf'の呼び出しで 'char'が' int'に昇格するという追加の落とし穴があります。 –

+0

これは移植可能ではないと仮定します...どのプラットフォームですか? 32ビット? 64ビット? – Dmitri

答えて

0

printfは、可変長引数リストを取ります。これらの引数にアクセスするには、引数が関数にどのように渡されるかの仕組みを知る必要があります。 Cの仕様は、このような低レベルのものがどのように機能すべきかを宣言しないようにしています。プラットフォームごとに異なります。その代わりに、Cの標準では、このプラットフォーム固有のものは全て、標準化されたインタフェースの後ろにラップされ、stdarg.hと呼ばれていました。

これは、ここに2つの可能な結果があることを意味します。あなたのインストラクターは、標準Cで行うことができないと判断し、なぜstdarg.hが存在するのかを深く理解しているか、プラットフォーム特有の何かをしたいと思っています。後者の場合、これはCの質問ではありません(あなたは未定義の動作をたくさん呼び、の方法での言語仕様に外しています)、これはお使いのプラットフォームの低レベルインタフェースに関する質問です。お手伝いをする前に、お使いのプロセッサアーキテクチャとABIバージョンの詳細を説明する必要があります。

0

引数がスタック上にあり、アライメントがなく、スタックが正しい方向を持っていると確信しても、コードには問題があります。

  1. Cはvalue semanticによる呼び出しを持っています。つまり、とcharの場合、値自体はポインタではなくスタックにあります。したがって、フォーマット文字 'd'と 'c'の場合は、traverseの増分が正しくありません。
  2. 'd'の場合は、整数引数を取り出してcharと解釈します。ただし、文字列に変換して文字列の文字を出力する必要があります。
関連する問題