আমি স্ট্রিংয়ে একাধিক ভেরিয়েবল কীভাবে মুদ্রণ করব?


46

বলুন যে আমার কিছু ভেরিয়েবল রয়েছে যা আমি টার্মিনালে মুদ্রণ করতে চাই, সেগুলিতে স্ট্রিংয়ে মুদ্রণের সহজতম উপায় কী?

বর্তমানে আমি এরকম কিছু করি:

Serial.print("Var 1:");Serial.println(var1);
Serial.print(" Var 2:");Serial.println(var2);
Serial.print(" Var 3:");Serial.println(var3);

এই কাজ করতে একটি ভাল উপায় আছে কি?


একটি ধারণা, কিন্তু আমি যদি এটা কাজ করবে জানি না এই কিছু পরিবর্তন হয় ... আবার, আমি যদি এই Arduino উপর সমর্থিত জানি না: stackoverflow.com/questions/804288/...
apnorton

উত্তর:


37

ardprintfএটি এমন একটি ফাংশন যা আমি একসাথে হ্যাক করেছি যা printfসিরিয়াল সংযোগের জন্য অনুকরণ করে। এই ফাংশনটি (নীচে দেওয়া) ফাংশনটি প্রয়োজনীয় যেখানে ফাইলগুলি শুরুতে আটকানো যেতে পারে। এটি কোনও দ্বন্দ্ব তৈরি করা উচিত নয়।

এটি অনুরূপ বলা যেতে পারে printf। এটি এই উদাহরণে কর্মে দেখুন:

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int l=2;
  char *j = "test";
  long k = 123456789;
  char s = 'g';
  float f = 2.3;

  ardprintf("test %d %l %c %s %f", l, k, s, j, f);

  delay(5000);

}

আশানুরূপ ফলাফল:

test 2 123456789 g test 2.30

ফাংশন প্রোটোটাইপটি হ'ল:

int ardprintf(char *, ...);

এটি ফাংশন কলে সনাক্ত করা আর্গুমেন্টের সংখ্যা প্রদান করে।

এটি ফাংশন সংজ্ঞা:

#ifndef ARDPRINTF
#define ARDPRINTF
#define ARDBUFFER 16
#include <stdarg.h>
#include <Arduino.h>

int ardprintf(char *str, ...)
{
  int i, count=0, j=0, flag=0;
  char temp[ARDBUFFER+1];
  for(i=0; str[i]!='\0';i++)  if(str[i]=='%')  count++;

  va_list argv;
  va_start(argv, count);
  for(i=0,j=0; str[i]!='\0';i++)
  {
    if(str[i]=='%')
    {
      temp[j] = '\0';
      Serial.print(temp);
      j=0;
      temp[0] = '\0';

      switch(str[++i])
      {
        case 'd': Serial.print(va_arg(argv, int));
                  break;
        case 'l': Serial.print(va_arg(argv, long));
                  break;
        case 'f': Serial.print(va_arg(argv, double));
                  break;
        case 'c': Serial.print((char)va_arg(argv, int));
                  break;
        case 's': Serial.print(va_arg(argv, char *));
                  break;
        default:  ;
      };
    }
    else 
    {
      temp[j] = str[i];
      j = (j+1)%ARDBUFFER;
      if(j==0) 
      {
        temp[ARDBUFFER] = '\0';
        Serial.print(temp);
        temp[0]='\0';
      }
    }
  };
  Serial.println();
  return count + 1;
}
#undef ARDBUFFER
#endif

** %চরিত্রটি মুদ্রণ করতে , ব্যবহার করুন %%। *


এখন, গিথুব জিস্টগুলিতে উপলব্ধ ।


3
খুব ভাল ধারণা, যদিও আমি অনুভব করেছি এটি আরও সংক্ষিপ্তবাদী হতে পারে, তাই আমি বাফারিং ছাড়াই এই সংস্করণটি আবার লিখলাম। আগ্রহী যে কেউ আক্ষেপটি
অ্যালিট্রাক্রাম

13

আমি সাধারণত এক প্রশ্নের দুটি উত্তর করা যাবে না, কিন্তু আমি কেবল মাত্র পাওয়া এই আজ, যেখানে আপনি কোন বাফার ছাড়া printf, ব্যবহার করতে পারেন।

// Function that printf and related will use to print
int serial_putchar(char c, FILE* f) {
    if (c == '\n') serial_putchar('\r', f);
    return Serial.write(c) == 1? 0 : 1;
}

FILE serial_stdout;

void setup(){
    Serial.begin(9600);

    // Set up stdout
    fdev_setup_stream(&serial_stdout, serial_putchar, NULL, _FDEV_SETUP_WRITE);
    stdout = &serial_stdout;

    printf("My favorite number is %6d!\n", 12);
}

void loop() {
  static long counter = 0;
  if (millis()%300==0){
    printf("millis(): %ld\tcounter: %ld (%02X)\n", millis(), counter, counter++);
    delay(1);    
  }
}

এটি এখনও ভাসমান পয়েন্ট সীমাবদ্ধতা আছে।

সম্পাদনা: আমি ভেবেছিলাম যে আমি এটির জন্য একটু পরীক্ষা করব এবং এটি বেশ ভালভাবে কাজ করে। আমি ফর্ম্যাটেড আউটপুট সহ লুপটিতে আরও ভাল পরীক্ষা যুক্ত করেছি।


ওহ মানুষ, এটা দুর্দান্ত। প্রিন্টফ স্প্রিন্টফের চেয়ে সম্পূর্ণ নিরাপদ। এটি আপনাকে ফ্রিমেটে স্ট্রিংগুলি দেয় যা দুর্দান্ত। কুল কৌশল। ধন্যবাদ। (ভোট দিয়েছেন)
ডানকান সি

একটি প্রশ্ন: আপনার serial_putcharফাংশনে, কেন রিটার্নের বিবৃতি দেবেন না return !Serial.write(c);? বুলিয়ান রিটার্ন মানটির সংজ্ঞা উল্টানোর জন্য কি ট্রিনিয়ার অপারেটরের চেয়ে পরিষ্কার নয়?
ডানকান সি

এটি একটি ভাল পয়েন্ট এবং আমি এটি পছন্দ করি। কোডটি আমার ছিল না এবং আমি এটিটি পেস্ট করেছিলাম।
মাদ্রিবাদ

serial_putcharফাংশনের জন্য ধন্যবাদ । এটি একটি ট্রিট কাজ করে। :-) আপনি কি ভাসমান পয়েন্ট সীমাবদ্ধতা ঠিক করতে পারেন ?
গ্রিননলাইন

4

এটি সম্ভবত আরও ভাল নয়, অন্যরকম। আপনি আউটপুট জন্য স্ট্রিং অবজেক্ট ব্যবহার করতে পারেন । এই বিষয়গুলি স্বয়ংক্রিয় টাইপকাস্টিং কনটেনটেশন এবং সমর্থন করে।

Serial.begin(9600);
String label = "Var";
const byte nValues = 3;
int var[nValues] = {36, 72, 49};

for (int i = 0; i < nValues; i++) {
    String stuff = label + i + ": ";
    Serial.println(stuff + var[i]);
}

4
স্পষ্টতই স্মৃতি সীমা সম্পর্কে সতর্ক হওয়া গুরুত্বপূর্ণ। এক জায়গায় প্রচুর পরিমাণে কনটেন্টেশন এবং অন্যান্য স্ট্রিং ক্রিয়াকলাপ অবাক করে দেওয়ার মতো জায়গা ব্যবহার করতে পারে।
পিটার ব্লুমফিল্ড

@ পিটারআর ব্লুমফিল্ড একেবারে সত্য! এই কারণেই আমি উল্লেখ করেছি যে এই রূপটি আরও ভাল নয়;)
ক্লাউস-ডিয়েটার ওয়ার্জেচা

4

আমি সিরিয়ালগুলিতে জিনিসগুলি আরও ভালভাবে তৈরি করতে সাধারণত ট্যাব ব্যবহার করি used ভেরিয়েবলের নির্দিষ্ট পরিবর্তনগুলি লক্ষ্য করতে সক্ষম হয়ে আমি যেমন অর্ডিনোকে যত তাড়াতাড়ি আগুন জ্বালানোর অনুমতি দেই এমন জিনিসগুলি সারি রাখার মতো।

এরকম কিছু চেষ্টা করুন:

Serial.println("Var 1:\tVar 2tVar 3:");
Serial.print("\t");
Serial.print(var1);
Serial.print("\t");
Serial.print(var2);
Serial.print("\t");
Serial.print(var3);
Serial.println();

বা এর মতো কিছু:

Serial.print("Var 1:");Serial.println(var1);
Serial.print("\tVar 2:");Serial.println(var2);
Serial.print("\tVar 3:");Serial.println(var3);

সত্য, আমি একই ("\ t" এবং "\ n") করি এবং সাধারণত কোড-ব্লোটিং স্ট্রিং অবজেক্টের ঘণ্টা এবং শিসগুলি এড়িয়ে চলি।
ক্লাউস-ডিয়েটার ওয়ার্জেচা

1
ক্লাউস ওয়ার্জেচা, আমি খুব কমই ভেরিয়েবলের নাম দিচ্ছি কারণ তারা সুন্দর কলামে রয়েছে। এছাড়াও এ সিনট্যাক্সের সাথে মেলে না এমন এলোমেলো প্রিন্ট আউটগুলি দেখতে আরও সহজ করুন
স্টিভেন 10172

4

আমি এটি কেবল ডিবাগিংয়ের জন্যই ব্যবহার করি তবে:

int a = 10;
int b = 20;
Serial.println("a = " + String(a) + " and b = " + String(b));

স্ট্রিং what কী?
Juraj

এলএমএফটিএফএম (আমাকে এটি আমার জন্য ঠিক করতে দিন)।
linhartr22

2

আমি আরডুইনো ওয়ার্ল্ডে নবাগত, তবে আমি সম্প্রতি পেয়েছি যে এটি কেবল একটি নিয়মিত সি ++ (ব্যতিক্রম এবং সম্ভবত বহুবিজ্ঞান ছাড়াই)। তবে আপনি এখনও টেমপ্লেটগুলি উপভোগ করতে পারেন। সুতরাং আমার সমাধানটি নিম্নলিখিত টেম্পলেটগুলি ব্যবহার করা:

void myprint(void)
{
  Serial.println("");
}

template<typename ...Args>
void myprint(const uint64_t & val, Args && ...args)
{
  serialPrintUint64(val);
  myprint(args...);
}

template<typename T, typename ...Args>
void myprint(const T & t, Args && ...args)
{
  Serial.print(t);
  myprint(args...);
}

....

// somewhere in your code
myprint("type: ", results.decode_type, 
        "\t value: ", results.value, 
        "\t addr: ", results.address,
        "\t cmd: ", results.command);

এখানে দুর্দান্ত জিনিস এটি এখানে কোনও অতিরিক্ত মেমরি এবং অতিরিক্ত প্রসেসিং ব্যবহার করে না।


1

আমি সাধারণত (বেদনাদায়ক) একাধিক লাইনের সাথে আটকে থাকি Serial.printতবে যখন এটি সংশ্লেষিত হয় তখন আমি আবার ফিরে যাই sprintf। এটি বিরক্তিকর যে আপনার এটির জন্য একটি উপলব্ধ বাফার থাকতে হবে।

ব্যবহার যেমন সহজ (??):

char buffer[35]; // you have to be aware of how long your data can be
                 // not forgetting unprintable and null term chars
sprintf(buffer,"var1:%i\tvar2:%i\tvar3:%i",var1,var2,var3);
Serial.println(buffer);

সতর্কতার একটি শব্দ যদিও এটি (ডিফল্টরূপে) ভাসমান প্রকারকে সমর্থন করে না।


1
স্প্রিন্টফ একটি ভয়ঙ্কর ঘৃণা। নিরাপদ টাইপ করুন না, আপনার বাফারগুলিকে ছাড়িয়ে নেওয়া সহজ, ইত্যাদি ইত্যাদি etc. এটি 1960 এর দশকের একটি সরঞ্জাম। এটি বলেছিল, আমি এটিও ব্যবহার করি তবে এটি হৃদয়ের মূর্ছনার জন্য নয় ....
ডানকান সি

ওভাররন এড়ানোর জন্য, স্নিপ্রিন্টফ ব্যবহার করুন ... বিটিডব্লিউ বেশিরভাগ মডেল আইডিই (আরডুইনো আইডিই নয়) প্রদত্ত ভেরিয়েবলের বিপরীতে স্ট্রিং ফর্ম্যাটটি পরীক্ষা করবে এবং একটি সতর্কতা নিক্ষেপ করবে।
পরের-হ্যাক 16

1

Streaming.hজায়গায়, ব্যবহার করে

Serial.print("Var 1:");Serial.println(var1);
Serial.print(" Var 2:");Serial.println(var2);
Serial.print(" Var 3:");Serial.println(var3);

একটি লিখতে পারেন

Serial << "Var 1:" << var1) << " Var 2:" << var2 << " Var 3:" << var3 << endl;

সংজ্ঞা <<মধ্যে Streaming.hকার্যকর সাধারণ সিরিজের মধ্যে অনুবাদ করে Serial.print()কল। অর্থাৎ <<অন্বিত চিনি, বৃদ্ধি কোড আকার ছাড়া বাস্তবায়িত হয়।

আপনি যদি Streaming.hইনস্টল না করে থাকেন তবে আরডুইইয়ানাআরএইগঅর্গStreaming5.zip থেকে পান । এটি আপনার লাইব্রেরি ডিরেক্টরিতে আনজিপ করুন, উদাহরণস্বরূপ ~/sketchbook/libraries। স্ট্রিম অপারেটর হিসাবে #include <Streaming.h>আপনি যেখানে স্কেচ ব্যবহার <<করেন সেখানে রেখা যুক্ত করুন ।

বেস-রূপান্তর স্পেসিফায়ার্স _হেক্স, _ডেক, _ওসিটি, এবং _ বিআইএন সরবরাহ করা হয়েছে, পাশাপাশি একটি _ফ্লোট ফাংশন (দশমিক স্থানের সংখ্যার সাথে) এবং endl। উদাহরণস্বরূপ, "আপনার স্থানাঙ্কগুলি -23.123, 135.4567" এর মতো আকারে অক্ষাংশ এবং দ্রাঘিমাংশের মানগুলি মুদ্রণ করতে যে কেউ লিখতে পারে:

Serial << "Your coordinates are " << _FLOAT(latitude,3) << ", " << _FLOAT(longitude,4) << endl;

এটি হিসাবে লেখা যেতে পারে

Serial << F("Your coordinates are ") << _FLOAT(latitude,3) << ", " << _FLOAT(longitude,4) << endl;

যা এটিকে র‌্যামে আনার পরিবর্তে প্রোগেমে দীর্ঘতর স্ট্রিং রাখবে।

দ্রষ্টব্য, এর Streaming.h মতো কোনও স্ট্রিং তৈরি করে না; এটি কেবলমাত্র তার <<ধারাগুলির পাঠ্যটি একটি প্রবাহে সরবরাহ করে। একজন arduiniana এ PString বর্গ , স্ট্রিম ইনপুট থেকে স্ট্রিং বিল্ড স্ট্রিম আউটপুট পরিবর্তে স্ট্রিং পছন্দসই বা প্রয়োজন হয় যদি করতে পারেন।


1

ব্যবহার আপনার ভেরিয়েবলের ডেটা ধরণের উপর নির্ভর করবে।

তারা যদি হয় intতবে তা হবে %dবা %i যদি তারা হয় stringতবে তা হবে%s

প্রিন্টফের জন্য মোড়ক

আপনার প্রয়োজনীয়তার উপর ভিত্তি করে আপনি সীমাটি পরিবর্তন করতে পারেন

#include <stdarg.h>
void p(char *fmt, ... ){
    char buf[128]; // resulting string limited to 128 chars
    va_list args;
    va_start (args, fmt );
    vsnprintf(buf, 128, fmt, args);
    va_end (args);
    Serial.print(buf); // Output result to Serial
}

সূত্র: https://playground.arduino.cc/Main/Pressf f

ব্যবহারের উদাহরণ:

p("Var 1:%s\nVar 2:%s\nVar 3:%s\n", var1, var2, var3); // strings
p("Var 1:%d\nVar 2:%d\nVar 3:%d\n", var1, var2, var3); // numbers

ESP8266

Serialকাঠামোর শ্রেণিতে এটি অন্তর্নির্মিত । অতিরিক্ত গ্রন্থাগার বা ফাংশনের প্রয়োজন নেই।

// strings
Serial.printf("Var 1:%s\nVar 2:%s\nVar 3:%s\n", var1, var2, var3);
// numbers
Serial.printf("Var 1:%d\nVar 2:%d\nVar 3:%d\n", var1, var2, var3);

প্রিন্টফ ফর্ম্যাট রেফারেন্স পৃষ্ঠায় ফর্ম্যাট করার টিপস সম্পর্কে আরও বিশদ: http://www.cplsplus.com/references/cstdio/printf/

\n লাইন ফিডের জন্য পালানোর ক্রম।

এস্কেপ সিকোয়েন্সগুলি স্ট্রিং ল্যাটারাল এবং চরিত্রের অক্ষরে অক্ষরের মধ্যে কয়েকটি বিশেষ অক্ষরের প্রতিনিধিত্ব করতে ব্যবহৃত হয়।

সূত্র: http://en.cppreferences.com/w/cpp/language/escape

[সম্পাদনা] - @ জুরজ যেমন উল্লেখ করেছেন, এটি বেশিরভাগ এভিআর মডিউলগুলিতে পাওয়া যায় না। সুতরাং আমি ESP8266 উল্লেখ এবং সাধারণ AVR মডিউলগুলির জন্য একটি প্রিন্টফ মোড়ক যুক্ত করেছি


এটা সত্য নয়। কোন সিরিয়াল ক্লাস নেই। প্রিন্টফ প্রিন্ট ক্লাসে থাকবে তবে এটি সর্বাধিক ব্যবহৃত AVR প্যাকেজে নেই
Juraj

@ জুরজ আপনি ঠিক বলেছেন, আমি এটি কেবল ESP8266 এ পরীক্ষা করেছি যা এর ( লিঙ্ক ) আছে এবং ভেবেছিল এটি আরডুইনো কোর থেকে এসেছে। সেই অনুসারে আমার উত্তর আপডেট করবে
রেমি

পি ফাংশনের জন্য আমি যদি আরও সম্ভব হয় তবে আরও একটি ডাউনওয়েট যুক্ত করব।
জুরজ

এটি একটি পুরানো প্রশ্ন এবং আমি পুরানো উত্তরগুলি বিচার করতে পারছি না কারণ 2014 সালে কী পাওয়া গেছে তা আমি জানি না but তবে এখন প্রিন্টফ প্রয়োগের সাথে একটি মুদ্রণ প্রবাহে মুদ্রণ স্রোতে মোড়ানোর জন্য গ্রন্থাগার রয়েছে।
জুরাজ


-1

Http://playground.arduino.cc/Main/ মুদ্রণ থেকে আমি পর্যবেক্ষণ করেছি যে এটি আমার মেগা 2560 এ ঠিকঠাক কাজ করছে

এগুলি কেবলমাত্র কাজ করেছে, ভার্সনপ্রিন্টএফপি বা PROGMEM এর দরকার নেই ...

#include "Arduino.h"
void local_printf(const char *format, ...)
{
static char line[80];
va_list args;
va_start(args, format);
int len = vsnprintf(line, sizeof(line), format, args);
va_end(args);
for (char *p = &line[0]; *p; p++) {
    if (*p == '\n') {
        Serial.write('\r');
    }
    Serial.write(*p);
}
if (len >= sizeof(line))
    Serial.write('$');
}

void setup()
{
Serial.begin(115200);
local_printf("%s:%d: %s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
}

void loop()
{
static int count=0;
local_printf("%s:%d: %s %d\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, count++);
delay(1*1000);
}

// src/main.c:24: void setup()
// src/main.c:30: void loop() 0
// src/main.c:30: void loop() 1

1
কেন কেবল নিজের ব্যবহারprintf() না করে কেউ কেন এটি করতে চাইবে ?
এডগার বোনেট

-3
int Money_amount = 55;

Serial.print(String("New amount: $" + Money_amount));

আপনি টার্মিনালে দেখতে পাবেন:

New amount: $55

1
আপনি কোনও +অপারেটরের সাথে সি-স্ট্রিংয়ের সাথে কোন সংযোগ দিতে পারবেন না ।
গ্রে_গোর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.