11.1 演示数组元素的引用方法
#include <stdio.h>
int main(){
int a[5],i;
printf("input:");
for(i=0;i<5;i++){
scanf("%d",&a[i]); //用下标法引用数组元素
}
for(i=0;i<5;i++){
printf("%4d",a[i]);
}
}
输出结果:input:1
2
3
4
5
1 2 3 4 5
#include <stdio.h>
int main(){
int a[5],i;
printf("input:");
for(i=0;i<5;i++){
scanf("%d",a+i); //等价于&a[i]
}
for(i=0;i<5;i++){
printf("%4d",*(a+i)); //等价于a[i]
}
}
#include <stdio.h>
int main(){
int a[5],*p; //p为指针
printf("input:");
for(p=a;p<a+5;p++){
scanf("%d",p); //用指针法引用数组元素
}
for(p=a;p<a+5;p++){
printf("%4d",*p); //取出指针的指向的值
}
}
#include <stdio.h>
int main(){
int a[5],*p=NULL,i; //p为指针
printf("input:");
p=a;
for(i=0;i<5;i++){
scanf("%d",&p[i]); //等价于p+i,指针p指向的数组元素 a[i] 的地址
}
p=a;
for(i=0;i<5;i++){
printf("%4d",p[i]); //等价于*(p+i)
}
}
11.2 演示数组和指针作为函数参数。
//被调函数的形参声明为数组类型,用下标法访问数组元素
void inputarray(int a[],int n);
void outputarray(int a[],int n);
void inputarray(int a[],int n){ //形参声明是数组,输出数组元素值
int i;
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
}
void outputarray(int a[],int n){
int i;
for(i=0;i<n;i++){
printf("%4d",a[i]);
}
}
//被调函数的形参声明为指针变量,用指针法访问数组元素
void inputarray(int *pa,int n);
void outputarray(int *pa,int n);
void inputarray(int *pa,int n){ //形参声明是指针变量,输出数组元素值
int i;
for(i=0;i<n;i++,pa++){
scanf("%d",pa);
}
}
void outputarray(int *pa,int n){
int i;
for(i=0;i<n;i++,pa++){
printf("%4d",*pa);
}
}
//被调函数的形参声明为数组类型,用指针法访问数组元素
void inputarray(int a[],int n);
void outputarray(int a[],int n);
void inputarray(int a[],int n){ //形参声明是指针变量,输出数组元素值
int i;
for(i=0;i<n;i++){
scanf("%d",a+i);
}
}
void outputarray(int a[],int n){
int i;
for(i=0;i<n;i++){
printf("%4d",*(a+i));
}
}
//被调函数的形参声明为指针变量,用下标法访问数组元素
void inputarray(int *pa,int n);
void outputarray(int *pa,int n);
void inputarray(int *pa,int n){ //形参声明是指针变量,输出数组元素值
int i;
for(i=0;i<n;i++){
scanf("%d",&pa[i]);
}
}
void outputarray(int *pa,int n){
int i;
for(i=0;i<n;i++){
printf("%4d",pa[i]);
}
}
//用数组名作函数实参
#include <stdio.h>
int main(){
int a[5];
printf("input:");
inputarray(a,5);
outputarray(a,5);
}
//用数组名作函数实参
#include <stdio.h>
int main(){
int a[5];
int *p=a;
printf("input:");
inputarray(p,5);
outputarray(p,5);
}
11.3 输入一个3行4列的二维数组,输出这个二维数组的元素值。
#include <stdio.h>
#define N 4
void inputarray(int p[][N],int m,int n);
void outputarray(int p[][N],int m,int n);
int main(){
int a[3][4];
printf("input:");
inputarray(a,3,4);
outputarray(a,3,4);
}
void inputarray(int p[][N],int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%d",&p[i][j]);
}
}
}
void outputarray(int p[][N],int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%4d",p[i][j]);
}
printf("\n");
}
}
输出结果:input:1 2 3 4 5 6 7 8 9 10 11 12
1 2 3 4
5 6 7 8
9 10 11 12
#include <stdio.h>
#define N 4
void inputarray(int (*p)[N],int m,int n); //用二维数组的行指针作函数形参
void outputarray(int (*p)[N],int m,int n);
int main(){
int a[3][4];
printf("input:");
inputarray(a,3,4);
outputarray(a,3,4);
}
void inputarray(int (*p)[N],int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%d",*(p+i)+j); //*(p+i) 表示取二维数组中第 i 行的地址,即指向第 i 行的指针
}
}
}
void outputarray(int (*p)[N],int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%4d",*(*(p+i)+j));
}
printf("\n");
}
}
#include <stdio.h> //用二维数组的列指针作函数形参
#define N 4
void inputarray(int *p,int m,int n);
void outputarray(int *p,int m,int n);
int main(){
int a[3][4];
printf("input:");
inputarray(*a,3,4); //向函数传递第0行第0列的地址
outputarray(*a,3,4);
}
void inputarray(int *p,int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%d",&p[i*n+j]); //取二维数组 p 中第 i 行、第 j 列元素的地址
}
}
}
void outputarray(int *p,int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%4d",p[i*n+j]); //取值
}
printf("\n");
}
}
11.4 用指针数组重新编写第10章例10.4的程序。
#include <stdio.h>
#include <string.h>
#define MAX_LEN 10
#define N 150
void sortstring(char *ptr[],int n);
int main(){
int i,n;
char name[N][MAX_LEN];
char *ptr[N]; //字符指针数组
printf("how many contries:");
scanf("%d",&n);
getchar(); //读走缓冲区的回车符
printf("input:");
for(i=0;i<n;i++){
ptr[i]=name[i]; //让ptr[i]指向二维数组name的第i行
gets(ptr[i]); //输入第i个字符串到ptr[i]指向的内存
}
sortstring(ptr,n); //按字典顺序排序
for(i=0;i<n;i++){
puts(ptr[i]); //输出字符串
printf("%p ",ptr[i]); //输出地址时依旧用ptr[i]
}
}
void sortstring(char *ptr[],int n){ //用指针数组作函数参数
int i,j;
char *temp=NULL; //因为交换的是字符串的地址值,故定义为指针变量
for(i=0;i<n-1;i++){
for(j=i+1;j<n;j++){
if(strcmp(ptr[j],ptr[i])<0){
temp=ptr[i];
ptr[i]=ptr[j]; //注意交换的写法
ptr[j]=temp;
}
}
}
}
输出结果:how many contries:3
warning: this program uses gets(), which is unsafe.
input:american
china
japan
american
china
japan
11.5 命令行参数与函数main()各形参之间的关系。
#include <stdio.h>
int main(int argc,char *argv[]){
int i;
printf("%d\n",argc);
printf("%s\n",argv[0]);
if(argc>1){
for(i=1;i<argc;i++){
printf("%s\n",argv[i]);
}
}
}
11.6 编程输入某班学生某门课的成绩,计算并输出平均分。
#include <stdio.h>
#include <stdlib.h>
void inputarray(int *p,int n);
double average(int *p,int n);
int main(){
int *p=NULL,n;
double aver;
printf("how many contries:");
scanf("%d",&n);
p=(int *)malloc(n*sizeof(int)); //申请内存
if(p==NULL){
printf("no enough memory");
exit(1);
}
printf("input:");
inputarray(p,n);
aver=average(p,n);
printf("aver is %.1f\n",aver);
free(p); //释放内存
}
void inputarray(int *p,int n){
int i;
for(i=0;i<n;i++){
scanf("%d",&p[i]);
}
}
double average(int *p,int n){
int i,sum=0;
for(i=0;i<n;i++){
sum=sum+p[i];
}
return (double)sum/n; //强制类型转换
}
输出结果:how many contries:5
input:90 85 70 95 80
aver is 84.0
11.7 编程输入m个班学生(每班n个学生)的某门课的成绩,计算并输出平均分。二维数组
#include <stdio.h>
#include <stdlib.h>
void inputarray(int *p,int m,int n);
double average(int *p,int m,int n);
int main(){
int *p=NULL,m,n;
double aver;
printf("how many classes:");
scanf("%d",&m);
printf("how many students:");
scanf("%d",&n);
p=(int *)malloc(n*sizeof(int)); //申请内存
if(p==NULL){
printf("no enough memory");
exit(1);
}
printf("input:");
inputarray(p,m,n);
aver=average(p,m,n);
printf("aver is %.1f\n",aver);
free(p); //释放内存
}
void inputarray(int *p,int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%d",&p[i*n+j]);
}
}
}
double average(int *p,int m,int n){
int i,j,sum=0;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
sum=sum+p[i*n+j]; //取值,也可写成*(p+i*n+j)
}
}
return (double)sum/(m*n); //强制类型转换
}
11.8 分析程序中出现的问题。
11.9 分析下面程序能否实现输入一个不带空格的字符串显示到屏幕上。
#include <stdio.H.
char *getstr(void);
int main(){
char *ptr=NULL;
ptr=getstr();
puts(ptr); //试图使用野指针
retune 0;
}
char *getstr(void){
char s[80]; //定义动态存储类型的数组
scanf("%s",s);
return a; //返回动态局部变量的地址
}
#include <stdio.h>
void getstr(char *);
int main(){
char s[80];
char *ptr=s;
getstr(ptr);
puts(ptr); //正确输出
return 0;
}
void getstr(char *s){ //指针形参接收数组实参传递过来的数组首地址
scanf("%s",s);
}
#include <stdio.h>
void getstr(char *);
int main(){
char *ptr=NULL;
getstr(ptr);
puts(ptr); //试图使用空指针
return 0;
}
void getstr(char *s){
scanf("%s",s); //试图使用空指针
}
#include <stdio.h>
void getstr(char *);
int main(){
char *ptr=NULL;
getstr(ptr);
puts(ptr); //试图使用空指针
return 0;
}
void getstr(char *s){
s=(char *)malloc(80); //形参s不能返回函数中动态分配的内存的首地址给实参,这样实参ptr仍为空指针
scanf("%s",s);
}
#include <stdio.h> //可得到正确输出
#include <stdlib.h>
char *getstr(char *);
int main(){
char *ptr=NULL;
ptr=getstr(ptr);
puts(ptr);
free(ptr);
return 0;
}
char *getstr(char *s){
s=(char *)malloc(80);
scanf("%s",s);
return s;
}
输出结果:12345
12345
11.10 分析程序的漏洞。
#include <stdio.h>
#include <stdlib.h>
#define N 10
int main(){
char str[N];
gets(str);
puts(str);
}
会有缓冲区溢出的隐患,当用户输入字符串超过N时,gets()并不限制,会造成缓冲区溢出。
11.11 分析程序的漏洞。
#include <stdio.h>
#include <string.h>
#define N 1024
int main(int argc,char *argv[]){
char buffer[N];
if(argc>1){
strcpy(buffer,argv[1]);
}
}
strcpy()不限制复制字符的长度,会导致缓冲区溢出。用strncpy(),strncat()等会限制字符串最大长度。