Înțelegerea mea este că "string" este un membru al std
de nume, așa că de ce urma să apară?
#include <iostream>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString);
cin.get();
return 0;
}
De fiecare dată când programul se execută, myString
imprimă un aparent aleatoare sir de 3 caractere, cum ar fi în producția de mai sus.
L's elaborarea deoarece "printf" e't de tip în condiții de siguranță, deoarece folosește argumente variabile în C sens1. "printf" nu are nici o opțiune pentru std::string`, doar C-style șir. Folosind altceva în locul a ceea ce se așteaptă de la voi't da rezultatele dorite. L's, de fapt nedefinit comportament, deci, nimic, la toate ar putea întâmpla.
Cel mai simplu mod de a rezolva acest lucru, din moment ce're folosind C++, se imprimă în mod normal cu std::cout, din
std::string` susține că, prin supraîncărcarea operatorilor:
std::cout << "Follow this command: " << myString;
Dacă, pentru un motiv oarecare, aveți nevoie pentru a extrage C-style șir de caractere, puteți utiliza c_str()
metoda std::string
pentru a primi un const char *
care este null-terminate. Folosind exemplul tau:
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString.c_str()); //note the use of c_str
cin.get();
return 0;
}
Dacă doriți o funcție care este ca "printf", dar, de tip în condiții de siguranță, uită-te în variadic șabloane (C++11, sprijinit pe toate marile compilatoare de MSVC12). Puteți găsi un exemplu de unul here. Nu's nu știu nimic de pus în aplicare astfel că în biblioteca standard, dar ar putea fi în Impuls, în mod special boost::format
.
[1]: Acest lucru înseamnă că puteți trece orice număr de argumente, dar funcția se bazează pe tine să-ți spun că numărul și tipurile de aceste argumente. În caz de "printf", care înseamnă un șir de caractere codificate cu informații de tip like %d
, însemnând int
. Dacă ai mințit în legătură cu tipul sau numărul, funcția nu are nici o modalitate standard de a ști, deși unele compilatoare au capacitatea de a verifica și de a da avertismente atunci când minți.
Vă rugăm să don't folosi printf("%s", your_string.c_str());`
Folosi cout << your_string; în loc. Scurt, simplu și typesafe. De fapt, atunci când te're scris în C++, în general, doresc să evite "printf" în întregime-l's resturi de la C ca's rareori necesare sau utile în C++.
Ca să ce ar trebui să utilizați cout
în loc de "printf", motivele sunt numeroase. Aici's o prelevare de probe de câteva dintre cele mai evidente:
cout
a care a acoperit la fel de bine. De exemplu:std::locale loc(""); std::cout.impregna(loc);
std::cout << 123456.78;
Fără nume locale ("") alege o localizare bazate pe utilizator's configurare. Prin urmare, pe masina mea (configurat pentru US English) acest imprimă ca 123,456.78
. Pentru cineva care are un computer configurat pentru (sa zicem) Germania, s-ar imprima ceva de genul 123.456,78
. Pentru cineva cu ea configurat pentru India, s-ar imprima ca 1,23,456.78
(și, desigur, există multe altele). Cu "printf" am înțeles exact un singur rezultat: 123456.78
. Este consistent, dar's în mod constant greșit pentru toată lumea peste tot. În esență, singura modalitate de a lucra în jurul valorii de ea este de a face formatarea separat, apoi se trece rezultatul ca un șir de "printf", pentru că "printf" în sine pur și simplu va nu de a face treaba corect.
4. Deși au're destul de compact, "printf" format siruri de caractere pot fi destul de ilizibil. Chiar și printre C programatori care folosesc "printf" practic în fiecare zi, am'd cred că cel puțin 99% ar trebui să uite lucrurile să fie sigur de ceea ce " # "în %#x
înseamnă, și modul în care diferă de ceea ce" # " în %#f
înseamnă (și da, ei spun lucruri complet diferite).
folosesc myString.c_str()dacă vrei un c-ca șir de caractere (
const char*`) pentru a utiliza cu printf
multumesc
Printf este de fapt destul de bun pentru a utiliza dacă mărimea contează. Sensul dacă se execută un program în cazul în care memoria este o problemă, atunci printf este de fapt un foarte bun și sub evaluator soluție. Cout, în esență, schimburi de biți pe pentru a face loc pentru șir, în timp ce printf nevoie doar într-un fel de parametri și tipărește la ecran. Dacă ai fost pentru a compila un simplu program hello world, printf-ar putea să-l compilați în mai puțin de 60 000 de biți spre deosebire de cout, ar fi nevoie de peste 1 milion de biți pentru a compila.
Pentru situația ta, id-ul sugerează utilizarea cout pur și simplu pentru că este mult mai convenabil de a folosi. Deși, aș spune că printf este ceva bun, să știi.
Principalul motiv este, probabil, că un C++ șir de caractere este o structură care include un curent-lungime valoare, nu doar adresa de o secvență de caractere terminate cu un 0 byte. Printf și rudele sale se aștepta să găsească un astfel de secvență, nu un struct, și, prin urmare, a obține confuz de C++ siruri de caractere.
Vorbind pentru mine, cred că printf are un loc care poate't fi ușor umplute de către C++ caracteristici sintactice, doar ca masă de structuri în html avem un loc care poate't fi ușor umplute de către divs. Ca Dykstra a scris mai târziu despre du-te, nici't intenționează să înceapă o religie și a fost într-adevăr doar argumentând împotriva folosind-o ca o improvizație pentru a compensa prost conceput cod.
Ar fi destul de frumos dacă proiectul GNU ar adăuga printf familia lor g++ extensii.
"printf" acceptă un număr variabil de argumente. Acestea pot avea doar Simple Date Vechi (POD) tipuri. Cod care trece de nimic altceva decât de POD pentru a "printf" doar compilează deoarece compilatorul presupune ți-ai format corect. "%s " înseamnă că respectivul argument ar trebui să fie un pointer la o char
. In cazul tau, este un std::string " nu "const char. "printf" nu știu pentru că argumentul tip se duce pierdut și ar trebui să fie restaurată din parametrul format. Atunci când cotitură care std::string
argument în `const char` rezultate indicatorul va indica unele irelevante regiune de memorie în loc de dorit C string. Pentru acest motiv, codul imprimă păsărească.
În timp ce "printf" este o alegere excelentă pentru imprimarea de text formatate]1, (mai ales dacă intenționați să aveți padding), poate fi periculos dacă te-ai't activate compiler avertismente. Activați întotdeauna avertismentele pentru că atunci greșeli de acest gen sunt ușor de evitat. Nu există nici un motiv pentru a utiliza stângace std::cout
mecanism dacă "printf" de familie poate face același lucru într-un mod mult mai repede și mai frumos mod. Doar asigurați-vă că ați activat toate avertismentele (-Perete -Wextra
) și va fi bine. În cazul în care utilizați propriul dvs. personalizat "printf" punerea în aplicare ar trebui să declare cu __attribute__
mecanism care permite compilatorului să verifice șir format împotriva parametrii oferit.