C ++에서 _tmain ()과 main ()의 차이점은 무엇입니까? return 0; } 나는 내가 기대하는

다음 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;
}

각 인수의 첫 문자 만 표시합니다.

이것을 일으키는 차이점은 무엇입니까?



답변

_tmainC ++에는 없습니다. main그렇습니다.

_tmain Microsoft 확장입니다.

mainC ++ 표준에 따르면 프로그램의 진입 점입니다. 다음 두 가지 서명 중 하나가 있습니다.

int main();
int main(int argc, char* argv[]);

Microsoft는 두 번째 서명을 다음과 같이 바꾸는 wmain을 추가했습니다.

int wmain(int argc, wchar_t* argv[]);

그런 다음 유니 코드 (UTF-16)와 멀티 바이트 문자 세트를 쉽게 전환 할 수 있도록 _tmain유니 코드가 활성화 된 wmain경우로 컴파일 되고 그렇지 않으면로 컴파일되는 것을 정의 했습니다 main.

질문의 두 번째 부분은 퍼즐의 첫 번째 부분이 주요 기능이 잘못되었다는 것입니다. 아닌 인수를 wmain취해야합니다 . 컴파일러는 함수에 대해 이것을 강제하지 않기 때문에 문자열 배열을 함수 로 전달 하는 프로그램을 얻습니다.이 문자열은 문자열로 해석 됩니다.wchar_tcharmainwchar_tmainchar

이제 UTF-16에서 유니 코드가 사용 가능한 경우 Windows에서 사용하는 문자 세트는 모든 ASCII 문자가 바이트 쌍으로 표시되고 \0ASCII 값이 뒤에옵니다.

x86 CPU는 리틀 엔디안이므로이 바이트의 순서가 바뀌어 ASCII 값이 먼저 온 다음 널 바이트가 뒤 따릅니다.

그리고 char 문자열에서 문자열은 일반적으로 어떻게 종료됩니까? 네, null 바이트입니다. 따라서 프로그램은 1 바이트 길이의 많은 문자열을 봅니다.

일반적으로 Windows 프로그래밍을 수행 할 때 세 가지 옵션이 있습니다.

  • 명시 적으로 유니 코드를 사용하십시오 (wmain을 호출하고 char 관련 인수를 취하는 모든 Windows API 함수 -W에 대해 함수 버전을 호출하십시오 . CreateWindow 대신 CreateWindowW를 호출하십시오). 그리고 charuse wchar_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';
}