C语言程序设计 第五章 上机报告
expr1
#include<stdio.h>
int main(){
char string[]="I am a girl.";
printf("%s\n",string);
printf("%c,%c\n",string[5],*(string+7));
return 0;
}
expr1 变式1
#include<stdio.h>
int main(){
Char string[]="I am a girl.";
printf("%s\n",string);
printf("%c,%c\n",string[5],*(string+7));
return 0;
}
我们可以注意到,虽然看起来二者的输出是完全一样的,但其实上发生了本质的区别。一个是以字符串常量的方式存储,并且由一个声明的指针变量指向这个字符串常量的首地址。另外一个是直接声明一段连续的内存,并且数组名就是头指针
expr1 变式2
查阅可以得到printf函数的原型:
int printf(const char *format, ...);
当printf函数进行打印的时候,如果输出的format是%d,%c则传入的是一个确切的值,而对于%s而言传入的是一个char型的指针。
在这个代码之中出现了错误导致了无法输出的错误。
对代码的L5进行了改动之后:
printf("%s,%s\n",string[5],*(string+15));
进行分析可以得出,传入的可以认为是先对string取内容之后的值(其实是以对应的字符的ASCII),然后会访问到其他部分的内容,从而导致报错。
expr2
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char str[100], *p, *q, *r, c;
gets(str);
for(p = str;*p;p++){
for(q=p,r=p; *q; q++)
if(*r > *q)
r = q;
if(r!=p){
c = *r;
*r = *p;
*p = c;
}
}
for(p = str; *p; p++){
for (q = p+1; *q == *p; q++);
strcpy(p+1,q);
}
puts(str);
return 0;
}
以下对于这一个程序填空的代码进行分析
从Line7到Line15的这一个双重for循环之中,本质上完成的是一个选择排序的过程。以q作为一个二级的指针向后访问找到之后的字符串之中的最大值,然后对于二者进行交换。
注意,“交换”交换的是具体的值而不是后续问题之中的地址交换。
所以进行了这一个双重循环加工之后的字符串,是一个递增的字符串。
然后非常巧妙的用Line18的这一个for空语句实现了while类似的功能,把重复出现的字符给删除掉。
expr3
#include<stdlib.h>
#include<stdio.h>
int main(){
char *k = (char*) malloc(sizeof(char)*20);
char str[50];
int count=0,i=0;
gets(k);
while(*k){
str[i++] = *k++, count++;
if((count)%3==0) str[i++] = ' ';
}
str[i++]='\0';
puts(str);
system("pause");
return 0;
}
要注意的事情是Line12的一个加入‘\0’ 的最后,否则会导致其输出的异常。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfOnEJeu-1640236445558)(C:\Users\Bealliant\AppData\Roaming\Typora\typora-user-images\image-20211210144202034.png)]
对于这里面的三个变量的解释:
k:标记的是从字符串k,即复制的来源。
i:标记的是把字符复制进字符串str的时候的
count:标记的是复制的次数。
expr4
#include<stdio.h>
#include<stdlib.h>
#define SIZE 5
int stringcmp(char* p1, char* p2){
while(*p1++ ==* p2++);
return *--p1 - *--p2;
}
int main(){
char *p[SIZE];
for(int i =0; i<SIZE;i++){
char *temp = (char*)malloc(sizeof(char)*20);
gets(temp);
p[i] = temp;
}
char *temp;
printf("-----------\n");
for(int i=0;i<SIZE-1;i++){
for(int j = SIZE-1; j > i; j--){
if(stringcmp(p[j],p[j-1])>0)
temp = p[j], p[j] = p[j-1], p[j-1] = temp;
}
}
for(int i=0;i<SIZE;i++)
puts(p[i]);
return 0;
}
1.注意自定义函数之中的–,因为是边比较边自加,所以会比较完向后加一位。
2.执行的是指针数组之中的一个地址的交换,通过每一个字符串的首地址找到这一整个字符串。
样例只用了五个,方便查看,可以直接在Line3之中对于其进行改变。
expr5
#include<stdlib.h>
#include<stdio.h>
int str2num(char* str, int* num){
int i=0, temp = 0;
while(*str){
if(*str>='0' && *str <= '9')
temp*=10, temp+= *str -'0';
else
num[i++] = temp,temp=0;
str++;
}
num[i++] = temp,temp=0;
// 最后的时候会碰到一个\0的break; 无法向num之中继续写入存了一半的数字
// 之所以return的是i而不是 i-1 是因为0-index和1-index的差距。
return i;
}
int main(){
int num[20],out[20];char str[40];
gets(str);
int size = str2num(str,num);
int k = 0;
for(int i=0;i<size;i++){
int status = 1;
for(int j=0;j<i && status;j++)
if(num[j]==num[i]) status=0;
if(status) out[k++] = num[i];
}
for(int i=0;i<k;i++){
printf("%4d",out[i]);
}
system("pause");
return 0;
}
写了一个函数,可以直接字符串转数组。
一个使用额外内存的数组复制问题。