2013-04-17 6 views
7

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

#include <iostream> 
#include <string> 
#include <vector> 
#include <stdlib.h> 

using namespace std; 

int main() 
{ 
    //this vector will store the integers 
    vector<int> a; 
    // this will store the user input 
    string inp; 
    getline(cin, inp); 
    // this string will temporarily store the digits 
    string tmp; 
    //be sure that the reading part is okay 
    cout << inp << endl; 
    //until you meet something different than a digit, read char by char and add to string 
    for(int i = 0; i < inp.length(); i++) 
    { 
     if(isdigit(inp[i])) 
     { 
      tmp +=inp[i]; 
     } 
     else 
     { 
      // when it is not a character, turn to integer, empty string 
      int value = atoi(tmp.c_str()); 
      a.push_back(value); 
      tmp = ""; 
     } 
    } 
    // paste the entire vector of integers 
    for(int i = 0; i < a.size(); i++) 
    { 
     cout << a[i] << endl; 
    } 
    return 0; 
} 
+0

कुछ उदाहरण इनपुट के लिए द्वारा for(int i = 0; i <inp.length(); i++)

, अपने अपेक्षित आउटपुट क्या है, और क्या आप वास्तव में देखते हैं? – BoBTFish

+0

यदि मैं "25 30 46" इनपुट करता हूं तो मुझे वेक्टर में 25 और 30 मिलेंगे, हालांकि स्ट्रिंग में "25 30 46" – Bloodcount

+0

आह होगा, मैंने देखा कि आपका मतलब सिर्फ एक लापता अंक था। – BoBTFish

उत्तर

3

में कुछ टिप्पणियाँ छोड़ दिया है लाइन के बहुत अंत एक अंक है, तो आप पिछले यात्रा पर else मारा नहीं है, और है कि पिछले संख्या कभी नहीं vector में धकेल दिया जाता है। सरल समाधान के पाश के बाद गैर-अंक तर्क को दोहराने के लिए होगा:

if (!tmp.empty()) // If tmp has content, we need to put it in the vector. 
{ 
     int value = atoi(tmp.c_str()); 
     a.push_back(value); 
     tmp = ""; 
} 

हालांकि मुझे यकीन है कि आप इसे की संरचना का एक अच्छा तरीका है के बारे में सोच सकता हूँ।

यहाँ एक संस्करण मैं std::stringstream का उपयोग कर, वह भी बचा जाता है के साथ आया है atoi:

int main() 
{ 
    std::vector<int> ints; 
    std::string line; 
    std::getline (std::cin, line); 
    std::cout << "Read \"" << line << "\"\n"; 
    std::stringstream ss(line); 

    int remaining = line.size(); 
    while (remaining) 
    { 
     if(std::isdigit(ss.peek())) // Read straight into an int 
     { 
      int tmp; 
      ss >> tmp; 
      ints.push_back(tmp); 
     } 
     else 
     { 
      ss.get(); // Eat useless characters 
     } 

     remaining = line.size()-ss.tellg(); 
    } 

    for (auto i : ints) 
     std::cout << i << '\n'; 

    return 0; 
} 

रनिंग:

$ ./a.out <<< "12 34 56" 
Read "12 34 56" 
12 
34 
56 

ध्यान दें, यह विशेष रूप से संख्याओं के बीच किसी भी पुराने निरर्थक शब्दों के साथ काम करने के लिए बनाया गया है :

$ ./a.out <<< "12-abc34-56" 
Read "12-abc34-56" 
12 
34 
56 

यदि केवल बी होगा ई व्हाइटस्पेस, यह भी आसान है, int एस stringstream से स्वचालित रूप से अनदेखा कर देगा। इस मामले में आपको बस इसकी आवश्यकता है:

int tmp; 
while (ss >> tmp) 
{ 
    ints.push_back(tmp); 
} 
+0

यह सही है। एक समाधान यह है कि इसे जोड़ने से पहले लाइन के अंत में यांत्रिक रूप से '' 'जोड़ना है। जब टाइमर मुझे चलो, तो मैं इसे एक उत्तर के रूप में चिह्नित करूंगा। धन्यवाद! – Bloodcount

1

आपके प्रोग्राम को एक स्ट्रिंग की आवश्यकता है जो सही तरीके से काम करने के लिए एक गैर-अंकों के चरित्र के साथ समाप्त हो। इस स्ट्रिंग को आजमाएं "1 12 14587 15" क्योंकि जब आप अंतिम स्थान भूल गए थे तो आपके एल्गोरिदम में, आपका प्रोग्राम संख्या को tmp स्ट्रिंग में संग्रहीत करता है लेकिन इसे वेक्टर में सहेजता नहीं है। इसे सही करने के लिए आपको अपने पहले लूप के बाद अंतिम push_back जोड़ने की आवश्यकता है।

1

आप a को केवल नए मान के साथ अपडेट करते हैं जब गैर अंक प्राप्त होता है। इस प्रकार यदि आपके पास अंकों के साथ स्ट्रिंग समाप्त हो रही है, तो tmp में डिजिटल स्ट्रिंग होगी लेकिन आप कभी भी ऐसा नहीं करेंगे जो push_back करना चाहिए। आप लूप

if(!tmp.empty()){ 
    // when it is not a character, turn to integer, empty string 
    int value = atoi(tmp.c_str()); 
    a.push_back(value); 
    tmp = ""; 
} 
0

के बाद निम्न कोड जोड़कर इसे ठीक कर सकते हैं आप कभी भी अपना अंतिम मूल्य वापस नहीं दबा सकते हैं। उदाहरण के लिए, इस इनपुट पर विचार करें

40 36 

फिर जब आप पढ़ रहे हों, तो आप पहली जगह पर वापस धक्का दें। लेकिन आप 36 को कभी नहीं दबाते हैं क्योंकि कोई और पात्र नहीं हैं। inp.push_back(' ')

1

पाश शुरू करने से पहले, स्ट्रिंग के लिए एक अंतरिक्ष जोड़ें:

अपने for() पाश के अंत के बाद आप इस कोशिश कर सकते हैं अंतिम अंक पढ़ने के बाद समाप्त हो गया है, इसलिए अंतिम अंक पूर्णांक में कभी नहीं बदला जाता है। लूप के लिए मूल के बाद बस कुछ कोड जोड़ें।

for(int i = 0; i < inp.length(); i++) 
{ 
    /* ...... */ 
} 
// add this to read the last digit 
if(tmp.length() > 0){ 
    int value = atoi(tmp.c_str()); 
    a.push_back(value); 
    tmp = ""; 
} 
1

आपका पाश: पिछले संख्या पुश करने के लिए सुनिश्चित करने के लिए

if(!tmp.empty()) { 
    a.push_back(tmp); 
} 
6

द्वारा

for(int i = 0; i <= inp.length(); i++) 

डेमो इस लाइन

for(int i = 0; i <inp.length(); i++)

बदलें IDEONE

अपने कोड के साथ समस्या है: उदाहरण में 25 30 46 जब भी i = 7, tmp = 46आप inp[8] के रूप में वेक्टर में 46 धक्का नहीं कर रहे हैं एक नई पंक्ति चरित्र है, इसलिए अपने लिए पाश के बाद मैं बन 7.

कृपया ध्यान दें समाप्त हो जाता है: मैं < = inp.length() के अधिकांश में पूरी तरह से चलाता है कंपाइलर्स को \ 0 के रूप में इस्तेमाल किया जाता है/सेंटीनेल के रूप में माना जाता है। हालांकि, कुछ कंपाइलर्स (जैसे माइक्रोसॉफ्ट विजुअल सी ++) हैं जो असर त्रुटि दिखा सकते हैं: स्ट्रिंग सबस्क्राइज़ रेंज से बाहर।

+1

हम्म +1, एक दिलचस्प चाल है, जिसे कभी भी '' 0'' को सेंटीनेल के रूप में उपयोग करने पर विचार नहीं किया जाता है। और यह भी पूरी तरह से अनुरूप है। लेकिन कोड में टिप्पणी प्रदान करना एक अच्छा विचार हो सकता है। – unkulunkulu

+0

@unkulunkulu: यह सी ++ 11 में अनुरूप है, हालांकि सी ++ 03 में मुझे संदेह है कि यह कानूनी था (स्ट्रिंग को शून्य-समाप्त करने की कोई गारंटी नहीं थी)।पूरी तरह से अनुरूप होने के लिए, आप 'c_str' कॉल के परिणाम पर सबस्क्रिप्ट का उपयोग कर सकते हैं। –

+0

@MatthieuM।, मुझे इसे ड्राफ्ट में नहीं मिला है (मैं वहां बहुत बुरी तरह से नेविगेट करता हूं), लेकिन मुझे कहीं और मिली जानकारी (cppreference) का अर्थ है कि 's.size()] == '\ 0'' _is_ गारंटी। यह गारंटी नहीं देता है कि '& s [0]' या 's.data()' शून्य समाप्त हो गया है। – unkulunkulu

0

जब अंतिम संख्या का अंतिम अंक tmp में संग्रहीत किया जाता है, उसके बाद लूप समाप्त होता है क्योंकि आपने पूरे स्ट्रिंग के अंतिम अक्षर को पढ़ लिया है। जब लूप समाप्त होता है तो अभी भी अंतिम संख्या होती है।

1) आप पाश के बाद वेक्टर में अंतिम संख्या को परिवर्तित और जोड़ सकते हैं। अंतिम संख्या अभी भी टीएमपी में उपलब्ध है।

2) या आप लूप से पहले स्ट्रिंग के अंत में स्पष्ट रूप से गैर-अंक वर्ण जोड़ सकते हैं।

0

आप इनपुट छोड़ दें। अपने कोड इस reflrct बदलें:

//this vector will store the integers 
    vector<int> a; 
    // this will store the user input 
    string inp; 
    getline(cin, inp); 
    // this string will temporarily store the digits 
    string tmp; 
    //be sure that the reading part is okay 
    cout << inp << endl; 
    //until you meet something different than a digit, read char by char and add to string 
    for(int i = 0; i < inp.length(); i++) 
    { 
     if(isdigit(inp[i])) 
     { 
      tmp =inp[i]; 
      int value = atoi(tmp.c_str()); 
      a.push_back(value); 
     } 
     else 
     { 
      tmp = ""; 
     } 
    } 
    // paste the entire vector of integers 
    for(int i = 0; i < a.size(); i++) 
    { 
     cout << a[i] << endl; 
    } 
    return 0; 

या पाश में बदल देते हैं:

for(int i = 0; i <= inp.length(); i++) 
संबंधित मुद्दे