Помогите преобразовать тип

error911
Offline
Зарегистрирован: 06.10.2012

Здравствуйте!

помогите пожалуйста кусочком кода...

Есть переменная integer. Принимает значение от 0 до 20.

нужно ее значение записать в char[2]

пример:  i=14 то с[0]="1" и с[1]="4"

Спасибо за помощь!

Strelec
Offline
Зарегистрирован: 20.11.2012

 

 
Наверное через:
sprintf
 
 
 sprintf(char, "%02d" , int);
 
и можно вызывать  char[0] 
и  char[1] 
 
там будут 1 и 4 отдельно (если в инте было 14).
 
 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Я бы сделал так:

  char cifra[2];
  int chislo = 14;
  cifra[0] = chislo/10;
  cifra[1] = chislo%10;

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Оба варианта имеют место жить :)

В первом варианте только нужно объявить буфер достаточной длины, не меньше 3-х.

Есть еще один вариант, itoa.

А вообще, если нужен корректный ответ - нужен корректный вопрос ;) Я про то, как далее будет использоваться строковое значение. Например, если просто вывести в Serial, тогда и преобразование не нужно.

 

mixail844
Offline
Зарегистрирован: 30.04.2012

а я бы сделал так :



char temp[4];
int num;
itoa(num,temp,10);

 

Strelec
Offline
Зарегистрирован: 20.11.2012

Я не знал про itoa... спасибо.

PS. А мысль с делением сразу пришла, но как-то читал статью, в которой программист старательно избегал разными путями деления, пояснив, что это очень ресурсоемкое мероприятие...

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

sprintf - наиболее универсальный вариант, но и более ресурсоемкий, потому что универсальный. Вариант максима самый эффективный, если не рассматривать дальнейшее использование строки. Хотя справедливости ради нужно добавить код '0', чтобы это были символы (chislo/10 + '0' и chislo%10 + '0'). Ну и вариант с itoa - середина :)

Деление, по большому счету, лучше избегать - если деление не на степень двойки (1,2,4,8,16,32..). Например, деление на 4, можно заменить на сдвиг вправо на 2. Хотя всё это философия, нужно смотреть для чего это нужно и нужно ли это.

 

maksim
Offline
Зарегистрирован: 12.02.2012

А вы думаете, что внутри itoa не деление, а какая то волшебная операция?
Топик-стартер не пояснил, что ему нужно строка с кодами АСКИ или просто цифры.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

А еще можно сделать без умножения и деления, просто и тупо:

char *gp_array[] =
{
  "00",
  "01",
  "02",
  "03",
  "04"
  ...
  "20"
};

int value = 5;
char *ptr = gp_array[ value ];

И массив поместить в PROGMEM.

 

Strelec
Offline
Зарегистрирован: 20.11.2012

maksim пишет:

А вы думаете, что внутри itoa не деление, а какая то волшебная операция?

Не берусь спорить, просто выразил свои опасения (я еще "чайник").

Про функцию itoa нашел тут:  http://ru.wikipedia.org/wiki/Itoa_(%D0%A1%D0%B8)

там пример ее реализации... 

 

А пример с памятью - шикарен) 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Массив хорош, но в жизни не используется, потому что ограничен объемом памяти и набором входных значений.

mishuta
Offline
Зарегистрирован: 15.04.2012

А наоборот это тоже работает? К примеру присвоить содержимое char to int.

Strelec
Offline
Зарегистрирован: 20.11.2012

mishuta пишет:

А наоборот это тоже работает? К примеру присвоить содержимое char to int.

 

Например функция: atoi

http://ru.wikipedia.org/wiki/Atoi

 

еще можно вычислять значение АСКИ символа - тоесть значение каждого char в массиве. По ASCII http://www.asciitable.com/ таблице - где они идут по порядку, нужно отнять абсолютное значение аски (тоесть значение нуля по таблице - это 48) и получится число, дальше прибавлять его к итоговому int  домножая на разрядность.

Например: 52 - берем первый с начала знак 5 - в аски это значение 53 (а 0 это 48) - значит вычитаем из 53 - 48 = 5 

умнажаем 5 * 10 и прибавляем в нужный int. получилось в int=50

затем берем 2, в аски это 50, отнимаем 48 (тоесть 0) = 2 *1 + к тому же int = 52

оформляем цикл - получаем автоматическое преобразование - только нужно знать количество знаков в char, чтобы задать размерность цикла и не переборщить с размерностью int.

PS. Выше ИМХО - просьба не пинать)

mishuta
Offline
Зарегистрирован: 15.04.2012
char data_in[100];
int interval;

interval_1 = atoi(data_in);

Как то так?

error911
Offline
Зарегистрирован: 06.10.2012

Спасибо большое!!!!

mishuta
Offline
Зарегистрирован: 15.04.2012

mishuta пишет:

char data_in[100];
int interval;

interval_1 = atoi(data_in);

Как то так?

Вроде и компелятор не ругается, а программа всё равно не работает.

mishuta
Offline
Зарегистрирован: 15.04.2012

Вот часть кода. Цель, с помощью таймера изменять частоту мигания леда. Величину таймера я посылаю с терминала.

К примеру 013,on,500

013 - Устройство. on - команда "Включить". 500 - 500mS

 Что-же я упускаю?

#include <string.h>

char unitID_in[10];
char command_in[10]; 
char data_in[100];     
int interval_1;

unsigned long newMillis_1;

void setup() 
{   
// открываем порт    
Serial.begin(9600);
// к пину 8 подключён led
pinMode(8, OUTPUT);
}   
void loop() 
{              
int i=0;   
char buffer[100];   

//если есть данные - читаем   
if(Serial.available())
{      
delay(100);             
//загоняем прочитанное в буфер
while( Serial.available() && i< 99) 
{         
buffer[i++] = Serial.read();
}      
//закрываем массив      
buffer[i++]='\0';   
}   
//если буфер наполнен
if(i>0)
{             
//разбераем его на части отделенные запятой     
sscanf(buffer, "%[^','],%[^','],%s", &unitID_in, &command_in, &data_in);         
}     
//Исполнительная часть 
//Проверяем какому устройству пришли данные   
//тестовое устройство 001     
if ((String)unitID_in == "001")
{  
//test serial read  
interval_1 = atoi(data_in);
Serial.print("001,arduino recive: unit ");       
Serial.print(unitID_in);       
Serial.print("\n");       
Serial.print("command: ");       
Serial.print(command_in);       
Serial.print("\n");       
Serial.print("data: ");       
Serial.print(data_in);             
Serial.print("\n"); 
Serial.print("interval_1: ");       
Serial.print(interval_1,DEC);             
Serial.print("\n"); 
unitID_in [0] = '\0';        
command_in [0] = '\0';                 
}       
//пример выполнения команды устройством 013      
if ((String)unitID_in == "013")
{               
if ((String)command_in == "on")
{           
interval_1 = atoi(data_in);
if(millis() > newMillis_1)  
   {  
     digitalWrite(8, !digitalRead(8));  
     newMillis_1 = millis() + interval_1;  
   }  
}       
if ((String)command_in == "off")
{           
digitalWrite(8, LOW);
}                      
Serial.print("001,arduino recive: unit ");
Serial.print(unitID_in);       
Serial.print(" command ");       
Serial.print(command_in);       
Serial.print("\n"); 
Serial.print("interval_1: ");       
Serial.print(interval_1,DEC);             
Serial.print("\n");
unitID_in [0] = '\0';       
command_in [0] = '\0';                 
} 
} 

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

32 строку перенесите и вставьте после 36, иначе в каждом loop, происходит "чудо", если нет данных, buffer очищается И увеличивается i, что явно нежелательно

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011
mishuta
Offline
Зарегистрирован: 15.04.2012

Есть, разобрался!

Теперь работает!

#include <string.h>

char unitID_in[10];
char command_in[10]; 
char data_in[100];     
int interval_1;

unsigned long newMillis_1;

void setup() 
{   
// открываем порт    
Serial.begin(9600);
pinMode(8, OUTPUT);
}   
void loop() 
{              
int i=0;   
char buffer[100];   

//если есть данные - читаем   
if(Serial.available())
{      
delay(100);             
//загоняем прочитанное в буфер
while( Serial.available() && i< 99) 
{         
buffer[i++] = Serial.read();
}      
//закрываем массив      
//buffer[i++]='\0';   
}   
//если буфер наполнен
if(i>0)
{ 
buffer[i++]='\0';   
 
//разбераем его на части отделенные запятой     
sscanf(buffer, "%[^','],%[^','],%s", &unitID_in, &command_in, &data_in);         
}     
//Исполнительная часть 
//Проверяем какому устройству пришли данные   
//тестовое устройство 001     
if ((String)unitID_in == "001")
{  
//test serial read  
interval_1 = atoi(data_in);
Serial.print("001,arduino recive: unit ");       
Serial.print(unitID_in);       
Serial.print("\n");       
Serial.print("command: ");       
Serial.print(command_in);       
Serial.print("\n");       
Serial.print("data: ");       
Serial.print(data_in);             
Serial.print("\n"); 
Serial.print("interval_1: ");       
Serial.print(interval_1,DEC);             
Serial.print("\n"); 
unitID_in [0] = '\0';        
command_in [0] = '\0';                 
}       
//пример выполнения команды устройством 013      
if ((String)unitID_in == "013")
{               
if ((String)command_in == "on")
{           
interval_1 = atoi(data_in);
 
}       
if ((String)command_in == "off")
{           
digitalWrite(8, LOW);
}                      
Serial.print("001,arduino recive: unit ");
Serial.print(unitID_in);       
Serial.print(" command ");       
Serial.print(command_in);       
Serial.print("\n"); 
Serial.print("interval_1: ");       
Serial.print(interval_1,DEC);             
Serial.print("\n");
unitID_in [0] = '\0';       
command_in [0] = '\0';                 
} 
// Мигание ледом
if(millis() > newMillis_1)  
   {  
     digitalWrite(8, !digitalRead(8));  
     newMillis_1 = millis() + interval_1;  
   } 
} 

 

Kvanto
Offline
Зарегистрирован: 26.04.2013

Подскажите, хочу записать в файл строку состоящую из температуры с датчика и времени. И что-то не получается вывести значение температуры. Перевожу из float в char. В порту отображается строка:

а код вот такой:



File myFile;
OneWire  ds(8);  // линия 1-Wire будет на pin 8
int led = 9;
int sec;
int minut;
int hours;
int days;
int months;
int years;
char filename[30];
char date[8];

void setup(void) {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
     ; // wait for serial port to connect. Needed for Leonardo only
   }

  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(10, OUTPUT);
   
   if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.

  sec = RTC.get(DS1307_SEC, true);        //set the seconds
  minut = RTC.get(DS1307_MIN, true);     //set the minutes
  hours = RTC.get(DS1307_HR, true);       //set the hours
  days = RTC.get(DS1307_DATE, true);       //set the date
  months = RTC.get(DS1307_MTH, true);        //set the month
  years = RTC.get(DS1307_YR, true);         //set the year
  sprintf(filename, "%02d_%02d.txt", days, months);
}
void loop(void) {
  digitalWrite(led, HIGH);
  delay (1000);
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {

    ds.reset_search();
    delay(250);
    return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
 
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
  data[i] = ds.read();

 }
 // convert the data to actual temperature

 unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
   raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
 } else 
  {
   byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  sec = RTC.get(DS1307_SEC, true);        //set the seconds
  minut = RTC.get(DS1307_MIN, true);     //set the minutes
  hours = RTC.get(DS1307_HR, true);       //set the hours
  days = RTC.get(DS1307_DATE, true);       //set the date
  months = RTC.get(DS1307_MTH, true);        //set the month
  years = RTC.get(DS1307_YR, true);         //set the year
  
  
  celsius = (float)raw / 16.0;
  sprintf(date, "%5.2f_%02d", celsius, months);
  myFile = SD.open(filename, FILE_WRITE);
   if (myFile) {
     myFile.println(date);
    // close the file:
    Serial.println(date);
    myFile.close();
   }
   else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  delay (100);

}

 

leshak
Offline
Зарегистрирован: 29.09.2011

Kvanto пишет:

Подскажите, хочу записать в файл строку состоящую из температуры с датчика и времени. И что-то не получается вывести значение температуры. Перевожу из float в char. В порту отображается строка:

Наталкивался на то что то-ли sprintf, то ли scanf, то ли оба (не помню точно, лень выкапывать) - на ардуине, для экономии памяти реализованы не в полном объеме. представляют собой "обкусанный вариант" который не умеет работать с float. Реализована поддержка только целых и строк.

Так, что, с большой доле вероятности вам нужно будет либо предварительно разбирать celsius на целую и дробную часть и кормить их sprintf-у отдельно. Либо самому делать преобразование float в строку.

maksim
Offline
Зарегистрирован: 12.02.2012

Можно так сделать:

  celsius = (float)raw / 16.0;
  myFile = SD.open(filename, FILE_WRITE);
  if (myFile) 
  {
    myFile.print(celsius, 2);
    myFile.print('_');
    if(months < 10)myFile.print('0');
    myFile.println(months);
  
    Serial.print(celsius, 2);
    Serial.print('_');
    if(months < 10)Serial.print('0');
    Serial.println(months);
    myFile.close();
  }
  else
    Serial.println("error opening test.txt");
  delay (100);

только вот не понятно зачем вы только месяц записываете?

Kvanto
Offline
Зарегистрирован: 26.04.2013

maksim пишет:

Можно так сделать:



  celsius = (float)raw / 16.0;
  myFile = SD.open(filename, FILE_WRITE);
  if (myFile) 
  {
    myFile.print(celsius, 2);
    myFile.print('_');
    if(months < 10)myFile.print('0');
    myFile.println(months);
  
    Serial.print(celsius, 2);
    Serial.print('_');
    if(months < 10)Serial.print('0');
    Serial.println(months);
    myFile.close();
  }
  else
    Serial.println("error opening test.txt");
  delay (100);

только вот не понятно зачем вы только месяц записываете?

благодарю! да это я для теста, чтобы всю строку не писать. А сейчас всё прописал. Еще вот такой вопрос, записываю в имя создаваемого файла значения даты, но больше двух типов(например, месяца и года или дня и месяца) не получается записать, не выводится на монитор порта. 

int sec;
int minut;
int hours;
int days;
int months;
int years;
char filename[30];
  
sec = RTC.get(DS1307_SEC, true);        //set the seconds
  minut = RTC.get(DS1307_MIN, true);     //set the minutes
  hours = RTC.get(DS1307_HR, true);       //set the hours
  days = RTC.get(DS1307_DATE, true);       //set the date
  months = RTC.get(DS1307_MTH, true);        //set the month
  years = RTC.get(DS1307_YR, true);         //set the year
  sprintf(filename, "%02d_%02d.txt", days, months);

 

maksim
Offline
Зарегистрирован: 12.02.2012

Это почему же? Вот все выводится:

  int days = 14;
  int months = 06;
  int years = 13;
  char filename[30];
  sprintf(filename, "%02d_%02d_%d.txt", days, months, years);
  Serial.println(filename);
  delay(1000); 

 

Kvanto
Offline
Зарегистрирован: 26.04.2013

maksim пишет:

Это почему же? Вот все выводится:



  int days = 14;
  int months = 06;
  int years = 13;
  char filename[30];
  sprintf(filename, "%02d_%02d_%d.txt", days, months, years);
  Serial.println(filename);
  delay(1000); 

 

выводиться то выводится, а вот почему-то записывать в файл с таким именем данные он не хочет. Наверное больше 8 символов, как где-то писалось.

void setup(void) {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
     ; // wait for serial port to connect. Needed for Leonardo only
   }

  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(10, OUTPUT);
   
   if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.

  sec = RTC.get(DS1307_SEC, true);        //set the seconds
  minut = RTC.get(DS1307_MIN, true);     //set the minutes
  hours = RTC.get(DS1307_HR, true);       //set the hours
  days = RTC.get(DS1307_DATE, true);       //set the date
  months = RTC.get(DS1307_MTH, true);        //set the month
  years = RTC.get(DS1307_YR, true);         //set the year
  sprintf(filename, "%02d_%02d_%d.txt", days, months, years);
  Serial.println(filename);
}
void loop(void) {
  digitalWrite(led, HIGH);
  delay (1000);
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {

    ds.reset_search();
    delay(250);
    return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
 
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
  data[i] = ds.read();

 }
 // convert the data to actual temperature

 unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
   raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
 } else 
  {
   byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  sec = RTC.get(DS1307_SEC, true);        //set the seconds
  minut = RTC.get(DS1307_MIN, true);     //set the minutes
  hours = RTC.get(DS1307_HR, true);       //set the hours
  days = RTC.get(DS1307_DATE, true);       //set the date
  months = RTC.get(DS1307_MTH, true);        //set the month
  years = RTC.get(DS1307_YR, true);         //set the year
  
  
celsius = (float)raw / 16.0;
myFile = SD.open(filename, FILE_WRITE);
if (myFile) 
{
  myFile.print(celsius, 2);
  myFile.print('_');
    
  myFile.print(years);
  myFile.print('-');
  
  myFile.print(months);
  myFile.print('-');
  
  myFile.print(days);
  myFile.print(' ');  
  
  myFile.print(hours);
  myFile.print(':');
  
  myFile.print(minut);
    myFile.print(':');
    
  myFile.println(sec);
  
  Serial.print(celsius, 2);
  Serial.print('_');
  Serial.print(years);
  Serial.print('-');
  
  Serial.print(months);
  Serial.print('-');
  
  Serial.print(days);
  Serial.print(' ');  
  
  Serial.print(hours);
  Serial.print(':');
  
  Serial.print(minut);
  Serial.print(':');
    
  Serial.println(sec);
  myFile.close();
}
else
  Serial.println("error opening test.txt");
delay (100);

}

leshak
Offline
Зарегистрирован: 29.09.2011

Kvanto пишет:

выводиться то выводится, а вот почему-то записывать в файл с таким именем данные он не хочет. Наверное больше 8 символов, как где-то писалось.

Не "наверное", а так и есть. "Писалось" в документации Arduino - SD :)

SD Library пишет:
The library supports FAT16 and FAT32 file systems on standard SD cards and SDHC cards. It uses short 8.3 names for files.

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так урежте год и получите 8 символов 17_06_13.txt:

sprintf(filename, "%02d_%02d_%02d.txt", days, months, years%100);

И кстати остальную то строку можно и sprintfом формировать:

  myFile.print(celsius, 2);
  char str1[20];
  sprintf(str1, "_%d-%02d-%02d %02d:%02d:%02d", years, months, days, hours, minut, sec);
  myFile.println(str1);
  
  Serial.print(celsius, 2);
  Serial.println(str1);