2016-11-06 7 views
1

Обычно, когда я хочу, чтобы проверить, если больше ввода хранится в нескольких строках не пустует я следовать этому простому подходу:Проверьте, если несколько строк являются пустыми и напечатать их имя

std::string fieldA = ""; 
std::string fieldB = ""; 
std::string fieldC = "Hello"; 

Теперь я могу проверить для всех :

if (fieldA.empty() || fieldB.empty() || fieldC.empty()) 
    std::cout << "Oh oh.. one or more fields are empty << std::endl; 

Но было бы неплохо знать, какие поля пусты, то я могу написать:

if (fieldA.empty()) 
    std::cout << "fieldA is empty" << std::endl; 
if (fieldB.empty()) 
    std::cout << "fieldB is empty" << std::endl; 
if (fieldC.empty()) 
    std::cout << "fieldC is empty" << std::endl; 

Но в го я могу обнаружить, что fieldA пуст, но не fieldB, и в этом примере у меня есть только три поля, но с большим количеством полей?

Какова наилучшая практика управления несколькими строками и поиск пустой строки?

+8

Научиться использовать массивы или классы контейнеров вместо отдельных строковых переменных. Тогда остальное становится легким. – PaulMcKenzie

+0

Имена переменных не доступны для кода во время выполнения в обычном ходе событий. Если вы хотите связать имена со значениями во время выполнения, вам нужна какая-то карта. – EJP

+0

Считайте, что имена переменных в вашем коде и тексте, видимые пользователем, должны быть разными, во всяком случае. Ваша переменная может быть названа 'fieldFirstName', но пользователь должен увидеть что-то вроде« Имя ». –

ответ

2

PaulMcKenzie Комментарий является тем, за которым следует следовать. Но предполагается, что ваш пример является более упрощение кода, и вы не можете поместить все переменные в массиве, я думаю, вы можете быть оправданной, если вы используете немного макрос сделать stringification для вас:

#define PRINT_IF_EMPTY(var) \ 
do { \ 
    if (var.empty()) \ 
    std::cout << #var " is empty" << std::endl; \ 
} while(0) 

Теперь вы можете заменить свой код с этим:

PRINT_IF_EMPTY(fieldA); 
PRINT_IF_EMPTY(fieldB); 
PRINT_IF_EMPTY(fieldC); 
+0

Честно говоря, нет, я не думаю, что это можно извинить. Я бы, конечно, боролся с ним в любом обзоре кода! :) –

+0

@ChristianHackl, вы бы не сильно повлияли, если такие макросы являются частью утилиты для отладки и получают условную компиляцию :) – StoryTeller

+0

Дело не в том, скомпилированы они или нет (на самом деле я бы * не * хотел для удаления важной информации об отладке в сборках релизов, где это необходимо больше всего, но это не должно быть просто написано на stdout, конечно). Дело в том, что они делают код более трудным для чтения.Макрос также не указывает, что он существует только для отладки и не скомпилирован с определенными настройками компилятора. Кроме того, он использует 'std :: endl', который, скорее всего, будет' '\ n'', но это незначительный nitpick. –

0

это лучше использовать контейнер (std::vector, std::list, std::array и т.д.) для подобного типа данных.

Предположим, вы сохранили свой std::string в std::vector.

std::vector<std::strting> data; 
// Now you have to insert std::string in std::vector. 

for(int i = 0; i < data.size(); i++) { 
    if(data[i].empty()) 
     std::cout << "field" << (char)i+65 << " is empty \n"; 
} 
0

Вы должны использовать отдельный класс FieldValidator. При этом ваш код должен выглядеть так:

FieldValidator val; 
val.requireNotEmpty("field1", field1); 
val.requireNotEmpty("field2", field2); 

Идея состоит в том, что все состояние проверки хранится в одном месте. Я уверен, что такой класс уже существует где-то, так как вы не первый, кто решил эту задачу.

0

Вы можете использовать для диапазона цикла над списком инициализатора, если печать которых поле пусто не является обязательной, и если вы предпочитаете поля быть различными переменными:

for (const std::string str : {fieldA, fieldB, fieldC}) 
{ 
    if (str.empty()) 
    { 
     std::cout << "One or more fields are empty." << std::endl; 
     break; // Break out of the for loop 
    } 
}