std:: 문자열을 사용한 printf?
로는 로는입니다.string
입니다의 입니다.std
네임스페이스, 그렇다면 왜 다음과 같은 현상이 발생합니까?
#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;
}
실행될 myString
는 위의 출력과 같이 3자로 구성된 임의의 문자열을 인쇄합니다.
C++23 업데이트
가 .std::print
으로를 쓰는 std::format
직접 출력의 경우:
#include <print>
#include <string>
int main() {
// ...
std::print("Follow this command: {}", myString);
// ...
}
이것은 두 가지 접근법 중 가장 좋은 것을 결합한 것입니다.
원답
편집을 하는 이유는printf
C1 의미의 변수 인수를 사용하기 때문에 타입 세이프가 아닙니다.printf
에 대한 옵션이 없습니다.std::string
C 만 만 만.기대하는 것 대신 다른 것을 사용한다고 해서 원하는 결과를 얻을 수는 없습니다.사실은 정의되지 않은 행동이기 때문에 무슨 일이든 일어날 수 있습니다.
C++를 사용하고 있기 때문에 이 문제를 해결하는 가장 쉬운 방법은 다음과 같이 정상적으로 인쇄하는 것입니다.std::cout
1972년 std::string
오버로드를 합니다.
std::cout << "Follow this command: " << myString;
로 C-style 로 을 C-style 해야 ,c_str()
std::string
학점을 const char *
③ null-terminated ④.예를 들어 다음과 같이 하십시오.
#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;
}
만약 당신이 다음과 같은 기능을 원한다면.printf
, safe를 입력하면 다양한 템플릿(C++11, MSVC12 현재 모든 주요 컴파일러에서 지원됨)을 확인할 수 있습니다.여기서 하나의 예를 찾을 수 있습니다.표준 라이브러리에는 그렇게 구현된 것이 없지만, 특히 Boost에는 있을 수 있습니다.
[1]: 인수의 개수는 얼마든지 전달할 수 있지만 함수는 인수의 개수와 유형을 알려주기 위해 사용자에게 의존합니다.①의 printf
, 과 된 를 합니다 을 합니다 을 은 를 과 된 %d
를 뜻하는int
나 숫자에 을 한다면, 그알 수 있는 , 일부 당신이 을 할 때 . 종류나 숫자에 대해 거짓말을 하는 경우, 일부 컴파일러는 거짓말을 할 때 확인하고 경고를 주는 기능이 있지만, 함수는 표준적인 알 수 있는 방법이 없습니다.
사용하다myString.c_str()
을 원한다면 (은을면와(면을fconst char*
) printf 합니다 합니다 와 함께 합니다.
감사해요.
사용하지 말아주세요printf("%s", your_string.c_str());
사용하다cout << your_string;
◦ 한 타입입니다짧고 단순하며 안전한 타입.쓸 때 실 C++쓸때로지다는이를다odn는지tyunc실,tcu쓸+,'를+eprintf
C++에서는 거의 필요 없거나 유용하지 않은 C에서 남은 잔재물입니다.
사용해야 하는 이유에 대해서는cout
에 대신에printf
, , , , , , , , , , , , , , , , , , , , , , , , , , , , .다음은 가장 명백한 몇 가지를 샘플링한 것은 다음과 같습니다.
- 질문에서 알 수 있듯이.
printf
안전하지 않습니다.는이에된과우를환우f과printf
정의되지 않은 동작을 제공하면서 스택에서 찾은 모든 것을 지정된 유형인 것처럼 사용하려고 합니다.일부 컴파일러는 상황에 따라 이에 대해 경고할 수 있지만, 일부 컴파일러는 전혀 경고할 수 없고, 어떤 컴파일러도 모든 상황에서 경고할 수 없습니다. printf
확장할 수 없습니다.원시 유형만 전달할 수 있습니다.이해하고 있는 변환 지정자 집합은 구현 과정에서 하드 코드화되어 있기 때문에 추가/기타를 추가할 방법이 없습니다.잘 작성된 대부분의 C++는 주로 해결 중인 문제를 지향하는 유형을 구현하기 위해 이러한 유형을 사용해야 합니다.이것은 괜찮은 포맷을 훨씬 더 어렵게 만듭니다.예를 들어, 사람들이 읽을 수 있도록 숫자를 인쇄할 때 일반적으로 몇 자리마다 수천 개의 구분 기호를 삽입하려고 합니다.로는한와는만,만는,
cout
그것도 포함되어 있습니다.예를 들어,std::locale loc(""); std::cout.imbue(loc); std::cout << 123456.78;
이름 없는 로케일(")은 사용자의 구성을 기반으로 로케일을 선택합니다.된) 내서 로된내과다이서국다이ts내e국서된,s로)서(sneg(d
123,456.78
위해 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123.456,78
.으로 의 과 됩니다 된 됩니다 과 으로 된 의1,23,456.78
(물론 다른 것들도 많이 있습니다.)와 함께printf
한 결과를 :히한지가다다가지i한:tye.123456.78
. 그것은 일관된 것이지만, 모든 곳에 있는 모든 사람들에게 항상 잘못된 것입니다.기본적으로 이 문제를 해결할 수 있는 유일한 방법은 포맷을 따로 한 다음 결과를 문자열로 전달하는 것입니다.printf
, , , , , , , , , , , , , , , , , , , .printf
그 자체로는 일을 제대로 하지 못할 겁니다.- 비록 그들이 꽤 작지만,
printf
형식 문자열을 읽을 수 없습니다.하는 C도머도esoncmprintf
거의 매일, 적어도 99%는 어떤 일이 있는지 확인하기 위해 물건을 찾아봐야 할 것 같습니다.#
인에%#x
이고, 하고,이게는게tmtes,이고,ws#
인에%#f
(그리고 네, 그들은 완전히 다른 것을 의미합니다.)
std::printf 및 c_str() 예제 사용:
std::printf("Follow this command: %s", myString.c_str());
을 사용할 수 .snprinft
필요한 문자 수를 결정하고 적절한 크기의 버퍼를 할당합니다.
int length = std::snprintf(nullptr, 0, "There can only be %i\n", 1 );
char* str = new char[length+1]; // one more character for null terminator
std::snprintf( str, length + 1, "There can only be %i\n", 1 );
std::string cppstr( str );
delete[] str;
이것은 cppreference.com 의 예제를 약간 변형한 것입니다.
printf
변수 개수의 인수를 허용합니다.이러한 유형은 POD(Plain Old Data) 유형만 사용할 수 있습니다.을 POD로 른에드는을를드eprintf
컴파일러는 당신이 당신의 포맷을 잘 맞추었다고 가정하기 때문에 컴파일만 합니다.%s
의 a에가야는다을한aorssaeo이의dtea한야etchar
는 . 의 는 입니다.std::string
것은 아니다.const char*
.printf
인수 유형이 손실되고 형식 매개 변수에서 복원되어야 하기 때문에 알 수 없습니다.때std::string
을로 const char*
결과 포인터는 원하는 C 문자열 대신 메모리의 일부 관련 없는 영역을 가리킵니다.그런 이유로 당신의 코드는 횡설수설합니다.
하는 동안에printf
는 포맷된 텍스트를 출력하는 데 탁월한 선택이며, 특히 패딩을 의도하는 경우 컴파일러 경고를 활성화하지 않으면 위험할 수 있습니다.이와 같은 실수는 쉽게 피할 수 있으므로 항상 경고를 활성화합니다.서투른 것을 쓸 이유가 없습니다.std::cout
메커니즘 만약에printf
가족들은 같은 일을 훨씬 더 빠르고 예쁜 방법으로 할 수 있습니다.경고를 를지다(다했는지 )-Wall -Wextra
잘 할 수 있을 겁니다자신만의 관습을 사용하는 경우printf
구현을 당신은 그것을 the와 함께 선언해야 합니다.__attribute__
컴파일러가 제공된 매개 변수와 비교하여 형식 문자열을 확인할 수 있도록 하는 메커니즘입니다.
주된 이유는 C++ 문자열이 0 바이트로 끝나는 문자 시퀀스의 주소가 아니라 전류 길이 값을 포함하는 구조이기 때문일 것입니다.Printf와 그 친척들은 구조가 아닌 그러한 수열을 찾기를 기대하며 따라서 C++ 문자열로 혼란스러워 합니다.
저는 html의 테이블 구조가 div로 쉽게 채워지지 않는 공간을 가지고 있는 것처럼 printf도 C++ 구문적 특징으로 쉽게 채워지지 않는 공간을 가지고 있다고 생각합니다.Dykstra가 나중에 고토에 대해 썼듯이, 그는 종교를 시작할 의도가 없었고, 단지 그것을 엉성하게 설계된 코드를 보충하기 위해 그것을 진흙으로 사용하는 것에 반대하는 주장을 하고 있었습니다.
GNU 프로젝트에서 printf 패밀리를 g++ 확장자에 추가하면 좋을 것 같습니다.
실제로 크기가 중요하다면 프린트f를 사용하는 것이 꽤 좋습니다.즉, 메모리가 문제가 되는 프로그램을 실행하고 있다면 printf는 실제로 매우 우수하고 낮은 수준의 솔루션입니다.Cout은 기본적으로 비트를 이동하여 문자열을 넣을 공간을 만드는 반면 printf는 일종의 매개 변수를 받아들여 화면에 인쇄합니다.만약 당신이 간단한 hello world 프로그램을 컴파일한다면, printf는 cout이 아닌 60,000 비트 이하로 컴파일 할 수 있을 것이고, 컴파일하는 데 100만 비트가 넘게 걸릴 것입니다.
당신의 상황을 위해, 저는 cout이 사용하기에 훨씬 편리하기 때문에 cout을 사용하는 것을 추천합니다.하지만, 저는 printf가 알아두면 좋은 것이라고 주장하고 싶습니다.
일반적인 방법은 다음과 같습니다.
#include <string>
#include <stdio.h>
auto print_helper(auto const & t){
return t;
}
auto print_helper(std::string const & s){
return s.c_str();
}
std::string four(){
return "four";
}
template<class ... Args>
void print(char const * fmt, Args&& ...args){
printf(fmt, print_helper(args) ...);
}
int main(){
std::string one {"one"};
char const * three = "three";
print("%c %d %s %s, %s five", 'c', 3+4, one + " two", three, four());
}
언급URL : https://stackoverflow.com/questions/10865957/printf-with-stdstring
'programing' 카테고리의 다른 글
symphony2 및 distrine을 사용하여 기존 데이터베이스에서 단일 개체 생성 (0) | 2023.09.09 |
---|---|
PIL을 사용하여 RGBA PNG를 RGB로 변환 (0) | 2023.09.09 |
잠금 테이블을 수행할 때 원격 사용자의 액세스가 거부됨 (0) | 2023.09.09 |
Ajax에서 POST 데이터 크기 제한이 있습니까? (0) | 2023.09.09 |
Angular CLI 6: angular.json에서 Sass 컴파일을 추가하려면 어떻게 해야 합니까? (0) | 2023.09.09 |