다음 main () 메서드로 C ++ 응용 프로그램을 실행하면 모든 것이 정상입니다.
int main(int argc, char *argv[])
{
cout << "There are " << argc << " arguments:" << endl;
// Loop through each argument and print its number and value
for (int i=0; i<argc; i++)
cout << i << " " << argv[i] << endl;
return 0;
}
나는 내가 기대하는 것을 얻었고 나의 주장은 인쇄되었다.
그러나 _tmain을 사용하면 :
int _tmain(int argc, char *argv[])
{
cout << "There are " << argc << " arguments:" << endl;
// Loop through each argument and print its number and value
for (int i=0; i<argc; i++)
cout << i << " " << argv[i] << endl;
return 0;
}
각 인수의 첫 문자 만 표시합니다.
이것을 일으키는 차이점은 무엇입니까?
답변
_tmain
C ++에는 없습니다. main
그렇습니다.
_tmain
Microsoft 확장입니다.
main
C ++ 표준에 따르면 프로그램의 진입 점입니다. 다음 두 가지 서명 중 하나가 있습니다.
int main();
int main(int argc, char* argv[]);
Microsoft는 두 번째 서명을 다음과 같이 바꾸는 wmain을 추가했습니다.
int wmain(int argc, wchar_t* argv[]);
그런 다음 유니 코드 (UTF-16)와 멀티 바이트 문자 세트를 쉽게 전환 할 수 있도록 _tmain
유니 코드가 활성화 된 wmain
경우로 컴파일 되고 그렇지 않으면로 컴파일되는 것을 정의 했습니다 main
.
질문의 두 번째 부분은 퍼즐의 첫 번째 부분이 주요 기능이 잘못되었다는 것입니다. 아닌 인수를 wmain
취해야합니다 . 컴파일러는 함수에 대해 이것을 강제하지 않기 때문에 문자열 배열을 함수 로 전달 하는 프로그램을 얻습니다.이 문자열은 문자열로 해석 됩니다.wchar_t
char
main
wchar_t
main
char
이제 UTF-16에서 유니 코드가 사용 가능한 경우 Windows에서 사용하는 문자 세트는 모든 ASCII 문자가 바이트 쌍으로 표시되고 \0
ASCII 값이 뒤에옵니다.
x86 CPU는 리틀 엔디안이므로이 바이트의 순서가 바뀌어 ASCII 값이 먼저 온 다음 널 바이트가 뒤 따릅니다.
그리고 char 문자열에서 문자열은 일반적으로 어떻게 종료됩니까? 네, null 바이트입니다. 따라서 프로그램은 1 바이트 길이의 많은 문자열을 봅니다.
일반적으로 Windows 프로그래밍을 수행 할 때 세 가지 옵션이 있습니다.
- 명시 적으로 유니 코드를 사용하십시오 (wmain을 호출하고 char 관련 인수를 취하는 모든 Windows API 함수
-W
에 대해 함수 버전을 호출하십시오 . CreateWindow 대신 CreateWindowW를 호출하십시오). 그리고char
usewchar_t
등 을 사용 하는 대신 - 유니 코드를 명시 적으로 비활성화하십시오. main 및 CreateWindowA를 호출
char
하고 문자열에 사용하십시오 . - 둘 다 허용하십시오. (main / _tmain 및 CreateWindowA / CreateWindowW로 해석되는 _tmain 및 CreateWindow를 호출) char / wchar_t 대신 TCHAR을 사용하십시오.
windows.h에 의해 정의 된 문자열 유형에도 동일하게 적용됩니다. LPCTSTR은 LPCSTR 또는 LPCWSTR로 해석되며 char 또는 wchar_t를 포함하는 다른 모든 유형의 경우 항상 대신 사용할 수있는 -T- 버전이 존재합니다.
이 모든 것은 Microsoft에만 해당됩니다. TCHAR은 표준 C ++ 유형이 아니며 windows.h에 정의 된 매크로입니다. wmain 및 _tmain도 Microsoft에서만 정의됩니다.
답변
_tmain은 유니 코드 또는 ASCII로 컴파일하는지 여부에 따라 재정의되는 매크로입니다. Microsoft 확장이며 다른 컴파일러에서 작동한다고 보장되지 않습니다.
올바른 선언은
int _tmain(int argc, _TCHAR *argv[])
매크로 UNICODE가 정의 된 경우
int wmain(int argc, wchar_t *argv[])
그렇지 않으면
int main(int argc, char *argv[])
정의는 각각 조금씩 진행되며 (유니 코드가 정의 된 경우)
int wmain(int argc, char *argv[])
그것은 명백한 잘못입니다.
std :: cout은 ASCII 문자와 함께 작동합니다. 넓은 문자를 사용하는 경우 std :: wcout이 필요합니다.
이런 식으로 해보십시오
#include <iostream>
#include <tchar.h>
#if defined(UNICODE)
#define _tcout std::wcout
#else
#define _tcout std::cout
#endif
int _tmain(int argc, _TCHAR *argv[])
{
_tcout << _T("There are ") << argc << _T(" arguments:") << std::endl;
// Loop through each argument and print its number and value
for (int i=0; i<argc; i++)
_tcout << i << _T(" ") << argv[i] << std::endl;
return 0;
}
또는 넓거나 좁은 문자를 사용할지 미리 결정할 수 있습니다. 🙂
2013 년 11 월 12 일 업데이트 :
기존의 “TCHAR”을 “_TCHAR”로 변경하여 최신 유행 인 것 같습니다. 둘 다 잘 작동합니다.
최종 업데이트
답변
_T 규칙은 프로그램이 응용 프로그램에 정의 된 문자 집합 (유니 코드, ASCII, MBCS 등)을 사용해야 함을 나타내는 데 사용됩니다. 문자열을 _T ()로 묶어 올바른 형식으로 저장할 수 있습니다.
cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl;
답변
문제는 상당히 잘 대답 된 것 같습니다. 유니 코드 과부하는 두 번째 매개 변수로 넓은 문자 배열을 가져야합니다. 따라서 명령 줄 매개 변수가 "Hello"
그 결과로 끝나고 "H\0e\0l\0l\0o\0\0\0"
프로그램이 'H'
null 종결 자라고 생각하는 것을보기 전에 만 인쇄합니다 .
이제 왜 컴파일하고 링크하는지 궁금 할 것입니다.
함수에 과부하를 정의 할 수 있기 때문에 컴파일됩니다.
연결은 약간 더 복잡한 문제입니다. C에는 장식 된 기호 정보가 없으므로 main이라는 함수 만 찾습니다. argc 및 argv는 함수가 해당 시그니처로 정의되어 있어도 함수가 무시하더라도 호출 스택 매개 변수로 항상 존재합니다.
C ++에는 장식 된 기호가 있지만 각 문자를 차례로 찾는 영리한 링커보다는 C- 링키지를 기본으로 사용합니다. 따라서 wmain을 발견하고 매개 변수가 int wmain(int, wchar_t*[])
버전 인 경우 매개 변수를 호출 스택에 넣습니다 .
답변
이것을 템플릿 화하기 위해 약간의 노력을 기울이면 모든 객체 목록과 함께 작동합니다.
#include <iostream>
#include <string>
#include <vector>
char non_repeating_char(std::string str){
while(str.size() >= 2){
std::vector<size_t> rmlist;
for(size_t i = 1; i < str.size(); i++){
if(str[0] == str[i]) {
rmlist.push_back(i);
}
}
if(rmlist.size()){
size_t s = 0; // Need for terator position adjustment
str.erase(str.begin() + 0);
++s;
for (size_t j : rmlist){
str.erase(str.begin() + (j-s));
++s;
}
continue;
}
return str[0];
}
if(str.size() == 1) return str[0];
else return -1;
}
int main(int argc, char ** args)
{
std::string test = "FabaccdbefafFG";
test = args[1];
char non_repeating = non_repeating_char(test);
Std::cout << non_repeating << '\n';
}