检查C struct数组中的member元素的内容

时间:2011-12-03 15:39:46

标签: c arrays struct

我正在做一本书练习(不是家庭作业,因为我是自学),我应该使用类型结构的数组编写电话簿。 所以我定义了:

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. 我是否将数组元素成员初始化为Null(例如cFirstName [10])?
  2. 有更好的方法吗?
  3. 如何检查数组元素成员是否为空?
  4. 提前感谢您的回答!

5 个答案:

答案 0 :(得分:2)

你的ïnitialization方法在某种程度上是不寻常的,因为它基本上将结构归零,memset(&MyContacts,0,sizeof(address)*5)你可以将结构中的所有东西都置为NULL。

您无法检查数组是否为“空”,因为NULL在一般情况下是有效元素。如果确定只有一个C字符串将包含在数组中,那么您只需要检查第一个元素是否为NULL。由于所有C字符串始终以NULL结尾,这意味着您必须始终在字符串末尾添加终止NULL。

答案 1 :(得分:2)

  

所以,我的问题是:

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 ?
     

提前感谢您的回答!

您在初始化struct数组时所做的工作可以改进。

第一个括号说,“用我的内容初始化数组:”

解决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循环。这就是你原来的初始化让我困惑的原因;我不确定它是“正确的”,即使它运行。

然后,你在那些内部放置了更多的括号(如果你仍然想为这个应用程序进行大括号初始化)来初始化结构中的数组:

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);   
    }
}

这允许您创建可变长度的字符串,任意大的联系人列表,如果要检查条目是否为空,只需检查它的指针是否为空:

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

我希望这个概念至少证明对你有用,即使你最终没有使用malloc(在每个程序中有充分的理由支持或反对使用它)。 :)

答案 2 :(得分:1)

你实际上是用0创建你的struct和paddint,因此条件myContacts[i].cFirstName == NULL永远不会成为真,因为你正在创建一个静态数组,它只有在你声明{{{ 1}}作为结构中的指针(cFirstName)。

此外,您的第二个条件与第一个条件基本相同,因为char*只是NULL的预处理器常量。

要测试字符串是否为空,通常将第一个字符与0进行比较,就像上次测试一样。

答案 3 :(得分:1)

我是否将数组元素成员初始化为真正的空(例如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

如果名称设置为“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'终止字符串的长度。

答案 4 :(得分:0)

您应该检查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));

但不知道哪一个效率更高。