2015-05-22 3 views
0

Я пишу TCP-сокет в C для отправки данных о местоположении для проекта, над которым я работаю.Копирование значений float в массив символов

До сих пор все работает, но я борюсь с этой, казалось бы, просто проблемой. Я пытаюсь создать строку JSON, которая будет отправлена ​​через сокет. У меня есть массив символов (представитель строки) json определяется как:

char json[1024]; 

С методом прототипа:

const char* build_json(void); 

И тело метода:

const char* build_json(void) { 
    strcpy(json, "{"); 
    strcat(json, "\"latitude\":"); 
    sprintf(json, "%0.5f", latitude); 
    strcat(json, "}"); 
    return json; 
} 

Я знаю, что latitude является и должно быть float примерно 5 знаков после запятой.

Но когда я звоню build_json();, 38.925034} это единственное, что возвращается. Почему это так? Похоже, что вызов sprintf переписывает то, что уже было написано в json.

Благодарим за помощь!

ответ

10

sprintf не добавляется к вашей строке; скорее, он перезапишет все, что есть. Вы можете сделать это:

sprintf(json + strlen(json), "%0.5f", 213.33f); 

Но, честно говоря, это гораздо лучшее решение:

sprintf(json, "{\"latitude\":%0.5f}", location); 

И это решение еще лучше:

snprintf(json, sizeof(json), "{\"latitude\":%0.5f}", location); 
json[sizeof(json) - 1] = '\0'; 

пока json представляет собой массив, видимый функции, вызывающей snprintf, т.е. выделенной в этой функции в стеке или глобально. Если это char*, что вы переходите к функции, это будет терпеть неудачу, так что будьте осторожны.

+0

Но первое решение выглядит очень аккуратно! –

+0

@BarmakShemirani Вопрос о вкусе, я думаю: P Там нет проверки переполнения, поэтому я предпочел бы использовать snprintf, чтобы убедиться. – szczurcio

+0

Использование 'snprintf()' - мудрый совет здесь. При печати с ''% f ''результирующая строка может составлять сотни или тысячи байтов (думаю,' -DBL_MAX'). – chux

1

Вам нужно было сделать это только с помощью sprintf, чтобы избежать нескольких операций.

const char* build_json(void) { 
    sprintf(json, "{\"latitude\":%0.5f}", latitude); 
    return json; 
} 

Кроме того, если вы пишете код сети, то вам лучше выделить вашу строку в функции, а не полагаться на глобальные. Часто сетевой код выполняется многопоточным способом.

0

Быстрого & загрязнен фикс:

char* cptr = json; 
... 
strcpy(cptr, "{"); 
cptr += sizeof("{") - 1; 

strcat(cptr, "\"latitude\":"); 
cptr += sizeof("\"latitude\":") - 1; 

sprintf(cptr, "%0.5f", latitude); 

Правильное решение будет поставить строковые литералы и их размеры в постоянном переменных, а не выше.

char* cptr = json; 
... 
strcpy(cptr, STR_START_BRACE); 
cptr += STR_START_BRACE_LEN; 

strcat(cptr, STR_LATITUDE); 
cptr += STR_LATITUDE_LEN; 

sprintf(cptr, "%0.5f", latitude); 
0

Вы можете написать всю строку сразу в буфер:

const void build_json(char * json, size_t *len) 
{ 
    char buff[50]; 
    sprintf(buff, "{\"latitude\":%0.5f}", latitude); 
    *len = strlen(buff); 
    strncpy(json, buff, *len); 
} 

Просто обеспечивают достаточно места для буфера, вы должны выделить свой JSON вне FUNC и освободить его, когда из области видимости

+0

'strncpy()' пропускает копию '0'-завершения. И почему (промежуточное) использование 'buf' вообще? – alk

+0

это зависит от использования, мы не знаем, что является потребителем функции. Из слова «json» я предположил, что это будет чистая передача - тогда у вас есть длина, чтобы иметь возможность отправлять, и в этом случае вам все равно, нулевое завершение –

+0

Не нужно вызывать 'strlen' после' sprintf', так как 'sprintf' возвращает количество символов, записанных в буфер. – szczurcio

Смежные вопросы