08.12.2017, 00:16
|
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Работа с командами GSM под stm32f4 (массивы)
Всем привет) Укажите пожалуйста на ошибки. Код работает, но может что-то я делаю слишком не оптимизированно.
Суть в следующем:
Есть массив
Код:
|
char gsm_cusd_command[30] = "AT+CUSD=1,,15\r";
char *gsm_point_cusd_command = gsm_cusd_command; |
Есть массив, который заполняется тем, что напечатают на матричной клаве
Код:
|
char gsm_ussd_balance_command[16] = "";
char *gsm_point_ussd_balance_command = gsm_ussd_balance_command; |
когда напечатали команду проверки баланса, в массиве будет "*100#"
Далее по нажатию определённой кнопки, надо всё что в массиве поместить в исходный массив между запятыми.
Сначала я писал под конкретную задачу, но потом подумал, а вдруг мне надо будет где-нибудь ещё это сделать
с другим массивом. И решил универсалить ф-ию.
Вобщем в ф-ию передаются параметры: указатель на массив в который дописывать, размер этого массива, указатель на массив
в котором хранится напечатанная команда, 2 символа между которыми надо всё вырезать если что-то было и вставить новое.
То есть если там раньше было ,*2005#, к примеру, то это вырезаем и вставляем новое.
Код:
|
system_cut_and_insert_array(gsm_point_cusd_command , 30, gsm_point_ussd_balance_command, ',', ','); |
Алгоритм такой:
Сначала надо посчитать не превышает ли размер массива (30) новый массив после вставки новой строки.
Поэтому я прогоняю массив, слежу за символами и считаю. После этого проверяю, если превышает, то return
Далее всё что после 2 символа надо потом дописать в хвост. Поэтому я это копирую во временный массив tmp
Далее я стираю всё что после первого символа.
Далее я после первого символа вставляю новую подстроку.
А далее дописываю в хвост тот кусочек ,15\r
Код:
|
void system_cut_and_insert_array(char *source, const uint8_t size, char *insert, char s1, char s2){
uint8_t count = 0, c = 0;
char *point_insert = 0, *point_delete = 0;
char *s = source;
char tmp[size];
char *t = tmp;
while(*s){
if(c){
if(*s == s2) break;
count++;
}
if(*s == s1 && !c){
c = 1;
point_insert = s + 1;
point_delete = point_insert;
}
s++;
}
if((strlen(source) - count + strlen(insert)) › size) return;
while(*s){
*t = *s;
t++;
s++;
}
while(*point_delete){
*point_delete = 0;
point_delete++;
}
while(*insert){
*point_insert = *insert;
point_insert++;
insert++;
}
t = tmp;
while(*t){
*point_insert = *t;
point_insert++;
t++;
}
} |
Скажите? Это конечно сделано по прямолинейной логике. Но может есть какие-нибудь программерские финты, что бы делать это не так размажисто?
|
|
|
|
08.12.2017, 07:56
|
|
Гуру портала
Регистрация: 06.05.2005
Адрес: Краснодар, возле укротворного моря.
Сообщений: 19,058
Сказал спасибо: 2,563
Сказали Спасибо 11,890 раз(а) в 5,964 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
На мой взгляд, проще иметь строковые константы начала и конца строки, между которыми вставляется переменная часть. Выходная строка в этом случае формируется в буфере простой конкатенацией констант и переменной части.
Этот подход более универсальный, чем Ваш. Особенно, если учесть, что есть достаточно много АТ команд, в которых возможно несколько пустых полей, разделенных запятыми.
__________________
Не бейте больно, ежели чо, ну не удержался... А вааще,
"Мы за все хорошее, против всей х..., По лугам некошеным чтобы шли ступни,
Чтобы миром правила правда, а не ложь, Мы за все хорошее, нас не на...!
..." (Ленинград)
Я не несу ответственности за свои действия в Вашей голове.
|
|
|
|
08.12.2017, 09:50
|
|
Модератор
Регистрация: 04.08.2010
Адрес: Москва СЗАО
Сообщений: 11,257
Сказал спасибо: 11,170
Сказали Спасибо 3,858 раз(а) в 2,928 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
А передача последовательно префикса, команды и суффикса не будет сильно проще?
Три строки в подпрограмму…
Если очень нужно в одном поле, то sprintf 'префикс%sсуффикс'.
Распределение буфера можно и динамически - главное не забыть его освободить после использования .
__________________
rtfm forever должно быть основой для каждого. Альтернатива грустна, поскольку метод слепого щенка успешно работает при весьма малом числе вариантов…
|
|
|
|
08.12.2017, 10:04
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
Вся эта белиберда заменяется одной командой sprintf. А для буферов лучше использовать динамическое выделение памяти. Будет более гибко.
И команду strcpy почитайте из stdlib. Зачем городить огород, когда он уже есть?
|
|
|
Сказали "Спасибо" Easyrider83
|
|
|
08.12.2017, 13:34
|
|
Гражданин KAZUS.RU
Регистрация: 02.06.2003
Адрес: Челябинск
Сообщений: 545
Сказал спасибо: 10
Сказали Спасибо 341 раз(а) в 202 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
Сообщение от Easyrider83
|
Вся эта белиберда заменяется одной командой sprintf. А для буферов лучше использовать динамическое выделение памяти. Будет более гибко.
И команду strcpy почитайте из stdlib. Зачем городить огород, когда он уже есть?
|
Вообще-то, есть стандартные библиотечные функции для работы со строкам: strlen, strstr, strcat, strcpy... Или нет?
|
|
|
|
08.12.2017, 17:36
|
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
Если исходить из концепции "чем проще - тем лучше" я бы сделал так...
char gsm_cusd_command[30] = "AT+CUSD=1,";
char* pGsm_point_ussd_balance_command = &char gsm_cusd_command[10];
// то есть место в памяти, где располагается '\0' строки "AT+CUSD=1," я присвоил
//новой переменной, куда будет ввод данных.
// а после окончания ввода в конец надо дописать ",15\r"
// такой алгоритм требует меньше манипуляций со строками
|
|
|
|
09.12.2017, 22:05
|
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Работа с командами GSM под stm32f4 (массивы)
Спасибо за ответы! Захотел проверить ещё одну идею,
Вот я создаю массив указателей
Код:
|
char *gsm_cusd_command[2] = {"AT+CUSD=1,",",15\r"}; |
Получается, что указатель gsm_cusd_command[0] будет указывать на строку AT+CUSD=1,
а gsm_cusd_command[1] на ,15\r
Как передать всё это в функцию одним параметром?
Если так: my_func(gsm_cusd_command){} на работает
void my_func(char *source){}
User\src\gsm.c(149): error: #167: argument of type "char **" is incompatible with parameter of type "char *"
Или только каждый передавать
Код:
|
my_func(gsm_cusd_command[0], gsm_cusd_command[1]){} |
UPD
Сделал указатель на указатель
Код:
|
char *gsm_cusd_part_command[2] = {"AT+CUSD=1,",",15\r"};
char **gsm_point_cusd_command = gsm_cusd_part_command; |
Для доступа к значениям делаю так:
Код:
|
void gsm_merge_command(char **source){
char s
s = *source[0]; - это например доступ к значению первого указателя и его значение 'A'
s = *source[1]; - это например доступ к значению второго указателя и его значение ',' |
Но почему существуют ещё какие-то лишние элементы?
*source[2] будет '@'
*source[3] будет 'e'
Хотя их же нет. Мне просто надо каким-то образом из char **source в ф-ии сосчитать сколько там массивов с указателями. В данном случае должно получиться 2.
Последний раз редактировалось supercelt; 09.12.2017 в 23:58.
|
|
|
|
10.12.2017, 10:09
|
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
Сообщение от supercelt
|
Но почему существуют ещё какие-то лишние элементы?
*source[2] будет '@'
*source[3] будет 'e'
|
Они совсем даже не лишние - вам ничего не мешает обратится по любому offset в массиве.
Если вам хочется красивое и универсальное решение - это можно сделать через классы (CPP). Создаётся класс STRING, в нём перегружается левая и правая операция '+' и вы сможете складывать элементы классов а также классов и строк как простые числа (для строк под '+' понимается конечно конкатенация).
Тогда весь ваш код будет выглядеть приблизительно так:
STRING Tail("AT+CUSD=1,");
STRING End(",15\r");
char gsm_ussd_balance_command; // здесь ввод пользователя
STRING Result();
Result = Tail + char gsm_ussd_balance_command;
Result = Result + End;
char* Output = Result.Get(); //Get() - ещё один метод класса STRING.
Такой пример со строками есть в любом учебнике по CPP
Последний раз редактировалось dgrishin; 10.12.2017 в 10:13.
|
|
|
|
10.12.2017, 15:41
|
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Работа с командами GSM под stm32f4 (массивы)
Сообщение от dgrishin
|
Они совсем даже не лишние
|
Как не лишние, если этих индексов я не создавал?)
Код:
|
char *gsm_cusd_command[2] = {"AT+CUSD=1,",",15\r"}; |
Вот, их же только два, с индексами 0 и 1.
|
|
|
|
10.12.2017, 16:31
|
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: Работа с командами GSM под stm32f4 (массивы)
supercelt, Вы на чём пишете? Как думаете - там есть проверка границ массивов? В C об этом должен заботиться программист.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 21:18.
|
|