C ++ में _tmain () और main () में क्या अंतर है?


224

अगर मैं अपना 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;
}

यह सिर्फ प्रत्येक तर्क का पहला चरित्र प्रदर्शित करता है।

इसके कारण क्या अंतर है?

जवाबों:


357

_tmainC ++ में मौजूद नहीं है। mainकर देता है।

_tmain एक Microsoft एक्सटेंशन है।

mainसी ++ मानक के अनुसार, कार्यक्रम का प्रवेश बिंदु है। इसके इन दो हस्ताक्षरों में से एक है:

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स्ट्रिंग्स के रूप में व्याख्या करता है ।

अब, यूटीएफ -16 में, यूनिकोड सक्षम होने पर विंडोज द्वारा उपयोग किया जाने वाला वर्ण, सभी ASCII वर्णों को \0ASCII मान के बाद बाइट्स की जोड़ी के रूप में दर्शाया जाता है ।

और चूंकि x86 CPU थोड़ा-सा एंडियन है, इसलिए इन बाइट्स का क्रम स्वैप किया जाता है, ताकि ASCII मान पहले आए, उसके बाद एक अशक्त बाइट।

और एक स्ट्रिंग स्ट्रिंग में, स्ट्रिंग को आमतौर पर कैसे समाप्त किया जाता है? हां, एक शून्य बाइट द्वारा। तो आपका कार्यक्रम स्ट्रिंग्स का एक गुच्छा देखता है, हर एक बाइट लंबी।

सामान्य तौर पर, विंडोज प्रोग्रामिंग करते समय आपके पास तीन विकल्प होते हैं:

  • स्पष्ट रूप से यूनिकोड का उपयोग करें (wmain को कॉल करें, और हर विंडोज एपीआई फ़ंक्शन के लिए जो चार-संबंधित तर्क लेता है, -Wफ़ंक्शन के संस्करण को कॉल करता है। CreateWindow के बजाय, CreateWindowW को कॉल करें)। और उपयोग करने के बजाए charउपयोग wchar_t, और इतने पर
  • स्पष्ट रूप से यूनिकोड को अक्षम करें। मुख्य कॉल करें, और CreateWindowA, और charस्ट्रिंग्स के लिए उपयोग करें ।
  • दोनों को अनुमति दें। (कॉल _tmain, और CreateWindow, जो मुख्य / _tmain और CreateWindowA / CreateWindowW को हल करते हैं), और char / wchar_t के बजाय TCHAR का उपयोग करें।

यह विंडोज़ .h द्वारा परिभाषित स्ट्रिंग प्रकारों पर लागू होता है: LPCTSTR, LPCSTR या LPCWSTR में से किसी एक के लिए हल होता है, और हर दूसरे प्रकार के लिए जिसमें char या wchar_t शामिल होता है, एक -T- संस्करण हमेशा मौजूद होता है जिसका उपयोग किया जा सकता है।

ध्यान दें कि यह सब Microsoft विशिष्ट है। TCHAR एक मानक C ++ प्रकार नहीं है, यह विंडोज़ में परिभाषित एक मैक्रो है। wmain और _tmain को भी केवल Microsoft द्वारा परिभाषित किया गया है।


6
मुझे आश्चर्य है कि क्या वे एक tcout भी प्रदान करते हैं? ताकि कोई बस tcout कर सके << argv [n]; और यह Ansi में cout करने और यूनिकोड मोड में wcout का समाधान करता है? मुझे संदेह है कि इस स्थिति में उसके लिए उपयोगी हो सकता है। और निश्चित रूप से, अच्छा जवाब :)
जोहान्स स्काउब -

1
UNICODE को अक्षम करने से क्या नुकसान होगा?
joshcomley

2
-1 सूचीबद्ध तीन विकल्पों में से कोई भी व्यावहारिक नहीं है। विंडोज को प्रोग्राम करने का व्यावहारिक तरीका परिभाषित करना है UNICODE। और सी ++ आदि के लिए कुछ अन्य समायोजन, शामिल करने से पहले <windows.h>। फिर यूनिकोड फ़ंक्शंस का उपयोग करें CreateWindow(सामान्य रूप Wसे अंत में कोई आवश्यकता नहीं )।
चीयर्स एंड हीथ। - अल्फ

11
आप वास्तव में इसे अधिक व्यावहारिक क्यों मानते हैं?
jalf

1
"__ tmain को भी केवल Microsoft द्वारा परिभाषित किया गया है " आपका अंतिम पैराग्राफ बिल्कुल गलत है , _tmain को RAD Studio के C ++ बिल्डर में बिल्कुल लागू किया गया है। वास्तव में, C ++ बिल्डर के डिफ़ॉल्ट _TCHAR मैपिंग के तहत , केवल मुख्य का उपयोग करना विफल हो जाएगा।
b1nary.atr0phy

35

_tmain एक मैक्रो है जिसे यूनिकोड या ASCII के साथ संकलित करने या न करने पर निर्भर करता है। यह एक Microsoft एक्सटेंशन है और किसी भी अन्य संकलक पर काम करने की गारंटी नहीं है।

सही घोषणा है

 int _tmain(int argc, _TCHAR *argv[]) 

यदि मैक्रो यूनिकोड को परिभाषित किया जाता है, तो इसका विस्तार होता है

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

या आप पहले से तय कर सकते हैं कि व्यापक या संकीर्ण वर्णों का उपयोग करना है या नहीं। :-)

अपडेट किया गया 12 नवंबर 2013:

पारंपरिक "TCHAR" को "_TCHAR" में बदल दिया जो नवीनतम फैशन लगता है। दोनों ठीक काम करते हैं।

अंत अद्यतन


1
"यह एक Microsoft एक्सटेंशन है और किसी भी अन्य संकलक पर काम नहीं करेगा।" जहाँ तक RAD Studio का सवाल है।
b1nary.atr0phy

@ b1naryatr0phy - बालों को विभाजित करने के लिए, "TCHAR" के बजाय "_TCHAR" का उपयोग करने के लिए आप जिस टूल से लिंक करते हैं, वह संगत नहीं है (हालांकि यह मेरे कथन को गलत साबित करता है)। हालाँकि मुझे कहना चाहिए था "यह एक Microsoft एक्सटेंशन है और किसी भी अन्य संकलक पर काम करने की गारंटी नहीं है।" मैं मूल में संशोधन करूंगा।
माइकल जे

@MichaelJ I मुख्य रूप से "कोड परिवर्तन ..." अनुभाग का उल्लेख कर रहा था, जो बताता है कि RAD Studio अब मुख्य के स्थान पर _tmain का उपयोग क्यों करता है, और वास्तव में अब यह Embarcadero के C ++ बिल्डर के लिए मानक डिफ़ॉल्ट है।
b1nary.atr0phy

1
यह दूसरी बार है कि हाल ही में इस चार साल पुराने उत्तर को अस्वीकार कर दिया गया है। यह अच्छा होगा यदि डाउनवोटर्स ने एक टिप्पणी की जो यह बताती है कि वे क्या समस्याएं महसूस करते हैं और (यदि संभव हो तो) उत्तर को कैसे सुधारें। b1naryatr0phy को एक बुरी तरह से लिखित वाक्य मिला, लेकिन मैंने तय किया कि मार्च में। किसी भी अपराध की सराहना की जाएगी।
माइकल जे

2
इसके लिए जीवन बहुत छोटा है।
माइकल जे।

10

_T कन्वेंशन का उपयोग यह इंगित करने के लिए किया जाता है कि प्रोग्राम को एप्लिकेशन के लिए परिभाषित वर्ण सेट (यूनिकोड, एएससीआईआई, एमबीसीएस, आदि) का उपयोग करना चाहिए। आप अपने तार को _T () के साथ घेर सकते हैं ताकि उन्हें सही प्रारूप में संग्रहीत किया जा सके।

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

वास्तव में, एमएस इस दृष्टिकोण की अनुशंसा करता है, afaik। आपके एप्लिकेशन को यूनिकोड-जागरूक बनाते हुए, वे इसे कहते हैं ... सभी स्ट्रिंग हेरफेर फ़ंक्शन के _t संस्करण का उपयोग करके, भी।
दीप-बी

1
@ डीप-बी: और विंडोज पर, यह है कि आप अपने आवेदन को यूनिकोड-रेडी कैसे बनाते हैं (मैं यूनिकोड-रेडी-टू-अनवे की अवधि को प्राथमिकता देता हूं), यदि यह charपहले से s पर आधारित था । आपके आवेदन सीधे का उपयोग करता है wchar_tतो आपके आवेदन है यूनिकोड।
पियरसबल

5
वैसे, यदि आप UNICODE पर संकलित करने का प्रयास करते हैं, तो आपका कोड आपके आउटपुट wchar_t के रूप में एक char-based cout के अंदर संकलित नहीं करेगा, जहाँ इसे wcout होना चाहिए था। एक "tcout" को परिभाषित करने का एक उदाहरण ... के लिए माइकल जे के जवाब देखें
paercebal

1
Microsoft द्वारा अनुशंसित कोई भी नहीं, बड़े पैमाने पर, क्योंकि यह स्पष्ट रूप से गलत है। यूनिकोड के लिए संकलन करते समय, कोड मानक आउटपुट स्ट्रीम के लिए पॉइंटर मान लिखता है। -1।
IInspectable

5

ठीक है, इस सवाल का उत्तर काफी अच्छी तरह से दिया गया है, UNICODE अधिभार को इसके दूसरे पैरामीटर के रूप में एक विस्तृत वर्ण सरणी लेना चाहिए। इसलिए यदि कमांड लाइन पैरामीटर वह है "Hello"जो संभवतः के रूप में समाप्त हो जाएगा "H\0e\0l\0l\0o\0\0\0"और आपका कार्यक्रम केवल 'H'यह प्रिंट करने से पहले यह देखेगा कि यह क्या सोचता है कि यह एक शून्य टर्मिनेटर है।

तो अब आप सोच सकते हैं कि यह संकलन और लिंक क्यों करता है।

खैर यह संकलित करता है क्योंकि आपको एक फ़ंक्शन पर एक अधिभार को परिभाषित करने की अनुमति है।

लिंकिंग थोड़ा अधिक जटिल मुद्दा है। सी में, कोई सजाया गया प्रतीक जानकारी नहीं है, इसलिए यह केवल एक फ़ंक्शन को बुलाता है जिसे मुख्य कहा जाता है। Argc और argv शायद हमेशा कॉल-स्टैक मापदंडों के रूप में होते हैं, भले ही आपका फ़ंक्शन उस हस्ताक्षर से परिभाषित किया गया हो, भले ही आपका फ़ंक्शन उन्हें अनदेखा करने के लिए हो।

भले ही सी ++ के पास प्रतीकों को सजाया गया हो, लेकिन यह निश्चित रूप से मुख्य के लिए सी-लिंकेज का उपयोग करता है, बजाय एक चतुर लिंकर के जो बदले में प्रत्येक को देखता है। तो यह आपके wmain पाया और यह int wmain(int, wchar_t*[])संस्करण है मामले में कॉल-स्टैक पर पैरामीटर डाल दिया ।


ठीक है, इसलिए मुझे अब सालों तक अपने कोड को विंडोज़ वाइडचेयर पर पोर्ट करने में समस्या है और यह पहली बार है जब मुझे समझ आया कि ऐसा क्यों होता है। यहाँ, मेरी सारी प्रतिष्ठा ले लो! हाहा
लियनेल

-1

इसे गति देने के थोड़े से प्रयास के साथ, यह वस्तुओं की किसी भी सूची के साथ काम करता है।

#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';
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.