konwersja, konwertowanie danych

konwersja, konwertowanie danych
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

czy Community 2022 ma obsługę standardowo konwersi(konwertowania) danych z char->int , int->char , float->char , char->float ? jeśli tak to można jakieś przykłady prosić ...
EDIT:sprawdziłem atoi oraz atof i błędne pokazuje wartości, sypie się..

BR
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 28
3

Community 2022 jest chyba zgodny z w miarę nowymi standardami. To standard 'ma obsługę' a nie IDE (no chyba że jakieś rozszerzenia).
No ale do rzeczy. Myślę że lepiej byłoby gdybyś sam pokazał przykłady gdzie nie działa ale mniejsza.

Są funkcje z:

  • <cstdlib (atoi, atof, strtof)
  • <string> (stoi, stof, to_string)
  • <charconv> (from_chars, to_chars)
  • <cstdio> (sprintf)
  • <format>

Przykład od GPT :

Kopiuj
#include <iostream>
#include <string>
#include <cstring>
#include <charconv>
#include <cstdlib>
#include <cstdio>
#include <format>

int main() {
    // ----- char* (C-string) -> int -----
    const char* str_num = "12345";
    int num1 = atoi(str_num); // C-style
    int num2 = std::stoi(std::string(str_num)); // C++ string + stoi

    int num3 = 0;
    std::from_chars(str_num, str_num + std::strlen(str_num), num3); // from_chars

    std::cout << "char* -> int:\n";
    std::cout << "atoi: " << num1 << "\n";
    std::cout << "stoi: " << num2 << "\n";
    std::cout << "from_chars: " << num3 << "\n\n";

    // ----- int -> char* / std::string -----
    int val = 6789;
    char buffer1[20];
    sprintf(buffer1, "%d", val); // C-style

    std::string str_val = std::to_string(val); // C++ style

    char buffer2[20];
    auto [ptr, ec] = std::to_chars(buffer2, buffer2 + sizeof(buffer2), val); // C++17 with std::to_chars
    *ptr = '\0'; // null-terminate manually

    std::cout << "int -> char* / string:\n";
    std::cout << "sprintf: " << buffer1 << "\n";
    std::cout << "to_string: " << str_val << "\n";
    std::cout << "to_chars: " << buffer2 << "\n";
    std::cout << "format: " << std::format("{}", val) << "\n\n";

    // ----- char* -> float -----
    const char* str_float = "3.14159";
    float f1 = atof(str_float); // C-style
    float f2 = std::stof(std::string(str_float)); // C++ string + stof

    float f3 = 0.0f;
    std::from_chars(str_float, str_float + std::strlen(str_float), f3); // from_chars (float) – may have limited support

    char* endptr;
    float f4 = strtof(str_float, &endptr); // strtof

    std::cout << "char* -> float:\n";
    std::cout << "atof: " << f1 << "\n";
    std::cout << "stof: " << f2 << "\n";
    std::cout << "from_chars: " << f3 << " (may be zero if not supported)\n";
    std::cout << "strtof: " << f4 << "\n\n";

    // ----- float -> char* / string -----
    float pi = 3.14159f;
    char buffer3[32];
    sprintf(buffer3, "%.5f", pi); // C-style formatting

    std::string str_pi = std::to_string(pi); // C++ style

    char buffer4[32];
    auto [ptr2, ec2] = std::to_chars(buffer4, buffer4 + sizeof(buffer4), pi); // C++17 with std::to_chars
    *ptr2 = '\0'; // null-terminate

    std::cout << "float -> char* / string:\n";
    std::cout << "sprintf: " << buffer3 << "\n";
    std::cout << "to_string: " << str_pi << "\n";
    std::cout << "to_chars: " << buffer4 << "\n";
    std::cout << "format: " << std::format("{}", pi) << "\n";

    return 0;
}

EDIT: Dodałem <format>

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0
Kopiuj
cout << atof((char*)"3.14159658") << endl;

wynik:3.1416 - obcina koniec 😕

Kopiuj
float pi = 3.14159658f;
char buffer3[32];
sprintf(buffer3, "%f", pi); // C-style formatting

wynik:: 3.141597 - też obcina, z tego co widać to zaokrągla to mi się nie podoba

MY
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1107
1
wilkwielki napisał(a):
Kopiuj
cout << atof((char*)"3.14159658") << endl;

wynik:3.1416 - obcina koniec 😕

Podglądałeś w debugerze co rzeczywiście zwraca atof np przypisując do tymczasowej zmiennej typu double? Bo mam wrażenie, że to tylko kwestia wyświetlania. Powinieneś zainteresować się tym https://en.cppreference.com/w/cpp/io/manip/setprecision Jak ustawisz odpowiednio precyzję, to powinien wyświetlać tyle ile chcesz.

Jeśli chodzi o drugą rzecz, spróbuj tak:

Kopiuj
sprintf(buffer3, "%.20f", pi); // C-style formatting

Pisane z pamięci bez sprawdzenia, ale powinno też zadziałać ;)

BR
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 28
2

Problemy są dwa.
Jeden to setprecision co do którego Mr.YaHooo mnie ubiegł bo za bardzo grzebie się z pisaniem odpowiedzi.
Drugi to wybór typu danych. Typ float jest za mały aby pomieścić tę liczbę. Zmiana na double rozwiązuje ten problem.

Poniżej przykład:

  • dodałem setprecision
  • zmieniłem to_string na format
  • zmieniłem float na double (zmieniając odpowiednio funkcje)
Kopiuj
#include <iostream>
#include <string>
#include <cstring>
#include <charconv>
#include <cstdlib>
#include <cstdio>
#include <format>
#include <iomanip>

int main() {
    // ----- char* -> double -----
    const char* str_double = "3.14159265358979";
    double f1 = atof(str_double);
    double f2 = std::stod(std::string(str_double));

    double f3;
    std::from_chars(str_double, str_double + std::strlen(str_double), f3);

    char* endptr;
    double f4 = strtod(str_double, &endptr);

    std::cout << std::fixed << std::setprecision(14);

    std::cout << "char* -> double:\n";
    std::cout << "atof: " << f1 << "\n";
    std::cout << "stod: " << f2 << "\n";
    std::cout << "from_chars: " << f3 << " (may be zero if not supported)\n";
    std::cout << "strtod: " << f4 << "\n\n";

    // ----- double -> char* / string -----
    double pi = 3.14159265358979;
    char buffer3[32];
    sprintf(buffer3, "%.14f", pi);

    std::string str_pi = std::format("{}", pi);

    char buffer4[32];
    auto [ptr2, ec2] = std::to_chars(buffer4, buffer4 + sizeof(buffer4), pi);
    *ptr2 = '\0';

    std::cout << "double -> char* / string:\n";
    std::cout << "sprintf: " << buffer3 << "\n";
    std::cout << "format: " << str_pi << "\n";
    std::cout << "to_chars: " << buffer4 << "\n";

    return 0;
}
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

zrobiłem tak:

Kopiuj
double pi = 3.14159265358979;
char buffer3[32];
std::setprecision(32);
sprintf(buffer3, "%.20f", pi);
cout << pi << endl;

wynik: 3.14159

MY
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1107
2

Ale setprecision nie tak się używa. Oba moje sposoby działają poprawnie https://ideone.com/c4PF5y

Kopiuj
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	// your code goes here
	double pi = 3.14159265358979;
	cout << std::setprecision(32) << pi << endl;
	
	char buffer3[32];
	sprintf(buffer3, "%.20f", pi);
	cout << buffer3;
	
	return 0;
}
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

rzeczywiście działa, ok to dzięki w razie problemów sprawdzę ostatnie posty, dzięki 😉

Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2184
1

sprintf w C++ nie jest przestarzała w sensie technicznym (ciągle jest w standardzie C i C++), ale uznaje się ją za niebezpieczną – bo łatwo o błąd typu buffer overflow (przekroczenie bufora, jeśli źle policzysz rozmiar).

W nowoczesnym C++ masz kilka lepszych opcji:

1. snprintf

Bezpieczniejsza wersja sprintf, bo podajesz maksymalny rozmiar bufora:

Kopiuj
char buf[100];
snprintf(buf, sizeof(buf), "Wynik: %d", 42);

2. std::ostringstream

Część standardu C++ (bezpieczna, ale trochę „ciężka” i mniej wygodna):

Kopiuj
#include <sstream>
#include <string>

std::ostringstream oss;
oss << "Wynik: " << 42;
std::string str = oss.str();

3. std::format (C++20)

Nowoczesne i bardzo wygodne:

Kopiuj
#include <format>
#include <string>

std::string s = std::format("Wynik: {}", 42);

4. fmt (biblioteka open-source, na której opiera się std::format)

Jeśli Twój kompilator nie wspiera jeszcze std::format, możesz użyć {fmt}:

Kopiuj
#include <fmt/core.h>
#include <string>

std::string s = fmt::format("Wynik: {}", 42);

👉 Podsumowanie:

  • sprintf nadal działa, ale lepiej go unikać w nowych projektach.
  • Jeśli chcesz pisać nowocześnie: używaj std::format (C++20) albo {fmt}.
  • Jeśli musisz w stylu C: snprintf.

Chcesz, żebym zrobił tabelkę porównawczą (sprintf vs snprintf vs ostringstream vs std::format)?

ja osobiście preferuję fmt

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
1

jeśli tak to zrób tą tabelkę porównawczą 😀

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
2
wilkwielki napisał(a):

czy Community 2022 ma obsługę standardowo konwersi(konwertowania) danych z char->int , int->char , float->char , char->float ? jeśli tak to można jakieś przykłady prosić ...
EDIT:sprawdziłem atoi oraz atof i błędne pokazuje wartości, sypie się..

brokenelevator napisał(a):

Community 2022 jest chyba zgodny z w miarę nowymi standardami.

Najwyraźniej mylicie IDE z kompilatorem.
Microsoft Visual Studio Community 2022 - odnosi się do IDE (Integrated Development Environment). Wraz z tym narzędziem jest instalowany kompilator MSVC.
Wersja Microsoft Visual Studio różnią się zestawem narzędzi jakie są dostarczane z/do tego IDE. Sam kompilator C/C++ jest ten sam dla wszystkich wersji.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.