Własna funkcja printf i scanf

Odpowiedz Nowy wątek
2019-08-22 14:12

Rejestracja: 10 miesięcy temu

Ostatnio: 6 miesięcy temu

0

Potrzebuję pomocy ze stworzeniem własnej wersji funkcji printf i scanf. Czyli my_printf i my_scanf. Dzialanie standardowe.
Funkcja my_scanf ma obsługiwać następujące formaty:

%d - liczba całkowita 32-bitowa ze znakiem,
%f - liczba zmiennoprzecinkowa podwójnej precyzji, wpisywana tylko w formie dziesiętnej

Funkcja my_printf ma obsługiwać następujące symbole formatujące:

%s - tekst (wskaźnik na znak, terminator='\x0'),
%d - liczba całkowita 32-bitowa ze znakiem,
%f - liczba zmiennoprzecinkowa podwójnej precyzji

C i C++ to różne języki, na pewno chcesz kod poprawny w obu? - kq 2019-08-22 15:11

Pozostało 580 znaków

2019-08-22 14:38

Rejestracja: 3 lata temu

Ostatnio: 18 sekund temu

2019-08-22 15:27

Rejestracja: 3 lata temu

Ostatnio: 59 minut temu

2019-08-22 15:39

Rejestracja: 5 lat temu

Ostatnio: 3 godziny temu

1

Jeżeli C++ to można spróbować opcji z variadic templates.

#include <iostream>

using namespace std;

enum class Type { INT , DOUBLE , STRING };

struct Arg
{
  Arg(int value) : type(Type::INT) { int_value = value; }
  Arg(double value) : type(Type::DOUBLE) { dbl_value = value; }
  Arg(const char *value) : type(Type::STRING) { str_value = value; }

  Type type;
  union {
    int int_value;
    double dbl_value;
    const char *str_value;
  };
};

string getValue( Type type , const Arg& arg )
{
    if( type != arg.type ) return "";

    if( arg.type == Type::INT ) return to_string(arg.int_value);
    else if( arg.type == Type::DOUBLE ) return to_string(arg.dbl_value);
    else if( arg.type == Type::STRING ) return arg.str_value;
}

void implement_my_printf( string text , const Arg *args , size_t argsize )
{
    int argcount {0};
    string result;

    for( size_t index=0 ; index<text.size() ; ++index )
    {
        if( text[index] == '%' && argcount != argsize )
        {
            if( ++index == text.size() ) break;
            switch( text[index] )
            {
                case 'd': result += getValue(Type::INT,args[argcount++]);  break;
                case 'f': result += getValue(Type::DOUBLE,args[argcount++]);  break;
                case 's': result += getValue(Type::STRING,args[argcount++]);  break;
            }
        }
        else result += text[index];
    }

    cout << result;
}

template <typename... Args>
void my_printf( string text , const Args&... args )
{
    Arg arg_array[] = {args...};
    implement_my_printf( text , arg_array , sizeof...(Args) );
}

int main()
{
    my_printf( "number1 %d number2 %d number3 %d double %f string %s end" , 2 , -4 , 4 , 45.6 , "test");
    return 0;
}
Już mogłeś się posilić na std::variant - kq 2019-08-22 15:57
i myślisz że osoba niepotrafiąca poradzić sobie z zadaniem zrozumie w ogóle twój kod? - Azarien 2019-08-22 16:13

Pozostało 580 znaków

2019-08-22 16:12

Rejestracja: 16 lat temu

Ostatnio: 1 minuta temu

1

Żeby to było poprawnie to należałoby zacząć nie od printf tylko od vprintf, a printf będzie tylko wywoływać vprintf konwertując parametry ... na va_list.

Pozostało 580 znaków

2019-08-23 14:02

Rejestracja: 12 lat temu

Ostatnio: 2 godziny temu

0

Polecam popatrzeć jak jest zrobiona biblioteka {fmt}.
Z tego co mi wiadomo rozważane jest by włączyć ją do standardu C++.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
Będzie w C++20 - kq 2019-08-23 15:18

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0