проверка содержимого элемента-члена в массиве структуры C - PullRequest
0 голосов
/ 03 декабря 2011

Я выполняю упражнение с книгой (не домашнее задание, так как я самообучаюсь), в котором я должен написать телефонную книгу, используя массив структур типа.Итак, я определил:

typedef struct contact {

    char cFirstName[10];
    char cLastName[10];
    char iTelphone[12];

} address ; // end type

Далее я определил:

address myContacts[5] = { 
                        { 
                { '\0' }  // inner most braces, 
                          // tell gcc to put 0 in all
                      // members of each struct ?
                }  // first braces, tell gcc we have a 
                   // a struct as array member
                }; // outer most braces, tell gcc we have 
                   // an array

Теперь у меня есть функция, которая печатает содержимое массива.Однако я не хочу печатать весь массив, потому что меня интересуют только элементы массива, члены которых не пусты.Итак, я попробовал следующее:

void printContacts( address * myContacts ){
    printf("Inside printContacts");
    int i = 0;

    while ( i < 5 ) {
        if (myContacts[i].cFirstName == NULL )
            printf("%s", myContacts[i].cFirstName); //does not work

        if (myContacts[i].cFirstName == '\0' )
            printf("%s", myContacts[i].cFirstName); //does not work

        if (myContacts[i].cFirstName[0] != 0 )
        {
            printf("%s", myContacts[i].cFirstName ); //does work!   
        }
        i++;
    }
}

Итак, мои вопросы:

  1. Я инициализирую элементы массива как действительно нулевые (например, cFirstName [10])?
  2. Есть ли лучший способ?
  3. Как проверить, что элемент массива пуст?

Заранее спасибо за ваши ответы!

Ответы [ 5 ]

2 голосов
/ 03 декабря 2011

Итак, мои вопросы:

Am I initializing the array elements members to be really null (e.g cFirstName[10]) ?
Is there a better way ?
How can I check that an array element member is empty ?

Заранее спасибо за ваши ответы!

То, что вы сделали при инициализации массива структуры, может быть улучшено.

Первая фигурная скобка говорит: «инициализируйте массив с моим содержимым:»

address myContacts [5] = {...}

Второй набор фигурных скобок говорит, "инициализировать первую структуру в массиве следующим образом:"

address myContacts[5] = { 
    { ... } ,   // each of these braces initializes a different struct in the 
    { ... } ,   // array (there are five inner brace sets as there are five  
    { ... } ,   // structs in the array).
    { ... } ,
    { ... }
 }

Обратите внимание, что это хорошая форма, чтобы инициализировать все элементы массива за раз, или использовать для этого цикл for.Вот почему ваша первоначальная инициализация смущает меня;Я не уверен, что это «правильно», даже если он работает.

Затем вы помещаете в них больше фигурных скобок (если вы все еще хотите выполнить инициализацию фигурных скобок для этого приложения), чтобы инициализировать массивы вstruct:

address myContacts[5] = { 
    {{'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'},
     {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'},
     {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0, '\0', '\0'} },
     .
     .
     .
 }

Это способ «обнуления» вашего массива сначала с помощью скобочной записи.Не слишком много людей делают это;это становится утомительным.Обычно для реального приложения люди используют кучу (память, которую вы можете выделить на лету, как показано ниже) для чего-то подобного, в этом случае вы можете просто использовать указатели в своей структуре:

typedef struct contact {

    char *cFirstName;
    char *cLastName;
    char *iTelphone;

} address ; // end type

Затем вы должны выделить список контактов:

address *myContacts = (address*) malloc(sizeof(address)*5); 
                      // the above allocates a five-element array
int i;
for (i = 0; i < 5; i++)
{
    myContacts[i].cFirstName = NULL;
    myContacts[i].cLastName = NULL;
    myContacts[i].iTelephone = NULL;
}

выделить строки, когда вам нужно добавить в адресную книгу:

myContacts[0].cFirstName = (char*) malloc(sizeof(char)*20);
strcpy(myContacts[0].cFirstName,"Tom, Dick, or Harry");

и когда вы закончите, освободите всеВы выделили:

int i;
for (i = 0; i < 5; i++)
{
    if (myContacts[i].cFirstName != NULL) // since we initialized all pointers 
    {                                     // to null, this only isn't null when
        free(myContacts[i].cFirstName);   // it's been previously allocated
    }
    if (myContacts[i].cLastName != NULL)
    {                                    
        free(myContacts[i].cLastName);   
    }
    if (myContacts[i].iTelephone != NULL) 
    {                                     
        free(myContacts[i].iTelephone);   
    }
}

Это позволяет вам создавать строки переменной длины, произвольно большие списки контактов, и если вы хотите проверить, является ли запись пустой, просто проверьте, является ли она указателемis null:

if (myContacts[i].cFirstName != NULL)
{
    printf("%s", myContacts[i].cFirstName ); //does work!
}

Я надеюсь, что эта концепция, по крайней мере, окажется полезной для вас, даже если вы в конечном итоге не используете malloc (есть веские причины за или против ее использования в каждой программе).:)

2 голосов
/ 03 декабря 2011

Ваш метод инициализации является чем-то необычным, для которого фактически обнуляется структура, с помощью memset(&MyContacts,0,sizeof(address)*5) вы можете поместить в NULL все, что есть в вашей структуре.

Вы не можете проверить, является ли массив «пустым», поскольку NULL является допустимым элементом в общих чертах. Если вы установили, что в массиве будет содержаться только строка C, то вам нужно только проверить, равен ли первый элемент NULL или нет. Поскольку все строки C всегда заканчиваются на NULL, это означает, что вы всегда должны добавлять завершающий NULL в конце вашей строки.

1 голос
/ 03 декабря 2011

Я инициализирую элементы-элементы массива как действительно нулевые (например, cFirstName [10])?

Вы в основном назначаете первый символ строкового буфера для '\ 0' (илиэквивалентно 0.)

Например, значение переменной name ниже относится к указателю на строковый буфер.Так что в этом случае, если вы сравните указатель с 0 или '\ 0', они не будут равны.

int i;
char name[10] = {'\0'};

printf("Raw content: ");
for(i = 0 ; i < 10 ; ++i)
    printf("%2d ", name[i]);
printf("\n\n");

printf("name = %p\n\n", name);
printf("*name = %d, name[0] = %d\n\n", *name, name[0]);

Это дает:

Raw content:  0  0  0  0  0  0  0  0  0  0

name = 0012FF48

*name = 0, name[0] = 0

Если вместо этого установлено имяto "Hello":

Raw content: 72 101 108 108 111  0  0  0  0  0

name = 0012FF48

*name = 72, name[0] = 72

Есть ли лучший способ?

Не уверен, правильно ли я понял ваш вопрос: чтобы убедиться, что каждый элемент массива xустановлено значение y, вы можете использовать функцию memset.

Как проверить, что элемент элемента массива пуст?

Чтобы проверить наличие пустой строки,Вы можете использовать функцию strlen, чтобы узнать длину строки, оканчивающейся на \ 0.

1 голос
/ 03 декабря 2011

Вы фактически создаете свою структуру и добавляете ее с помощью 0, следовательно, условие myContacts[i].cFirstName == NULL никогда не будет истинным, поскольку вы создаете статический массив, оно будет работать, только если вы объявите cFirstName в качестве указателя (char*) в вашей структуре.

Кроме того, ваше второе условие по существу совпадает с первым, поскольку NULL является только константой препроцессора для 0.

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

0 голосов
/ 03 декабря 2011

Вы должны проверить myContacts[i].cFirstName[0], поскольку myContacts[i].cFirstName является указателем на массив char.


Подробное объяснение

Для вашего первого вопроса: Да, вы уже инициализировали всеэлементы myContacts пусто.Причина, по которой первые два теста не пройдены, заключается в том, что myContacts[i].cFirstName является указателем на массив char, который не является NULL.Когда вы определяете массив myContacts, он располагается в стеке и myContacts[i] указывает на какое-то место / адрес в стеке, которое не является NULL.

Второе: вы также можете инициализировать массив с помощью

address myContacts[5]; // define an address array with 5 elements
memset((void*)myContacts, 0, sizeof(myContacts));

Но понятия не имею, какой из них лучше по эффективности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...