2017-12-12 157 views
7

fscanf() एक साधन लिखने के लिए "अब तक fscanf समारोह को यह कॉल द्वारा इनपुट स्ट्रीम से पढ़ने वर्णों की संख्या" के रूप में "%n" निर्देश निर्दिष्ट करता C11dr §7.21.6.2 12.fscanf में "वर्णों की संख्या पढ़ने" की सीमा क्या है?

हमें इस नंबर पर कॉल करते हैं: ncount


"%n" निर्देश लंबाई संशोधक hh, h, l, ll, j और पूर्व अन्य लोगों द्वारा किया जा सकता है। उदाहरण:

FILE *stream = stdin; 
int n_i; 
fscanf(stream, "%*s%n", &n_i); // save as int 
signed char n_hh; 
fscanf(stream, "%*s%hhn", &n_hh); // save as signed char 
long long n_ll; 
fscanf(stream, "%*s%lln", &n_ll); // save as long long 

प्रकार या ncount के न्यूनतम उम्मीद सीमा क्या है?
क्या होता है, या तब होना चाहिए, जब "इनपुट स्ट्रीम से वर्णित वर्णों की संख्या" बड़ा है?

मेरे निष्कर्ष:
सी कल्पना ncount की न्यूनतम सीमा/प्रकार की परिभाषा पर शांत दिखाई देता है। ncount आमतौर पर "%n" के माध्यम से सहेजा जाता है जो intगंतव्य निर्दिष्ट करता है हालांकि intस्रोत नहीं है।

प्रयोग करके, ncount को मेरे प्लेटफ़ॉर्म पर int या long जैसा माना जाता है - कोई वास्तविक आश्चर्य नहीं है। (मेरा int/long/long long 4/4/8 बाइट्स है।) ncount को long long पर सहेजते समय, बचाया गया मान INT_MAX/LONG_MAX से अधिक नहीं है। ncountunsignedlong long पर असाइन किए जाने पर उपयोग करने योग्य सीमा से दोगुनी हो सकती है, फिर भी, यह एक चरम कोने है और शायद कार्यान्वयनकर्ताओं द्वारा नहीं माना जाता है।

नीचे दिए गए मेरे परीक्षणों में ncountint रेंज के बाद के रूप में सहेजे जाने पर भी विस्तारित सीमा दिखाई नहीं दी गई है।

मेरी रुचि एक (चरम) रेखा लंबाई निर्धारित करने के लिए "%*[^\n]%lln" का उपयोग करने से उत्पन्न हुई।


कार्यान्वयन नोट:

जीएनयू सी 11 (जीसीसी) संस्करण 6.4.0 (i686-पीसी-cygwin) GNU सी संस्करण 6.4.0, जीएमपी संस्करण 6.1.2, MPFR संस्करण 3.1.5 द्वारा संकलित -पी 10, एमपीसी संस्करण 1.0.3, आईएसएल संस्करण 0.14 या 0.13

glibc 2.26 जारी किया गया।

इंटेल जिऑन W3530, 64-बिट ऑपरेटिंग सिस्टम (विंडोज 7)


टेस्ट कोड

#include <limits.h> 
#include <stdio.h> 
#include <string.h> 

int print(FILE *stream, long long size, int ch) { 
    char buf[4096]; 
    memset(buf, ch, sizeof buf); 
    while (size > 0) { 
    size_t len = size < (long long) sizeof buf ? (size_t) size : sizeof buf; 
    size_t y = fwrite(buf, 1, len, stream); 
    if (len != y) { 
     perror("printf"); 
     return 1; 
    } 
    size -= len; 
    } 
    return 0; 
} 

int scan(FILE *stream) { 
    rewind(stream); 
    long long n = -42; 
    int cnt = fscanf(stream, "%*s%lln", &n); 
    printf("cnt:%d n:%lld ", cnt, n); 
    return cnt != 0; 
} 

int testf(long long n) { 
    printf("%10lld ", n); 
    FILE *f = fopen("x.txt", "w+b"); 
    if (f == NULL) { 
    perror("fopen"); 
    return 1; 
    } 
    if (print(f, n, 'x')) { 
    perror("print"); 
    fclose(f); 
    return 2; 
    } 
    if (scan(f)) { 
    perror("scan"); 
    fclose(f); 
    return 3; 
    } 
    fclose(f); 
    puts("OK"); 
    fflush(stdout); 
    return 0; 
} 

int main(void) { 
    printf("%d %ld %lld\n", INT_MAX, LONG_MAX, LLONG_MAX); 
    testf(1000); 
    testf(1000000); 
    testf(INT_MAX); 
    testf(INT_MAX + 1LL); 
    testf(UINT_MAX); 
    testf(UINT_MAX + 1LL); 
    testf(1); 
    return 0; 
} 

टेस्ट उत्पादन

2147483647 2147483647 9223372036854775807 

File length  Reported bytes read 
     1000 cnt:0 n:1000 OK 
    1000000 cnt:0 n:1000000 OK 
2147483647 cnt:0 n:2147483647 OK 
2147483648 cnt:0 n:-2147483648 OK // implies ncount is internally an `int/long` 
4294967295 cnt:0 n:-1 OK 
4294967296 cnt:0 n:-1088421888 OK // This `n` value may not be consistent. -1 also seen 
     1 cnt:0 n:1 OK 

[संपादित करें]

कुछ के साथके रन 10, मुझे अन्य असंगत परिणाम जैसे '42 9 4 9 672 9 6 सीएनटी: 0 एन: 1239482368 ओके' मिला। Hmmmm।

नमूना fscanf()support source codencount के लिए int का उपयोग करता है।

+0

मैंने एक दिलचस्प प्रश्न के लिए वोटिंग के बीच संघर्ष किया और मतदान नहीं किया क्योंकि, यदि आपका इनपुट विदेशी है, तो आपको अपना खुद का पार्सिंग लिखना चाहिए और 'fscanf' का उपयोग नहीं करना चाहिए। फिर भी, मुझे उम्मीद है कि उत्तर सी 2011 5.2.4.1 है: "कार्यान्वयन कम से कम एक कार्यक्रम का अनुवाद और निष्पादन करने में सक्षम होगा ..." आपका कार्यक्रम वह नहीं है। –

+1

मैं मानक के आपके विश्लेषण से सहमत हूं। यह इस बात पर बाध्य नहीं करता है कि 'ncount' कितना बड़ा होना चाहिए। यह निर्दिष्ट करता है कि 'll' (और' z' और 't') लंबाई विनिर्देशक 'n' निर्देश में प्रकट हो सकते हैं, और निश्चित रूप से आप सही हैं कि प्राप्त करने वाले चर के आकार का वर्णन करता है, स्रोत संख्या नहीं । –

+0

@EricPostpischil 'fscanf()' का उपयोग पढ़ने से पहले नहीं जानता है कि इनपुट विदेशी है या नहीं। मुद्दा यह नहीं है कि इनपुट विदेशी है, लेकिन '% * s% n" 'विदेशी इनपुट के लिए लचीला नहीं है। उदाहरण के लिए, '"% 1000s% n "' विदेशी इनपुट के साथ काम करेगा - जब तक 'ncount' कम से कम 10 बिट होगा। – chux

उत्तर

4

एनसीएउंट का प्रकार या न्यूनतम अपेक्षित सीमा क्या है?

मानक कोई विशिष्ट न्यूनतम निर्दिष्ट नहीं करता है। यह स्पष्ट रूप से

संबंधित तर्क हस्ताक्षर पूर्णांक के लिए एक सूचक होगा जिसमें इस कॉल द्वारा fscanf फ़ंक्शन तक अब तक इनपुट स्ट्रीम से वर्णित वर्णों की संख्या लिखी जानी चाहिए।

(C2011, 7.21.6.2/12)

इस मानक के रूप में यद्यपि, एक अनुरूप कार्यान्वयन गंतव्य चर में एक अलग संख्या को स्टोर करने के लिए कोई जगह नहीं छोड़ देता है सिवाय %n सहित सभी रूपांतरण के लिए निर्दिष्ट करता है, कि

यदि रूपांतरण का परिणाम [गंतव्य] ऑब्जेक्ट में प्रदर्शित नहीं किया जा सकता है, तो व्यवहार अपरिभाषित है।

(C2011 7.21.6.2/10)

क्या होता है, या होना चाहिए, जब "इनपुट स्ट्रीम से पढ़ने वर्णों की संख्या" बड़ी है?

सूचक %n निर्देश के लिए इसी को सही ढंग से निर्देश की दूरी विनिर्देशक के लिए लिखा गया हो (या उसके कमी), और यदि पात्रों की सही गिनती कि scanf() कॉल द्वारा उस समय तक पढ़ा एक वस्तु में प्रतिनिधित्व किया जा सकता है उस प्रकार के, तो वास्तविक गिनती वास्तव में संग्रहीत किया जाना चाहिए। अन्यथा, व्यवहार अपरिभाषित है।

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