【问题标题】:Find the number of strings in an array of strings in C在C中查找字符串数组中的字符串数
【发布时间】:2012-03-20 08:01:24
【问题描述】:
char* names[]={"A", "B", "C"};

有没有办法找到数组中字符串的数量?例如,在这种情况下,它应该输出:3。

【问题讨论】:

标签: c arrays string numbers


【解决方案1】:

下面的答案是什么

size_t arrLength( char** arr) {
    size_t i = 0;
    size_t count = 0;
    int len;
   len = sizeof(**arr) / sizeof(arr[0]);
    for (i = 0; i < len; i++) {
        printf("%zu - %s\n", count + 1, *(arr + i));
        count++;
    }

    return count;
}

int main(void) {
    char* names[] = { "Jimmy", "Tom", "Michael", "Maria", "Sandra", "Madonna" };
    size_t length, size;

    //size = sizeof(names) / sizeof(names[0]);
    length = arrLength(names);

    printf("\n");
    printf("The number of strings found are %zu\n", length);
    return 0;
}

我得到 1

【讨论】:

    【解决方案2】:

    使用增量运算符使 字符串数组While 循环 中运行,直到循环变为 NULL,给出数组大小:

    #include<stdio.h>
    char* names[]={"A", "B", "C"};
    
    int main(){
    int nameSize = 0;
    while(names[++nameSize]!='\0');
    }
    
    for(i=0;i<nameSize;i++){
    printf("%s\n", names[i]);
    }
    
    return 0;
    }
    

    输出:

    A
    B
    C
    

    【讨论】:

    • 这太错误了(而且很危险)!我想知道为什么它没有崩溃。
    • 它甚至无法编译。
    【解决方案3】:

    您在这里定义的并不是字面上的字符串数组,而是字符指针数组。如果你想知道字符串的数量,你只需要计算指针,就像

    size_t size = sizeof(names)/sizeof(char*);
    

    会这样做,这样你就可以将数组的大小除以单个指针的大小。但请注意,这只适用于在编译时知道数组大小的情况(即数组是静态分配的) ,如果它是动态定义的(即 char** 字符串),那么 sizeof(strings) 将返回指针的大小而不是数组。

    p.s.:字符串的长度不相关,因为数组甚至不“知道”指针指向的内容。

    【讨论】:

      【解决方案4】:

      有没有办法找到数组中字符串的个数

      当然有,试试这个:

      #include<stdio.h>
      
      int main(void){
          size_t size, i=0;
          int count=0;
          char* names[]={"A", "B", "C"};
      
          size = sizeof(names)/sizeof(char*);
      
          for(i=0;i<size;i++){
              printf("%d - %s\n",count+1, *(names+i));
              count++;
          }
      
          printf("\n");
          printf("The number of strings found are %d\n",count);
          return 0;
      }
      
      1 - A
      2 - B
      3 - C
      
      The number of strings found are 3
      

      同样的事情:

      #include<stdio.h>
      
      int main(void){
          size_t size, i=0;
          int count=0;
          char *names[]={"Jimmy", "Tom", "Michael", "Maria", "Sandra", "Madonna"};
      
          size = sizeof(names)/sizeof(char*);
      
          for(i=0;i<size;i++){
              printf("%d - %s\n",count+1, *(names+i));
              count++;
          }
      
          printf("\n");
          printf("The number of strings found are %d\n",count);
          return 0;
      }
      

      输出:

      1 - Jimmy
      2 - Tom
      3 - Michael
      4 - Maria
      5 - Sandra
      6 - Madonna
      
      The number of strings found are 6
      

      或者使用这样的函数:

      #include<stdio.h>
      
      size_t arrLength(size_t len, char **arr){
          size_t i=0;
          size_t count=0;
      
          for(i=0;i<len;i++){
              printf("%zu - %s\n",count+1, *(arr+i));
              count++;
          }
      
          return count;
      }
      
      int main(void){
          char *names[]={"Jimmy", "Tom", "Michael", "Maria", "Sandra", "Madonna"};
          size_t length,size;
      
          size = sizeof(names)/sizeof(char*);
          length = arrLength(size, names);
      
          printf("\n");
          printf("The number of strings found are %zu\n",length);
          return 0;
      }
      

      输出:

      1 - Jimmy
      2 - Tom
      3 - Michael
      4 - Maria
      5 - Sandra
      6 - Madonna
      
      The number of strings found are 6
      

      【讨论】:

        【解决方案5】:

        在 C 中查找字符串数组中的字符串数

        查找数组中对象数量的简单方法是用数组的大小除以其中一个元素的大小。使用sizeof 运算符返回对象的大小(以字节为单位)。

        // For size_t
        #include <stddef.h>
        
        char* names[] = { "A", "B", "C" };
        size_t number_of_strings = sizeof names / sizeof names[0];
        
        printf("Number of strings %zu\n", number_of_strings);
        

        重要的是要考虑从sizeof 返回的类型是size_t,这是一种能够索引任何数组以及任何对象大小的无符号整数类型。要打印size_t 类型的变量,请使用修饰符z

        【讨论】:

          【解决方案6】:

          对于数组,如赏金中的示例,执行sizeof(names)/sizeof(names[0]) 足以确定数组的长度。

          示例中的字符串长度不同这一事实并不重要。 nameschar * 的数组,因此数组的总大小(以字节为单位)是数组中元素的数量乘以每个元素的大小(即 char *)。这些指针中的每一个都可以指向任意长度的字符串,或者指向 NULL。没关系。

          测试程序:

          #include<stdio.h>
          
          int main(void)
          {
              char* names1[]={"A", "B", "C"}; // Three elements
              char* names2[]={"A", "", "C"}; // Three elements
              char* names3[]={"", "A", "C", ""}; // Four elements
              char* names4[]={"John", "Paul", "George", "Ringo"}; // Four elements
              char* names5[]={"", "B", NULL, NULL, "E"}; // Five elements
          
              printf("len 1 = %zu\n",sizeof(names1)/sizeof(names1[0]));
              printf("len 2 = %zu\n",sizeof(names2)/sizeof(names2[0]));
              printf("len 3 = %zu\n",sizeof(names3)/sizeof(names3[0]));
              printf("len 4 = %zu\n",sizeof(names4)/sizeof(names4[0]));
              printf("len 5 = %zu\n",sizeof(names5)/sizeof(names5[0]));
          }
          

          输出:

          len 1 = 3
          len 2 = 3
          len 3 = 4
          len 4 = 4
          len 5 = 5
          

          编辑:

          澄清一下,这仅适用于您定义了一个数组,即char *names[]char names[][],并且您处于定义数组的范围内。如果它被定义为char **names,那么你有一个指针,它作为一个数组起作用,上述技术将不起作用。同样,如果char *names[] 是函数参数,则数组衰减到第一个元素的地址。

          【讨论】:

          • 谢谢。您给出的解释非常好,这是关键。我想基于 cnicutar 的答案应该是接受的答案的解释,因为它给出了相同的答案但没有解释,但到目前为止,这个答案是赏金的主要候选人。谢谢。
          • 如果数组为空会怎样?
          • @Niels 包含 0 个元素的数组是标准不允许的。
          【解决方案7】:

          返回数组中的数字或字符串的一种简单方法是遍历数组,直到字符串用完。这是一个例子。

          #include <stdio.h>
          
          int main()
          {
              char* names[] = {"John", "Paul", "George", "Ringo", '\0'};
          
              int size = 0;
              while(names[++size]!='\0');
          
              printf("Size: %d\n", size); // Prints "4"
          
              return 0;
          }
          

          这种方法的优点是它即使在字符串长度不同时也能工作。注意 names 数组中的终止 NULL 字节,以及用于关闭 while 语句的 ; 字符,因为没有要运行的语句体。

          【讨论】:

          • 只有在 *names[] 数组的最后一个元素为 NULL 并且在 while 循环中与 NULL 进行比较时,这才有效吗?否则,您将依赖存储字符串的内存“归零”,但情况并非总是如此!因此,上面的代码不是很安全或可靠。
          • 补充以上内容,我的理解是在上面的代码中,您存储了一个指向字符串的指针数组。该数组当前有 4 个元素(即 4 个指向字符串的指针)。每个字符串都以空值结尾,但您的指针数组默认情况下没有终止记录 - 您需要手动设置它,NULL 是最后一条记录的理想候选者。这样,您可以通过与NULL 进行比较,轻松地在while 循环中识别它。我希望我的解释是清楚的,我的理解是正确的。
          • @mike:你是对的,我已经编辑了代码来解释你的观察。谢谢。
          • 最后一个条目为'\0',而正确原则上语义不清晰。最后一个'\0' 代表一个空指针常量——最好使用NULL0
          • 这仍然是错误的。你甚至尝试编译它吗?您不能将像 '\0' 这样的字符常量与指向字符的指针进行比较。
          【解决方案8】:

          这取决于您的数组是如何创建的。在 C 中,没有办法检查作为指针的数组的长度,除非它具有哨兵元素,或者与数组一起传递的整数作为数组中元素的计数。在你的情况下,你可以使用这个:

          int namesLen = sizeof(names) / sizeof(char);
          

          但是,如果你的数组是一个指针,

          char **names = { "A", "B", "C" };
          

          你可以有一个整数,对于数组的长度是恒定的:

          int namesLen = 3;
          

          或者添加一个标记值(例如NULL)

          char **names = { "A", "B", "C", NULL };
          
          int namesLen = -1;
          while (names[++namesLen] != NULL) { /* do nothing */}
          
          // namesLen is now the length of your array
          

          作为另一种方式,您可以创建一个填充有您想要的值的结构:

          struct Array {
              void **values;
              int length;
          };
          
          #define array(elements...) ({ void *values[] = { elements }; array_make(values, sizeof(values) / sizeof(void *)); })
          #define destroy(arr) ({ free(arr.values); })
          
          struct Array array_make(void **elements, int count)
          {
              struct Array ret;
              ret.values = malloc(sizeof(void *) * count);
              ret.length = count;
          
              for (int i = 0; i < count; i++) {
                  ret.values[i] = elements[i];
              }
          
              return ret;
          }
          

          你会这样使用它:

          struct Array myArray = array("Hi", "There", "This", "Is", "A", "Test");
          // use myArray
          
          printf("%i", myArray.length);
          destroy(myArray);
          

          【讨论】:

          • 你应该除以 sizeof(char *) 或 sizeof(*names),而不是 sizeof(char)
          【解决方案9】:
          int count = sizeof(names)/sizeof(*names);
          

          这将names 的总大小除以names 中一个元素的大小,得到3。

          【讨论】:

          • “不适用于动态分配的内存”。更具体地说,如果数组(与“数组的成员”相反)已被动态分配,则它不起作用。由于这是一个指针数组,因此需要进行区分。
          【解决方案10】:

          在这种情况下,您可以将总大小除以第一个元素的大小:

          num = sizeof(names) / sizeof(names[0]);
          

          但请注意,这适用于 数组。它不适用于指针。

          【讨论】:

          • 许多代码库将其定义为宏,例如:#define ARRAY_SIZE(x) ( sizeof(x) / sizeof((x)[0]) )
          • 这个答案应该是公认的答案。这是第一个答案,它是正确的。也就是说,赏金我授予第一个答案,解释了为什么这样做。
          • 我用我的数组 array[]={".A.","..B",".C.",".D.","..E",} 尝试了 sizeof我得到了 5 个中的第 3 个 ..... 使用 sizeof 和 strlen
          • 我得到:“sizeof”对不完整类型“const char *[]”的无效应用
          猜你喜欢
          • 2020-06-19
          • 1970-01-01
          • 2019-02-01
          • 2017-03-22
          • 2015-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多