c++ - _tmain - main 関数 仕様




C++の_tmain()とmain()の違いは何ですか? (4)

OK、問題はかなりうまく答えられたようですが、UNICODEのオーバーロードはワイド文字配列を2番目のパラメータとして取ります。 したがって、コマンドラインパラメータが"Hello"場合、おそらく"H\0e\0l\0l\0o\0\0\0"なり、あなたのプログラムはそれが何であるかを見る前に'H'ヌルターミネータ。

だから、なぜそれがコンパイルされてリンクされるのか不思議に思うかもしれません。

関数へのオーバーロードを定義することが許可されているので、コンパイルされます。

リンクはやや複雑な問題です。 Cでは、デコレートされたシンボル情報がないので、単にmainという関数が見つかります。 あなたの関数がそのシグニチャで定義されていても、あなたの関数がそれを無視したとしても、argcとargvはたぶんコールスタックパラメータとして存在します。

C ++はデコレートされたシンボルを持っていますが、順番にそれぞれを探す巧妙なリンカではなく、主にC-リンケージを使用しています。 だからあなたのwmainを見つけ、 int wmain(int, wchar_t*[])バージョンの場合はパラメータをcall-stackに置きます。

次の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;
}

各引数の最初の文字が表示されます。

これを引き起こす違いは何ですか?


_T規則は、プログラムでアプリケーション用に定義された文字セット(Unicode、ASCII、MBCSなど)を使用する必要があることを示すために使用されます。 文字列を_T()で囲むことで、正しい形式で格納することができます。

 cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl;

_tmainはC ++では存在しません。 mainは行います。

_tmainはMicrosoftの拡張機能です。

mainは、C ++標準に従って、プログラムのエントリポイントです。 それはこれらの2つの署名の1つを持っています:

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

マイクロソフトでは、2番目の署名を次のように置き換えるwmainを追加しました。

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

そして、Unicode(UTF-16)とそのマルチバイト文字セットを簡単に切り替えるために、 _tmainを定義しました。これは、Unicodeが有効な場合はwmainとしてコンパイルされ、そうでない場合はmainとしてコンパイルされます。

あなたの質問の第二の部分については、パズルの最初の部分は、あなたの主な機能が間違っているということです。 wmaincharではなくwchar_t引数をとる必要があります。 コンパイラーはmain関数に対してこれを強制しないので、 wchar_tストリングの配列がmain関数に渡され、それらをchar文字列として解釈するプログラムを取得します。

Unicodeが有効になっているときにWindowsが使用する文字セットであるUTF-16では、すべてのASCII文字は\0後にASCII値が続きます。

x86 CPUはリトルエンディアンであるため、これらのバイトの順序が入れ替えられ、ASCII値が最初に来てからヌルバイトが続くようになります。

そして、文字列では、通常どのように文字列が終了しますか? うん、ヌルバイト。 だからあなたのプログラムは1バイトごとにたくさんの文字列を見ています。

一般に、Windowsのプログラミングを行う場合、次の3つのオプションがあります。

  • Unicodeを明示的に使用します(wmainを呼び出し、char関連の引数を取るすべてのWindows API関数に対して-Wバージョンの関数を呼び出します)。CreateWindowの代わりにCreateWindowWを呼び出します。 そして、 char使用する代わりにwchar_tを使用するなど
  • 明示的にUnicodeを無効にします。 mainとCreateWindowAを呼び出し、文字列にcharを使用します。
  • 両方を許可する。 (main / _tmainおよびCreateWindowA / CreateWindowWに解決される_tmainおよびCreateWindowを呼び出す)、char / wchar_tの代わりにTCHARを使用します。

LPCTSTRはLPCSTRまたはLPCWSTRのいずれかに解決され、charまたはwchar_tを含む他のすべての型に対しては常に代わりに使用できる-T-バージョンが存在します。

これらはすべてMicrosoft固有のものであることに注意してください。 TCHARは標準のC ++型ではなく、windows.hで定義されているマクロです。 wmainと_tmainもMicrosoftによってのみ定義されています。


これをテンプレート化する少しの努力で、オブジェクトのリストを使って作業します。

#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';
}






arguments