2012-03-09 11 views
43

मैं एक असाइनमेंट कर रहा हूं जहां हमें किसी फ़ाइल से स्ट्रिंग की श्रृंखला को सरणी में पढ़ना होगा। मुझे सरणी पर एक सिफर एल्गोरिदम कॉल करना है (सिफर ट्रांसफर 2 डी सरणी)। तो, सबसे पहले मैंने फ़ाइल से सभी जानकारी को 2 डी सरणी में डाल दिया, लेकिन मुझे अपने शेष कोड में विवादित प्रकारों के साथ बहुत परेशानी थी (विशेष रूप से चार [] को char * सेट करने की कोशिश कर रहा था)। इसलिए, मैंने पॉइंटर्स की एक सरणी पर स्विच करने का फैसला किया, जिसने मेरे अधिकांश कोड में सब कुछ बहुत आसान बना दिया।क्या सी में char [] से char * को परिवर्तित करना संभव है?

लेकिन अब मुझे char * को char [] और फिर से परिवर्तित करने की आवश्यकता है, लेकिन मैं इसे समझ नहीं सकता। मैं Google पर कुछ भी नहीं ढूंढ पा रहा हूं। मुझे आश्चर्य हो रहा है कि यह भी संभव है।

+1

[comp.lang.c FAQ] (http://c-faq.com/) के अनुभाग 6 पढ़ें। –

उत्तर

87

ऐसा लगता है जैसे आप पॉइंटर्स और सरणी के बीच उलझन में हैं। संकेत और सरणियों (इस मामले char * और char [] में) कर रहे हैं not the same thing.

  • एक सरणी char a[SIZE] का कहना है कि a के स्थान पर मूल्य लंबाई की एक सरणी SIZE
  • एक संकेतक char *a; कहते है उस स्थान पर मूल्य achar पर एक सूचक है।

    char a[] = "hello"; // array 
    
        +---+---+---+---+---+---+ 
    a: | h | e | l | l | o |\0 | 
        +---+---+---+---+---+---+ 
    
    char *p = "world"; // pointer 
    
        +-----+  +---+---+---+---+---+---+ 
    p: | *======> | w | o | r | l | d |\0 | 
        +-----+  +---+---+---+---+---+---+ 
    
    : यह एक सरणी की तरह व्यवहार करने के लिए सूचक अंकगणित साथ जोड़ा जा सकता

स्मृति में, यह इस तरह से (उदाहरण के the FAQ से लिया गया) लग रहा है (जैसे, a[10] अतीत जहाँ भी a अंक 10 प्रविष्टियों है)

पॉइंटर्स और सरणी के बीच के अंतर के बारे में भ्रमित होना आसान है, क्योंकि कई मामलों में, एक सरणी संदर्भ के पहले तत्व के लिए "decays" संदर्भ देता है। इसका मतलब है कि कई मामलों में (जैसे कि जब फंक्शन कॉल में पास किया जाता है) सरणी पॉइंटर्स बन जाती है। यदि आप और जानना चाहते हैं, this section of the C FAQ describes the differences in detail

एक प्रमुख व्यावहारिक अंतर यह है कि संकलक जानता है कि एक सरणी कितनी देर तक है। उपरोक्त उदाहरण का उपयोग करना:

char a[] = "hello"; 
char *p = "world"; 

sizeof(a); // 6 - one byte for each character in the string, 
      // one for the '\0' terminator 
sizeof(p); // whatever the size of the pointer is 
      // probably 4 or 8 on most machines (depending on whether it's a 
      // 32 or 64 bit machine) 

अपने कोड को देखने के बिना, यह सर्वोत्तम कदम की सिफारिश करने के लिए मुश्किल है, लेकिन मैं हर जगह संकेत का उपयोग करने के लिए समस्या यदि आप वर्तमान में हो रही हैं, समाधान होगा बदलते संदेह है।ध्यान दें कि अब:

  • जहां भी सरणी होती थी, आपको स्मृति को प्रारंभ करने की आवश्यकता होगी। उदाहरण के लिए, char a[10];char *a = malloc(10 * sizeof(char)); बन जाएगा, इसके बाद a != NULL पर एक चेक होगा। ध्यान दें कि आपको इस मामले में sizeof(char) कहने की ज़रूरत नहीं है, क्योंकि sizeof(char) को 1 के रूप में परिभाषित किया गया है। मैंने इसे पूर्णता के लिए छोड़ दिया है।

  • कहीं भी आपने पहले सरणी लंबाई के लिए sizeof(a) था (आप तार का उपयोग कर रहे हैं, तो आप strlen() इस्तेमाल कर सकते हैं, जो '\0' अप करने के लिए मायने रखता है) स्मृति आप आवंटित की लंबाई से प्रतिस्थापित करने की आवश्यकता होगी।

  • आपको प्रत्येक कॉल के लिए पर free() पर एक संबंधित कॉल करने की आवश्यकता होगी। यह उस कंप्यूटर को बताता है जिसे आपने malloc() के साथ मांगी गई स्मृति का उपयोग करके किया है। यदि आपका सूचक a है, तो कोड में एक बिंदु पर बस free(a); लिखें जहां आप जानते हैं कि अब आपको a अंक की आवश्यकता नहीं है।

एक और जवाब के रूप में बताया, तो आप एक सरणी की शुरुआत का पता प्राप्त करना चाहते हैं, आप का उपयोग कर सकते हैं:

char* p = &a[0] 

आप के रूप में "चार सूचक p पता बन जाता है यह पढ़ सकते हैं तत्व [0]a "।

+7

+1 ग्रेट उत्तर –

+0

अंतिम उदाहरण में, 'char * p = और a [0]' को 'char * p = और एक '? –

+1

@thom_nic: नहीं, क्योंकि '& a' में 'char (*) [6]' यानी, छह वर्णों की एक सरणी के लिए एक सूचक है। यह 'char *' जैसा नहीं है, इसलिए आपको एक चेतावनी मिलेगी। हालांकि, आप 'char * p = a;' कह सकते हैं, क्योंकि एक सरणी संदर्भ [अपने पहले तत्व में पॉइंटर में क्षय हो सकता है] (http://c-faq.com/aryptr/aryptrequiv.html)। मैंने यहां लंबा फॉर्म इस्तेमाल किया, क्योंकि यह बेहतर होता है कि क्या हो रहा है। –

9

यदि आप char[] c तो आप char* d = &c[0] और पहुँच तत्व कर सकते हैं ग [1] *(d+1) करके, आदि

+0

ओह, धन्यवाद! मैं कोशिश करूँगा। – tparf

+0

या आप केवल 'char * d = c; 'कर सकते हैं। – mah

-4

ठीक है, मैं नहीं अपने प्रश्न को समझने के लिए यकीन है कि है ...

सी में, चार [] और चार * एक ही चीज़ हैं।

संपादित करें: इस दिलचस्प लिंक के लिए धन्यवाद।

+2

मुझे डर है कि यह सच नहीं है - [पॉइंटर्स और एरे सी में समान नहीं हैं] (http://www.lysator.liu.se/c/c-faq/c-2.html) –

+0

मैंने ऐसा सोचा भी, लेकिन संकलक मुझे एक त्रुटि दे रहा है :( – tparf

+0

@ टिमोथी जोन्स: एफएक्यू के लिए एक बेहतर लिंक http://c-faq.com/ है और निश्चित रूप से आप 100% सही हैं: सरणी और पॉइंटर्स * नहीं हैं * वही बात। (और यह 'char'' लिखा गया है, न कि 'Char'; यह मायने रखता है।) –

2

यदि आप उन्हें पॉइंटर्स के रूप में उपयोग करना चाहते हैं तो आपको उन्हें सरणी के रूप में घोषित करने की आवश्यकता नहीं है। आप बस पॉइंटर्स को संदर्भित कर सकते हैं जैसे कि वे बहु-आयामी सरणी थे। बस एक सूचक के सूचक के रूप में यह बना सकते हैं और malloc का उपयोग करें:

int i; 
int M=30, N=25; 
int ** buf; 
buf = (int**) malloc(M * sizeof(int*)); 
for(i=0;i<M;i++) 
    buf[i] = (int*) malloc(N * sizeof(int)); 

और फिर आप संदर्भित कर सकते हैं buf[3][5] या जो कुछ भी।

+3

'malloc()' के परिणाम न डालें। –

+0

यह आवश्यक है क्योंकि 'malloc()' 'void *' देता है, जिसे 'buf' में संग्रहीत करने के लिए 'int *' पर डाला जाना आवश्यक है। – Arcinde

+4

नहीं, कास्ट आवश्यक नहीं है। सी में, प्रकार 'शून्य *' की अभिव्यक्ति को किसी भी पॉइंटर-टू-ऑब्जेक्ट (या पॉइंटर-टू-अपूर्ण) प्रकार में स्पष्ट रूप से परिवर्तित किया जा सकता है। [Comp.lang.c FAQ] (http://c-faq.com/) के प्रश्न 7.7b और [सी मानक] के अनुभाग 6.5.16.1 देखें (http://www.open-std.org/ jtc1/sc22/wg14/www/डॉक्स/n1570.pdf)। (सी ++ में अलग-अलग नियम हैं, जो कि यदि हम सी ++ पर चर्चा कर रहे थे तो प्रासंगिक होगा।) –

संबंधित मुद्दे