# 数组 在实际开发中,经常需要查询数组中的元素。例如,学校为每位同学分配了一个唯一的编号,现在有一个数组,保存了实验班所有同学的编号信息,如果有家长想知道他的孩子是否进入了实验班,只要提供孩子的编号就可以,如果编号和数组中的某个元素相等,就进入了实验班,否则就没进入。不幸的是,C语言标准库没有提供与数组查询相关的函数,所以我们只能自己编写代码。 1. 对无序数组的查询 所谓无序数组,就是数组元素的排列没有规律。无序数组元素查询的思路也很简单,就是用循环遍历数组中的每个元素,把要查询的值挨个比较一遍。 ```c #include int main(){ int nums[10] = {1, 10, 6, 296, 177, 23, 0, 100, 34, 999}; int i, num, thisindex = -1; printf("Input an integer: "); scanf("%d", &num); for(i=0; i<10; i++){ if(nums[i] == num){ thisindex = i; break; } } if(thisindex < 0){ printf("%d isn't in the array.\n", num); }else{ printf("%d is in the array, it's index is %d.\n", num, thisindex); } return 0; } ``` 2. 对有序数组的查询 查询无序数组需要遍历数组中的所有元素,而查询有序数组只需要遍历其中一部分元素。例如有一个长度为 10 的整型数组,它所包含的元素按照从小到大的顺序(升序)排列,假设比较到第 4 个元素时发现它的值大于输入的数字,那么剩下的 5 个元素就没必要再比较了,肯定也大于输入的数字,这样就减少了循环的次数,提高了执行效率。 ```c #include int main(){ int nums[10] = {0, 1, 6, 10, 23, 34, 100, 177, 296, 999}; int i, num, thisindex = -1; printf("Input an integer: "); scanf("%d", &num); for(i=0; i<10; i++){ if(nums[i] == num){ thisindex = i; break; }else if(nums[i] > num){ break; } } if(thisindex < 0){ printf("%d isn't in the array.\n", num); }else{ printf("%d is in the array, it's index is %d.\n", num, thisindex); } return 0; } ``` ## 字符数组和字符串 初始化 ```c char str[30] = {"wangyuedong"}; char str[30] = "wangyuedong"; //这种形式更加简洁,实际开发中常用 //也可以不指定长度 char str1[] = {"wang"}; char str1[] = "wang"; //这种形式更加简洁,实际开发中常用 ``` 这里需要留意一个坑,字符数组只有在定义时才能将整个字符串一次性地赋值给它,一旦定义完了,就只能一个字符一个字符地赋值了。 ### 字符串结束标志 字符串是一系列连续的字符的组合,要想在内存中定位一个字符串,除了要知道它的开头,还要知道它的结尾。找到字符串的开头很容易,知道它的名字(字符数组名或者字符串名)就可以;然而,如何找到字符串的结尾呢?C语言的解决方案有点奇妙,或者说有点奇葩。 在C语言中,字符串总是以`'\0'`作为结尾,所以`'\0'`也被称为字符串结束标志,或者字符串结束符。`'\0'`是 ASCII 码表中的第 0 个字符,英文称为 NUL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志。C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到`'\0'`就认为到达了字符串的末尾,就结束处理。`'\0'`至关重要,没有`'\0'`就意味着永远也到达不了字符串的结尾。 由`" "`包围的字符串会自动在末尾添加`'\0'`。例如,`"abc123"`从表面看起来只包含了 6 个字符,其实不然,C语言会在最后隐式地添加一个`'\0'`,这个过程是在后台默默地进行的,所以我们感受不到。 需要注意的是,逐个字符地给数组赋值并不会自动添加`'\0'`。 ```c char str[] = {'a', 'b', 'c'}; ``` 数组 str 的长度为 3,而不是 4,因为最后没有`'\0'`。 当用字符数组存储字符串时,要特别注意`'\0'`,要为`'\0'`留个位置;这意味着,字符数组的长度至少要比字符串的长度大 1。 ```c char str[7] = "abc123"; ``` `"abc123"`看起来只包含了 6 个字符,我们却将 str 的长度定义为 7,就是为了能够容纳最后的`'\0'`。如果将 str 的长度定义为 6,它就无法容纳`'\0'`了。 示例 ```c #include int main(){ char str[30]; char c; int i; for(c=65,i=0; c<=90; c++,i++){ str[i] = c; } printf("%s\n", str); return 0; } ``` 数组总共才 30 个元素,到了第 50 个元素不早就超出数组范围了吗?是的,的确超出范围了!然而,数组后面依然有其它的数据,printf() 也会将这些数据作为字符串输出。 改良 ```c #include int main(){ char str[30]; char c; int i; for(c=65,i=0; c<=90; c++,i++){ str[i] = c; } str[i] = 0; //此处为添加的代码,也可以写作 str[i] = '\0'; printf("%s\n", str); return 0; } ``` 这样的写法貌似有点业余,或者说不够简洁,更加专业的做法是将数组的所有元素都初始化为“零”值,这样才能够从根本上避免问题。 进一步改良 ```c #include int main(){ char str[30] = {0}; //将所有元素都初始化为 0,或者说 '\0' char c; int i; for(c=65,i=0; c<=90; c++,i++){ str[i] = c; } printf("%s\n", str); return 0; } ``` ### 字符串长度 所谓字符串长度,就是字符串包含了多少个字符(不包括最后的结束符`'\0'`)。例如`"abc"`的长度是 3,而不是 4。在C语言中,我们使用`string.h`头文件中的 strlen() 函数来求字符串的长度。 ```c #include #include #include int main(int argc, char *argv[]){ char str[100] = {0}; scanf("%s", &str); long str_len = strlen(str); printf("The string length: %d\n", str_len); system("pause"); return 0; } ```