snprintf এবং ভিজ্যুয়াল স্টুডিও 2010


102

আমি দুর্ভাগ্যজনক যে কোনও প্রকল্পের জন্য ভিএস ২০১০ ব্যবহার করে আটকে গিয়েছি এবং লক্ষ্য করেছি যে নিম্নলিখিত কোডটি এখনও মান-মান সম্মত কম্পাইলার ব্যবহার করে তৈরি করে না:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    char buffer[512];

    snprintf(buffer, sizeof(buffer), "SomeString");

    return 0;
}

(ত্রুটির সাথে সংকলন ব্যর্থ: C3861: 'স্নিপ্রিন্টফ': সনাক্তকারী পাওয়া যায়নি)

আমি মনে করি এটি ভিএস ২০০৫-এর সাথে ফিরে এসেছে এবং এটি এখনও স্থির হয়নি তা দেখে অবাক হয়েছি।

মাইক্রোসফ্টের তাদের স্ট্যান্ডার্ড সি লাইব্রেরিগুলিকে ২০১০ সালে সরানোর কোনও পরিকল্পনা আছে কিনা তা কি কেউ জানেন?


1
... বা আপনি কেবল "# ডেফাইন স্নিপ্রিন্ট _ _স্নিপ্রিন্টফ" করতে পারেন
ফার্নান্দো গঞ্জালেজ সানচেজ

4
... আপনি পারতেন, তবে দুর্ভাগ্যক্রমে _snprintf () snprintf () এর মতো নয় কারণ এটি নাল সমাপনের গ্যারান্টি দেয় না।
অ্যান্ডি ক্রওয়েল

ঠিক আছে সুতরাং _snprintf () ব্যবহার করার আগে আপনাকে এটিকে শূন্যতে স্মরণ করতে হবে। এছাড়াও আমি আপনার সাথে একমত। এমএসভিসির অধীনে বিকাশ করা ভয়াবহ। ত্রুটিগুলি নরক হিসাবেও বিভ্রান্তিকর।
পেঁচা

উত্তর:


88

সংক্ষিপ্ত বিবরণ: মাইক্রোসফ্ট অবশেষে ভিজ্যুয়াল স্টুডিও 2015 এ স্নিপ্রিন্টফ প্রয়োগ করেছে earlier পূর্ববর্তী সংস্করণগুলিতে আপনি এটি নীচের মতো অনুকরণ করতে পারেন।


দীর্ঘ সংস্করণ:

স্নিপ্রিন্টফের জন্য প্রত্যাশিত আচরণটি এখানে:

int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );

buf_size - 1একটি বাফারে বেশিরভাগ অক্ষর লিখেছেন । ফলস্বরূপ অক্ষরের স্ট্রিং buf_sizeশূন্য না হলে নাল অক্ষর দিয়ে সমাপ্ত হবে । যদি buf_sizeশূন্য হয় তবে কিছুই লেখা নেই এবং bufferএটি নাল পয়েন্টার হতে পারে। প্রত্যাবর্তনের মান হ'ল অক্ষরের সংখ্যা যা সীমাহীন ধরে ধরে লেখা হত buf_size, সমাপ্ত নাল অক্ষর গণনা না করে।

ভিজ্যুয়াল স্টুডিও 2015 এর পূর্বে রিলিজগুলির যথাযথ বাস্তবায়ন হয়নি। এর পরিবর্তে অ-মানক এক্সটেনশান রয়েছে _snprintf()( যেমন ওভারফ্লোতে নাল-টার্মিনেটর লিখেনি) এবং _snprintf_s()(যা নাল-টার্মিনেশন কার্যকর করতে পারে, তবে যে অক্ষরগুলি লিখিত হত তার পরিবর্তে ওভারফ্লোতে -1 প্রদান করে)।

ভিএস 2005 এবং এর জন্য প্রস্তাবিত ফ্যালব্যাক:

#if defined(_MSC_VER) && _MSC_VER < 1900

#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf

__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
    int count = -1;

    if (size != 0)
        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
    if (count == -1)
        count = _vscprintf(format, ap);

    return count;
}

__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
    int count;
    va_list ap;

    va_start(ap, format);
    count = c99_vsnprintf(outBuf, size, format, ap);
    va_end(ap);

    return count;
}

#endif

এটি সর্বদা 0 দিয়ে স্ট্রিংটি শেষ করে না যা একটি ওভারফ্লোতে প্রয়োজনীয়। C99_vsnprintf এ দ্বিতীয়টি হতে হবে: যদি (গণনা == -1) {যদি (আকার> 0) টিআর [আকার -1] = 0; গণনা = _vscprintf (ফর্ম্যাট, এপি); }
লোথার

1
@ লোথার: বাফারটি সর্বদা শূন্য থাকে। এমএসডিএন অনুসারে: "স্ট্রিং ট্রানসেকশনটি _TRUNCATE পেরিয়ে সক্ষম করা হলে, এই ফাংশনগুলি কেবল স্ট্রিংয়ের যথাযথ কপি করবে, গন্তব্য বাফারকে নাল-টার্মিনেট ছেড়ে রেখে এবং সফলভাবে ফিরে যাবে"।
ভ্যালেন্টিন মাইলিয়া

2
জুন ২০১৪ হিসাবে, এখনও আপডেট ২ সহ, ভিজ্যুয়াল স্টুডিওতে এখনও কোনও "পূর্ণ" সি 99 সমর্থন নেই This এই ব্লগটি এমএসভিসি 2013-এর জন্য সি 99 সমর্থন সংক্ষিপ্তসার দেয় sn , এমএসভিসি সি ++ 11 বাস্তবায়নে ঝনঝন এবং জিসিসি পিছনে!
fnisi

2
ভিএস2014 এর সাথে স্নিপ্রিন্টফ এবং ভার্সনপ্রিন্টফের সাথে সি 99 মান যুক্ত করা হয়েছে। ব্লগস.এমএসএনএন / বি / ভিসাব্লগ / অর্চিভ / ২০১৪ / ০/0 / ১৮ / ১৮ দেখুন ।
ভলকান রেভেন

1
মিকেল লেপিস্ট: সত্যি? আমার জন্য _স্নিপ্রিন্টফ কেবল তখনই কাজ করে যদি আমি _CRT_SECURE_NO_WARNINGS সক্ষম করি। এই কাজটি এই পদক্ষেপ ছাড়াই দুর্দান্ত কাজ করে।
এফভিডি

33

snprintfসি 98 এর অংশ নয়। এটি কেবল সি 99 এ স্ট্যান্ডার্ড। মাইক্রোসফ্টের সি 99 সমর্থন করার কোনও পরিকল্পনা নেই

(তবে এটি সি ++ 0x এও মান ...!)

একটি কাজের জন্য নীচে অন্যান্য উত্তর দেখুন।


5
স্নিপ্রিন্টফ এবং _স্নিপ্রিন্টফ আচরণের মধ্যে যেমন পার্থক্য রয়েছে তেমনি এটি কোনও ভাল কাজ নয়। অপর্যাপ্ত বাফার স্পেসের সাথে কাজ করার সময় _snprintf নাল টার্মিনেটরটিকে অত্যন্ত বিরক্তিকরভাবে পরিচালনা করে।
অ্যান্ড্রু

7
@ ডেড এমজি - ভুল cl.exe / Tc বিকল্পটি সমর্থন করে যা কম্পাইলারকে সি কোড হিসাবে একটি ফাইল সংকলন করার নির্দেশ দেয়। তদ্ব্যতীত, স্ট্যান্ডার্ড সি লাইব্রেরির একটি সংস্করণ সহ এমএসভিসি জাহাজগুলি।
অ্যান্ড্রু

3
@ ডেড এমজি - এটি সি 90 এর সাথে সাথে সি 99 এর কয়েকটি বিটকে সমর্থন করে এটি একটি সি সংকলক করে।
অ্যান্ড্রু

15
কেবল যদি আপনি 1990 এবং 1999 এর মধ্যে থাকেন
কুকুরছানা

6
-১, মাইক্রোসফ্ট _snprintfএকটি অনিরাপদ ফাংশন যা আলাদাভাবে আচরণ করে snprintf(এটি অগত্যা কোনও নাল টার্মিনেটর যুক্ত করে না), সুতরাং এই উত্তরে দেওয়া পরামর্শ বিভ্রান্তিকর এবং বিপজ্জনক।
ইন্টারজয়

8

আপনার যদি ফেরতের মানের প্রয়োজন না হয় তবে আপনি স্নিপ্রিন্টফকে _snprintf_s হিসাবে সংজ্ঞায়িত করতে পারেন

#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)

3

আমি বিশ্বাস করি উইন্ডোজ সমতুল্য sprintf_s


7
sprintf_sথেকে আলাদা আচরণ করে snprintf
ইন্টারজয়

বিশেষত স্প্রিনটিফ_এস ডক্স বলছে, "পাঠ্য মুদ্রণের জন্য যদি বাফার খুব ছোট হয় তবে বাফারটি একটি খালি স্ট্রিংয়ে সেট করা আছে"। বিপরীতে স্নিপ্রিন্টফ আউটপুটে একটি কাটা স্ট্রিং লিখে।
অ্যান্ড্রু বেনব্রিজ

2
@ অ্যান্ড্রুবাইনব্রিজ - আপনি ডকুমেন্টেশন কেটে ফেলেছেন। পুরো বাক্যটি হ'ল "যদি পাঠ্যটি মুদ্রণের জন্য বাফার খুব ছোট হয় তবে বাফারটি একটি খালি স্ট্রিংয়ে সেট করা আছে এবং অবৈধ প্যারামিটার হ্যান্ডলারটি চাওয়া হয়েছে।" অবৈধ প্যারামিটার হ্যান্ডেলের জন্য ডিফল্ট আচরণ হ'ল আপনার প্রোগ্রামটি সমাপ্ত করা। আপনি যদি _ পরিবারের সাথে ছাঁটাই করতে চান তবে আপনার স্নিপ্রিন্টফ_স এবং _TRUNCATE পতাকা ব্যবহার করতে হবে। হ্যাঁ, এটি দুর্ভাগ্যজনক যে _s এর ক্রিয়াগুলি কাটা কাটার কোনও সুবিধাজনক উপায় দেয় না। অন্যদিকে, _ এর ফাংশনগুলি বাফার আকারগুলি নির্ধারণ করতে টেমপ্লেট যাদু ব্যবহার করে এবং এটি দুর্দান্ত।
ব্রুস ডসন


1

আমি ভ্যালেন্টিন মিলার কোডটি চেষ্টা করেছিলাম তবে আমার অ্যাক্সেস লঙ্ঘনের ত্রুটি রয়েছে। আমার পক্ষে কেবল কাজটিই হ'ল ইনসান কোডিং এর বাস্তবায়ন: http://asprintf.insanecoding.org/

বিশেষত, আমি ভিসি ++ ২০০ leg এর লিগ্যাসি কোড নিয়ে কাজ করছিলাম। উন্মাদ কোডিং বাস্তবায়ন থেকে (উপরের লিঙ্কটি থেকে ডাউনলোড করা যাবে), আমার তিনটি ফাইল ব্যবহৃত: asprintf.c, asprintf.hএবং vasprintf-msvc.c। অন্যান্য ফাইলগুলি এমএসভিসির অন্যান্য সংস্করণের জন্য ছিল।

[সম্পাদনা] সম্পূর্ণতার জন্য, তাদের বিষয়বস্তু নীচে রয়েছে:

asprintf.h:

#ifndef INSANE_ASPRINTF_H
#define INSANE_ASPRINTF_H

#ifndef __cplusplus
#include <stdarg.h>
#else
#include <cstdarg>
extern "C"
{
#endif

#define insane_free(ptr) { free(ptr); ptr = 0; }

int vasprintf(char **strp, const char *fmt, va_list ap);
int asprintf(char **strp, const char *fmt, ...);

#ifdef __cplusplus
}
#endif

#endif

asprintf.c:

#include "asprintf.h"

int asprintf(char **strp, const char *fmt, ...)
{
  int r;
  va_list ap;
  va_start(ap, fmt);
  r = vasprintf(strp, fmt, ap);
  va_end(ap);
  return(r);
}

vasprintf-msvc.c:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "asprintf.h"

int vasprintf(char **strp, const char *fmt, va_list ap)
{
  int r = -1, size = _vscprintf(fmt, ap);

  if ((size >= 0) && (size < INT_MAX))
  {
    *strp = (char *)malloc(size+1); //+1 for null
    if (*strp)
    {
      r = vsnprintf(*strp, size+1, fmt, ap);  //+1 for null
      if ((r < 0) || (r > size))
      {
        insane_free(*strp);
        r = -1;
      }
    }
  }
  else { *strp = 0; }

  return(r);
}

ব্যবহার ( test.cউন্মাদ কোডিং দ্বারা সরবরাহিত অংশ ):

#include <stdio.h>
#include <stdlib.h>
#include "asprintf.h"

int main()
{
  char *s;
  if (asprintf(&s, "Hello, %d in hex padded to 8 digits is: %08x\n", 15, 15) != -1)
  {
    puts(s);
    insane_free(s);
  }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.