选择性复制数组和字符串在全国二级C分值高达24分的程序设计题中屡见不鲜。
【问题:复制数组】
函数的功能:将数组s(长度为n)的所以元素复制到数组t,返回复制的元素的个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <stdio.h> int copy_array(int s[], int t[], int n) { int i, j=0; for (i=0; i<n; i++) t[j++] = s[i]; return j; } int main() { int s[6] = {3,6,9,11,18,20}, t[6]; int i, n; n = copy_array(s, t, 6); for (i=0; i<n; i++) printf("%5d",t[i]); printf("\n"); return 0; } |
最简单的版本
1 2 3 4 5 6 7 8 | #include <stdio.h> int copy_array(int s[], int t[], int n) { int i; for (i=0; i<n; i++) t[i] = s[i]; return n; } |
如果数组 t 不用下标 i,而是使用和 i 完全一样的变量 j
1 2 3 4 5 6 7 | int copy_array(int s[], int t[], int n) { int i, j; for (i=0, j=0; i<n; i++, j++) t[j] = s[i]; return n; } |
再改变一下变量 j 的位置,并根据后缀向后移的原则,可以获得下面的程序
1 2 3 4 5 6 7 | int copy_array(int s[], int t[], int n) { int i, j=0; for (i=0; i<n; i++) t[j++] = s[i]; return j; } |
【问题:有选择的复制数组 】
函数的功能:将数组s(长度为n)中的偶数依次复制到数组t,返回复制的元素个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> int copy_array(int s[], int t[], int n) { int i, j=0; for (i=0; i<n; i++) if (s[i]%2==0) t[j++] = s[i]; return j; } int main() { int s[6] = {3,6,9,11,18,20}, t[6]; int i, n; n = copy_array(s, t, 6); for (i=0; i<n; i++) printf("%5d",t[i]); printf("\n"); return 0; } |
函数的功能:删除数组s(长度为n)中的奇数,返回剩余元素的个数。
分析:删除奇数,就是保留偶数,或者说将数组s中的所有偶数复制到数组s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> int copy_array(int s[], int n) { int i, j=0; for (i=0; i<n; i++) if (s[i]%2==0) s[j++] = s[i]; return j; } int main() { int s[6] = {3,6,9,11,18,20}, t[6]; int i, n; n = copy_array(s, 6); for (i=0; i<n; i++) printf("%5d",s[i]); printf("\n"); return 0; } |
如果是字符串,就不需要在函数中传递字符串的长度,因为可以直接根据'\0'标记来判断字符串的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> int string_length(char s[]) { int i, n=0; for (i=0; s[i]!='\0'; i++) n++; return n; } int main() { char s[10] = "abcdefgh"; printf("%d\n", sizeof(s)); printf("%d\n",string_length(s)); return 0; } |
在这个例子中,给字符串预先分配的空间是10,实际使用的空间是8,其中8个字符,一个结束标记'\0'。预先分配的空间可以用sizeof求得,字符串的长度可以使用库函数strlen计算。本例提供了strlen的一种实现方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h> int string_length(char s[]) { int n=0; while (*s!='\0') { n++; s++; } return n; } 或者 int string_length(char s[]) { int n=0; for ( ;*s!='\0'; s++) n++; return n; } |
采用地址算术运算的方式
1 2 3 4 5 6 7 | int strlen(char *s) { char *p = s; while (*p != '\0') p++; return p - s; } |
【问题:字符串的复制】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> void string_copy(char s[], char t[]) { int i; for (i=0; s[i]!='\0'; i++) t[i] = s[i]; t[i]='\0'; } int main() { char a[10] = "abcdefgh", b[10]; string_copy(a, b); printf("%s\n", b); return 0; } |
如果递增的不是i,而是s,则程序如下:
1 2 3 4 5 6 7 | void string_copy(char s[], char t[]) { int i; for (i=0; *s!='\0'; s++) t[i++] = *s; t[i]='\0'; } |
如果t也采取地址递增的方式
1 2 3 4 5 6 7 | #include <stdio.h> void string_copy(char s[], char t[]) { for (; *s!='\0'; s++) *(t++) = *s; *t='\0'; } |
再来欣赏一下库函数中的字符串复制函数是怎么实现的:
1 2 3 4 5 6 | void strcpy(char *s, char *t) { while ((*s = *t) != '\0') { s++; t++; } } |
将递增合并到运算中,得到
1 2 3 4 5 | void strcpy(char *s, char *t) { while ((*s++ = *t++) != '\0') ; } |
和'\0'比较是多余的
1 2 3 4 5 | void strcpy(char *s, char *t) { while (*s++ = *t++) ; } |
1 |