2015-09-01 3 views
0

Можно ли упростить это утверждение с помощью sprintf?Как упростить инструкцию с помощью sprintf?

unsigned char text[50]; 
void decode (unsigned char* msg) 
{ 
    // ON LED 
    if (strstr (msg, "DO1=1") == msg) 
    { 
     LATGbits.LATG1 =1 ; //led1 on 
     sprintf(text,"OK"); // Send the result in HyperTerminal 
     sendString(text) ; 
    } 
    else if (strstr (msg, "DO2=1") == msg) 
    { 
     LATGbits.LATG0 = 0 ; //LED 2 on 
     sprintf(text,"OK"); // Send the result in HyperTerminal 
     sendString(text) ; 
    } 
    else if (strstr (msg, "DO3=1") == msg) 
    { 
     LATGbits.LATG13 = 0 ; //LED 3 on 
     sprintf(text,"OK"); // Send the result in HyperTerminal 
     sendString(text) ; 
    } 
    else if (strstr (msg, "DO4=1") == msg) 
    { 
     LATGbits.LATG14 = 0 ; //LED 4 on 
     sprintf(text,"OK"); // Send the result in HyperTerminal 
     sendString(text) ; 
    } 
    else if (strstr (msg, "DO5=1") == msg) 
    { 
     LATGbits.LATG12 = 0 ; //LED 5 on 
     sprintf(text,"OK"); // Send the result in HyperTerminal 
     sendString(text) ; 
    } 

    // OFF LED 
    else if (strstr (msg, "DO1=0") == msg) 
    { 
     LATGbits.LATG1 =0 ; //LED 1 off 
    } 
      else if (strstr (msg, "DO2=0") == msg) 
    { 
     LATGbits.LATG0 = 1 ; //LED 2 off 
    } 
      else if (strstr (msg, "DO3=0") == msg) 
    { 
     LATGbits.LATG13 = 1 ; //LED 3 off 
    } 
      else if (strstr (msg, "DO4=0") == msg) 
    { 
     LATGbits.LATG14 = 1 ; //LED 4 off 
    } 
      else if (strstr (msg, "DO5=0") == msg) 
    { 
     LATGbits.LATG12 = 1 ; //LED 5 off 
    } 

} 

Из кода выше показывает, например, когда слово "DO1=1" является тип в HyperTerminal, то LED1 включится и "DO1=0" погаснет светодиод. То же самое с DO1 до DO5. Ответы зависят от определения типа LATGbits.

+0

Обратите внимание, что эти проверки дадут ложные срабатывания для чего-то вроде '' DO5 = 01 "' - это было предназначено? –

+0

@MattMcNabb, если эти проверки дадут ложные срабатывания. Ничего не происходит, когда 'DO5 = 01'. Но это похоже на результат. – athirah

ответ

2

Поскольку он состоит полностью из взаимоисключающих вариантов, вы можете избавиться от всех else if бит с небольшим количеством разумного рефакторинга.

Кроме того, то, как вы сравниваете строки, означает, что они должны быть в начале, так что вы можете уйти с strncmp.

И нет необходимости копировать строковый литерал в буфер, а затем отправлять буфер, когда вы можете просто отправить строковый литерал.

внесение тех изменения приведут к коду, как:

#define okayReturn { sendString("OK"); return; } 
void decode (unsigned char* msg) { 
    if (strncmp (msg, "DO1=1", 5) == 0) { 
     LATGbits.LATG1 = 1; 
     okayReturn; 
    } 

    if (strncmp (msg, "DO2=1", 5) == 0) { 
     LATGbits.LATG0 = 0; 
     okayReturn; 
    } 

    : 

    if (strncmp (msg, "DO5=0", 5) == 0) { 
     LATGbits.LATG12 = 1; 
     return; 
    } 
} 

Другой альтернативой является разделить строку на три секции (DO, n и =v где n это одна из цифр 1..5 и v является либо 0 или 1).

Тогда вы можете соединить ориентированный подход данных с использованием переменных указателей, например, с:

#include <ctype.h> 

void decode (unsigned char* msg) { 
    // Variables to change for each n in DOn=v 

    static int *vars[] = { &LATGbits.LATG1, &LATGbits.LATG0, 
     &LATGbits.LATG13, &LATGbits.LATG14, &LATGbits.LATG12 }; 

    // Check content, allowing for upper/lower case. 

    msg[0] = toupper (msg[0]); 
    msg[1] = toupper (msg[1]); 

    if ((msg[0] != 'D') && (msg[1] != 'O')) return; 
    if ((msg[2] < '1') || (msg[2] > '5')) return; 
    if (msg[3] != '=') return; 
    if ((msg[4] != '0') && (msg[4] != '1')) return; 

    // Special case for LED 1 vs 2-5. 

    int on = (msg[2] == '1') ? 1 : 0; 

    // All content validated, make change, first turning on. 

    if (msg[4] == '1') { 
     *(vars[msg[2] - '1']) = on; 
     sendString("OK"); 
     return; 
    } 

    // Or turning off. 

    *(vars[msg[2] - '1']) = 1 - on; 
} 

Обратите внимание на использование toupper(), чтобы заставить первые два символа в верхнем регистре. Это позволяет вводить любой случай, и к нему будет относиться то же самое. Если вам нужна чувствительность к регистру, просто удалите эти две строки.

Хотя это немного сложнее, гораздо короче, особенно, если вы решите добавить больше светодиодов позже.


Имейте в виду, что это будет работать только тогда, когда переменные в vars фактически адресацией. Это не в случае, если они битовые поля, но даже в этом случае, вы можете использовать некоторые из методов, укорочение выше, чтобы минимизировать длину кода и тем самым сделать его более ремонтопригодны:

#include <ctype.h> 

void decode (unsigned char* msg) { 
    // Check content, allowing for upper/lower case. 

    msg[0] = toupper (msg[0]); 
    msg[1] = toupper (msg[1]); 

    if ((msg[0] != 'D') && (msg[1] != 'O')) return; 
    if ((msg[2] < '1') || (msg[2] > '5')) return; 
    if (msg[3] != '=') return; 
    if ((msg[4] != '0') && (msg[4] != '1')) return; 

    // All content validated, make change, either turning off. 

    if (msg[4] == '0') { 
     switch (msg[2]) { 
      case '1': LATGbits.LATG1 = 0; break; 
      case '2': LATGbits.LATG0 = 1; break; 
      case '3': LATGbits.LATG13 = 1; break; 
      case '4': LATGbits.LATG14 = 1; break; 
      case '5': LATGbits.LATG12 = 1; break; 
     } 
     return; 
    } 

    // Or turning on. 

    switch (msg[2]) { 
     case '1': LATGbits.LATG1 = 1; break; 
     case '2': LATGbits.LATG0 = 0; break; 
     case '3': LATGbits.LATG13 = 0; break; 
     case '4': LATGbits.LATG14 = 0; break; 
     case '5': LATGbits.LATG12 = 0; break; 
     default: return; 
    } 
    sendString("OK"); 
} 

Это все еще короткий и только маленький менее прост в расширении, если вы хотите добавить светодиоды. Однако, если вам нужно обновить битовые поля, он все еще хорошо структурирован и прост в понимании.

+0

Когда я пытался, я получил ошибку: не могу принять адрес битового поля «LATG1» .. до LATG12'. это означает, что 'static int' не подходит для' LATG'? – athirah

+0

@athirah, я не понимал, что они были битфилдами, поэтому нет, вы не можете взять их адрес. Тем не менее, вы все равно можете использовать другие методы, чтобы сделать ваш код короче и удобнее обслуживать, см. Обновление. – paxdiablo

+0

Я заметил что-то, когда я нажимаю 'enter', чтобы написать новое слово, он возвращает слово' OK'. это означает 'sendString (« ОК »);' написано вне скобки? – athirah

1

Вы можете изменить это:

unsigned char text[50]; 
void decode (unsigned char* msg) 
{ 
    int on = 0; 
    // ON LED 
    if (strstr (msg, "DO1=1") == msg) 
    { 
     LATGbits.LATG1 =1 ; //led1 on 
     on = 1; 
    } 
    else if (strstr (msg, "DO2=1") == msg) 
    { 
     LATGbits.LATG0 = 0 ; //LED 2 on 
     on = 1; 
    } 
    else if (strstr (msg, "DO3=1") == msg) 
    { 
     LATGbits.LATG13 = 0 ; //LED 3 on 
     on = 1; 
    } 
    else if (strstr (msg, "DO4=1") == msg) 
    { 
     LATGbits.LATG14 = 0 ; //LED 4 on 
     on = 1; 
    } 
    else if (strstr (msg, "DO5=1") == msg) 
    { 
     LATGbits.LATG12 = 0 ; //LED 5 on 
     on = 1; 
    } 

    // OFF LED 
    else if (strstr (msg, "DO1=0") == msg) 
    { 
     LATGbits.LATG1 =0 ; //LED 1 off 
    } 
    else if (strstr (msg, "DO2=0") == msg) 
    { 
     LATGbits.LATG0 = 1 ; //LED 2 off 
    } 
    else if (strstr (msg, "DO3=0") == msg) 
    { 
     LATGbits.LATG13 = 1 ; //LED 3 off 
    } 
    else if (strstr (msg, "DO4=0") == msg) 
    { 
     LATGbits.LATG14 = 1 ; //LED 4 off 
    } 
    else if (strstr (msg, "DO5=0") == msg) 
    { 
     LATGbits.LATG12 = 1 ; //LED 5 off 
    } 

    if (on) 
    { 
     sprintf(text,"OK"); // Send the result in HyperTerminal 
     sendString(text) ; 
    } 
} 
Смежные вопросы