केवल एक वर्ण को पढ़ने के लिए getchar () के साथ Enter दबाने से कैसे बचें?


80

अगले कोड में:

मुझे उन Enterसभी पत्रों को प्रिंट करने के लिए प्रेस करना होगा जिन्हें मैंने दर्ज किया था getchar, लेकिन मैं ऐसा नहीं करना चाहता, जो मैं करना चाहता हूं वह पत्र को प्रेस करना है और तुरंत उस पत्र को देखना है जिसे मैंने बिना दबाए दोहराया Enter। उदाहरण के लिए, यदि मैं 'a' अक्षर को दबाता हूं, तो मैं उसके बगल में एक 'a' देखना चाहता हूं, और इसी तरह:

लेकिन जब मैं 'a' प्रेस करता हूं तो कुछ नहीं होता है, मैं अन्य पत्र लिख सकता हूं और कॉपी तभी दिखाई देती है जब मैं प्रेस करता हूं Enter:

मैं यह कैसे कर सकता हूँ?

मैं cc -o example example.cसंकलन के लिए Ubuntu के तहत कमांड का उपयोग कर रहा हूं ।


5
यह बहुत निर्भर करता है कि आपका ओएस और टर्मिनल प्रक्रिया इनपुट कैसे है। यदि आप अपना ऑपरेटिंग वातावरण निर्दिष्ट करते हैं, तो आपको संभवतः बेहतर उत्तर मिलेंगे।
GoldPseudo

WinplusI का उपयोग करके विंडोज़ पर cplusplus.com/forum/articles/19975 पर दिया गया उत्तर काम करता है।

जवाबों:


72

एक लिनक्स सिस्टम पर, आप sttyकमांड का उपयोग करके टर्मिनल व्यवहार को संशोधित कर सकते हैं । डिफ़ॉल्ट रूप से, टर्मिनल सभी सूचनाओं को तब तक Enterदबाए रखेगा, जब तक कि उसे C प्रोग्राम में भेजने से पहले।

प्रोग्राम के भीतर से ही व्यवहार को बदलने के लिए एक त्वरित, गंदा और विशेष रूप से पोर्टेबल उदाहरण:

कृपया ध्यान दें कि यह वास्तव में इष्टतम नहीं है, क्योंकि यह मान लेता है कि stty cookedयह वही व्यवहार है जो आप चाहते हैं कि कार्यक्रम से बाहर निकलते समय, मूल टर्मिनल सेटिंग्स क्या थीं, यह जाँचने के बजाय। इसके अलावा, चूंकि सभी विशेष प्रसंस्करण कच्चे मोड में छोड़ दिए जाते हैं, इसलिए कई महत्वपूर्ण अनुक्रम (जैसे कि CTRL-C या CTRL-D ) वास्तव में काम नहीं करेंगे क्योंकि आप उन्हें कार्यक्रम में स्पष्ट रूप से संसाधित किए बिना उम्मीद करते हैं।

आप man sttyटर्मिनल व्यवहार पर अधिक नियंत्रण के लिए, वास्तव में आप क्या हासिल करना चाहते हैं पर निर्भर करता है।


का उपयोग करना systemएक बुरा विचार है।
Sapphire_Brick

बहुत अधिक कच्चा .... मैं एक ऐसे समाधान की खोज कर रहा था जो मुझे ENTER की प्रतीक्षा न कर सके। यह समाधान सभी इनपुट टर्मिनल कार्यात्मकताओं को तोड़ता है।
एबीसी

93

यह आपके OS पर निर्भर करता है, यदि आप UNIX में हैं जैसे वातावरण ICANON ध्वज डिफ़ॉल्ट रूप से सक्षम है, इसलिए इनपुट अगले '\n'या जब तक बफ़र्ड है EOF। विहित मोड को अक्षम करने से आपको वर्ण तुरंत मिलेंगे। यह अन्य प्लेटफार्मों पर भी संभव है, लेकिन सीधे आगे क्रॉस-प्लेटफॉर्म समाधान नहीं है।

संपादित करें: मैं आपको निर्दिष्ट करता हूं कि आप उबंटू का उपयोग करते हैं। मैंने कल ही कुछ ऐसा ही पोस्ट किया था, लेकिन ध्यान रहे कि यह आपके टर्मिनल के कई डिफ़ॉल्ट व्यवहारों को निष्क्रिय कर देगा।

आप देखेंगे, कि हर चरित्र दो बार दिखाई देता है। इसका कारण यह है कि इनपुट तुरंत टर्मिनल पर वापस गूँज जाता है और फिर आपका प्रोग्राम इसे putchar()भी वापस रख देता है। यदि आप आउटपुट से इनपुट को अलग करना चाहते हैं, तो आपको ईसीएचओ का झंडा भी बदलना होगा। आप इसे केवल उपयुक्त पंक्ति को बदलकर ऐसा कर सकते हैं:


9
+1 यद्यपि tbh, यह शायद मूल पोस्टर के कोड के स्तर के साथ सहज नहीं है;)
Andomar

2
महान! यही मैं ढूंढ रहा था!
डेनिल्सन सा माआ

विस्तृत टिप्पणियों के साथ मदद के लिए धन्यवाद, इसने मेरी समस्या हल कर दी।
विटामिन ए

यह अविश्वसनीय है कि इतना बुनियादी कुछ हासिल करना मुश्किल है और गैर पोर्टेबल।
पेड्रो77

12

getchar () एक मानक फ़ंक्शन है जो कई प्लेटफार्मों पर आपको इनपुट प्राप्त करने के लिए ENTER दबाने की आवश्यकता होती है, क्योंकि प्लेटफ़ॉर्म बफर इनपुट तब तक होता है जब तक कि कुंजी दबाया नहीं जाता है। कई कंपाइलर / प्लेटफ़ॉर्म गैर-मानक getch () का समर्थन करते हैं जो ENTER की परवाह नहीं करता है (प्लेटफ़ॉर्म बफरिंग को बायपास करता है, ENTER को सिर्फ दूसरी कुंजी की तरह मानता है)।


1
+1 सही, getchar()आपके द्वारा एंटर दबाने के बाद ही कैरेक्टर को एक-एक करके पढ़ना शुरू किया जाता है
एंडोमर

32
getchar()ENTER के बारे में परवाह नहीं है, यह सिर्फ वही करता है जो स्टड के माध्यम से आता है। लाइन बफ़रिंग ओएस / टर्मिनल परिभाषित व्यवहार करता है।
GoldPseudo

1
@goldPseudo: यह सच है, लेकिन लगभग सभी प्लेटफ़ॉर्म बफर इनपुट हैं, इसलिए यह वह व्यवहार है जिसे आप अधिकांश व्यावहारिक मामलों में देखेंगे। getch (), जहाँ समर्थित है, या तो बफ़रिंग को प्रबंधित या अनदेखा करेगा। मुझे पता है कि कुछ पुराने डॉस कार्यान्वयन हार्डवेयर के साथ सीधे बातचीत करने के लिए ओएस बफरिंग को बायपास करते हैं। अन्य कार्यान्वयन समान व्यवहार प्राप्त करने के लिए स्टड फ्लश कर सकते हैं।
एरिक जे।

10
बहरहाल, ऐसा नहीं है getchar()कि "आपको एंटर प्रेस करने की आवश्यकता है", लेकिन पर्यावरण।
बेंजी XVI

1
बहुत संक्षिप्त और समझने में आसान। अन्य टॉप रेटेड उत्तर केवल अनावश्यक तकनीकी विवरणों के बारे में बताते हैं।
mzoz

6

I / O एक ऑपरेटिंग सिस्टम फ़ंक्शन है। कई मामलों में, ऑपरेटिंग सिस्टम किसी प्रोग्राम में टाइप किए गए कैरेक्टर को तब तक पास नहीं करेगा जब तक कि एंटर दबाया न जाए। यह उपयोगकर्ता को प्रोग्राम को भेजने से पहले इनपुट (जैसे बैकस्पेसिंग और रिटाइपिंग) को संशोधित करने की अनुमति देता है। अधिकांश उद्देश्यों के लिए, यह अच्छी तरह से काम करता है, उपयोगकर्ता के लिए एक सुसंगत इंटरफ़ेस प्रस्तुत करता है, और इस से निपटने के लिए कार्यक्रम से राहत देता है। कुछ मामलों में, कुंजी से वर्ण प्राप्त करने के लिए एक कार्यक्रम के लिए यह वांछनीय है क्योंकि वे दबाए जाते हैं।

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

इसके अलावा, मानक उत्पादन आम तौर पर दक्षता के लिए बफ़र किया जाता है। यह सी पुस्तकालयों द्वारा किया जाता है, और इसलिए एक सी समाधान है, जो fflush(stdout);प्रत्येक वर्ण के लिखे जाने के बाद है। उसके बाद, चाहे वर्ण तुरंत ऑपरेटिंग सिस्टम पर प्रदर्शित होते हैं, लेकिन मैं जिन सभी OS से परिचित हूं, वे तुरंत आउटपुट प्रदर्शित करेंगे, इसलिए यह आमतौर पर कोई समस्या नहीं है।


6

मुझे लुकास जवाब पसंद है, लेकिन मैं इसे थोड़ा विस्तार देना चाहूंगा। वहाँ एक अंतर्निहित है समारोह में termios.hनामित किया गया cfmakeraw()है जो आदमी के रूप में वर्णन करता है:

यह मूल रूप से लुकास द्वारा सुझाए गए और अधिक के समान है, आप सटीक झंडे इसे मैन पेजों में देख सकते हैं: टर्मिनस (3)

उदाहरण


ध्यान दें कि POSIX केcfmakeraw() लिए एक गैर-पोर्टेबल, गैर-मानक विस्तार है और आवश्यक रूप से उपलब्ध नहीं है। termios.h
एंड्रयू हेनले

4

चूँकि आप एक यूनिक्स व्युत्पन्न (उबंटू) पर काम कर रहे हैं, यहाँ एक तरीका यह है - अनुशंसित नहीं है, लेकिन यह तब तक काम करेगा (जब तक आप सही तरीके से कमांड टाइप कर सकते हैं):

जब आप इससे ऊब चुके हों तो प्रोग्राम को रोकने के लिए इंटरप्ट का उपयोग करें।

  • 'इको' लाइन वर्तमान टर्मिनल सेटिंग्स को शेल स्क्रिप्ट के रूप में सहेजती है जो उन्हें पुनर्स्थापित करेगी।
  • 'स्टिकी' लाइन अधिकांश विशेष प्रसंस्करण को बंद कर देती है (इसलिए Control-Dइसका कोई प्रभाव नहीं है, उदाहरण के लिए) और जैसे ही वे उपलब्ध होते हैं, कार्यक्रम में वर्ण भेजते हैं। इसका मतलब है कि आप अपने टाइपिंग को और अधिक संपादित नहीं कर सकते।
  • 'Sh' लाइन आपकी मूल टर्मिनल सेटिंग्स को बहाल करती है।

यदि 'स्टेंट साने' आपकी सेटिंग्स को आपके उद्देश्यों के लिए पर्याप्त रूप से सही ढंग से पुनर्स्थापित करता है, तो आप इसका अर्थ लगा सकते हैं। '-G ’का प्रारूप (स्ट्टी’ के संस्करणों के पार पोर्टेबल नहीं है (इसलिए सोलारिस 10 पर जो उत्पन्न होता है वह लिनक्स, या इसके विपरीत काम नहीं करेगा), लेकिन अवधारणा हर जगह काम करती है। 'स्टेंट साने' विकल्प सार्वभौमिक रूप से उपलब्ध नहीं है, AFAIK (लेकिन लिनक्स पर है)।


2

आप 'ncurses' लाइब्रेरी शामिल कर सकते हैं, और getch()इसके बजाय उपयोग कर सकते हैं getchar()


1

हाँ, आप इसे विंडोज़ पर भी कर सकते हैं, यहाँ नीचे दिया गया कोड है, जो conio.h लाइब्रेरी का उपयोग कर रहा है


6
प्रश्न को सी के साथ टैग किया गया है , न कि c ++
Spikatrix

@CoolGuy तो क्या? यदि किसी ने ठीक उसी प्रश्न को खोला है, तो यह किसी की मदद क्यों करेगा, लेकिन टैग को c से c ++ में बदल दिया?
एंड्रियास हेफरबर्ग

@AndreasHaferburg क्योंकि हमारे यहाँ C ++ के उत्तर नहीं होंगे, विशेष रूप से खराब लिखे गए, पलक झपकते नहीं
Sapphire_Brick

1

मुझे यह समस्या / प्रश्न एक असाइनमेंट में आया है जो मैं वर्तमान में काम कर रहा हूं। यह इस बात पर भी निर्भर करता है कि आप किस इनपुट से हड़प रहे हैं। मै इस्तेमाल कर रहा हूँ

प्रोग्राम चलने के दौरान इनपुट प्राप्त करने के लिए, ताकि कमांड से जुड़ी फाइलस्ट्रीम की आवश्यकता हो।

उबंटू मशीन पर मुझे परीक्षण / लक्ष्य करना है, इसके लिए बस आवश्यकता से अधिक की आवश्यकता है

या

मुझे --फाइल ध्वज, साथ ही कमांड के लिए रास्ता जोड़ना था, जैसे:

सब कुछ अब कापसी है।


2
कृपया ध्यान दें कि यह समाधान ओएस पर निर्भर है।
ओटावियो कैम्पाना

0

इस कोड ने मेरे लिए काम किया। ध्यान दें: यह मानक पुस्तकालय का हिस्सा नहीं है, भले ही अधिकांश कंपाइलर (मैं जीसीसी का उपयोग करता हूं) इसका समर्थन करता है।

यह कोड पहली कुंजी प्रेस का पता लगाता है।


0

" कैसे दबाने से बचने के लिए Enterके साथ getchar()? "

सबसे पहले, टर्मिनल इनपुट या तो लाइन या पूरी तरह से बफर होता है। इसका मतलब है कि ऑपरेशन सिस्टम टर्मिनल से वास्तविक इनपुट को एक बफर में संग्रहीत करता है। आमतौर पर इस बफ़र को प्रोग्राम में फ़्लश किया जाता है जब फ़े \nको संकेतित किया जाता है / प्रदान किया जाता है stdin। यह एक प्रेस द्वारा बनाई गई fe है Enter

getchar()श्रृंखला के अंत में है। यह वास्तव में बफरिंग प्रक्रिया को प्रभावित करने की कोई क्षमता नहीं है।


" मैं यह कैसे कर सकता हूं? "

getchar()पहली जगह में खाई , यदि आप टर्मिनल के व्यवहार को स्पष्ट रूप से बदलने के लिए विशिष्ट प्रणाली कॉल का उपयोग नहीं करना चाहते हैं जैसे कि अन्य उत्तर में अच्छी तरह से समझाया गया है।

दुर्भाग्य से कोई मानक पुस्तकालय फ़ंक्शन नहीं है और इसके साथ ही एकल चरित्र इनपुट पर बफर को फ्लश करने का कोई पोर्टेबल तरीका नहीं है। हालांकि, कार्यान्वयन-आधारित और गैर-पोर्टेबल समाधान हैं।


विंडोज / एमएस-डॉस में, हेडर फ़ाइल में फ़ंक्शन getch()और getche()फ़ंक्शन होते हैं conio.h, जो बिल्कुल वही काम करते हैं जो आप चाहते हैं - बफर को फ्लश करने के लिए नई लाइन की प्रतीक्षा करने की आवश्यकता के बिना एक भी चरित्र पढ़ें।

के बीच मुख्य अंतर getch()और getche()वह यह है कि getch()जबकि, कंसोल में नहीं तुरंत उत्पादन वास्तविक इनपुट चरित्र करता getche()है। प्रतिध्वनि"e" के लिए अतिरिक्त खड़ा है ।

उदाहरण:


लिनक्स, प्रत्यक्ष चरित्र प्रसंस्करण और उत्पादन प्राप्त करने के लिए एक तरह से उपयोग करने के लिए है cbreak()और echo()विकल्प और getch()और refresh()ncurses-पुस्तकालय में दिनचर्या।

ध्यान दें, कि आपको तथाकथित मानक स्क्रीन को आरंभीकरण के साथ initscr()बंद करने की आवश्यकता है endwin()

उदाहरण:


नोट: आपको -lncursesविकल्प के साथ कंपाइलर को आमंत्रित करना होगा , ताकि लिंकर ncurses-Library को खोज सके और खोज सके।


-1

डिफ़ॉल्ट रूप से, C लाइब्रेरी आउटपुट को तब तक बफ़र करती है जब तक कि वह रिटर्न नहीं देखता। तुरंत परिणाम जानने के लिए, उपयोग करें fflush:


2
हालाँकि, आउटपुट समस्या का हिस्सा है। प्रश्नकर्ता प्रोग्राम रीड कीज़ को रखना चाहता है क्योंकि उन्हें दबाया जाता है और स्क्रीन पर तुरंत प्रिंट किया जाता है। यह एक इनपुट और आउटपुट इश्यू दोनों है।
डेविड थॉर्नले

यानी एफफ्लश केवल आउटपुट को फ्लश करता है, लेकिन कुंजी दबाए जाने के बाद गेटचर्स फिर भी वापस नहीं आएगा (चाबियाँ बफ़र की जाएगी)।
निकोफ्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.