第二十八课 字符串、字符数组、字符指针
项目一 【M$pszi$y是嘛意思?】
背景:小明让同学传纸条给小丽。小丽接到会心一笑,大家却不知所云。纸条上写着M$pszi$y,两人暗中约定是,真实字符为实际字符前面的第4个!M$pszi$y是神马意思?推算一下,或从ASCII码表中查一下,自然是I love u。
(1)小明请你写一个程序,在给小丽写情书时,再不用费功夫自己“翻译”,原信中每一个字符加密为其后的第4个字符。例,输入I love u,输出M$pszi$y。
(2)小丽请你写一个程序,在看小明的情书时,让程序帮着“解密”。因为有同学知道了他们俩人的“加密”手段,决定纸条由人传,加密数字(1-9)用两人约好的手势传,所以解密时,需要将加密数字作为程序输入。例,输入M$pszi$y(回车)4,输出I love u
(3)小刚常帮着传纸条,想知道俩人的秘密,但不知道加密数字,于是写了一个程序,可以列出所有可能的情况。例,输入M$pszi$y,多行输出中必然有一行是I love u。你就是小刚,写出这个程序来吧。
(1)小明请你写一个程序,在给小丽写情书时,再不用费功夫自己“翻译”,原信中每一个字符加密为其后的第4个字符。例,输入I love u,输出M$pszi$y。
(2)小丽请你写一个程序,在看小明的情书时,让程序帮着“解密”。因为有同学知道了他们俩人的“加密”手段,决定纸条由人传,加密数字(1-9)用两人约好的手势传,所以解密时,需要将加密数字作为程序输入。例,输入M$pszi$y(回车)4,输出I love u
(3)小刚常帮着传纸条,想知道俩人的秘密,但不知道加密数字,于是写了一个程序,可以列出所有可能的情况。例,输入M$pszi$y,多行输出中必然有一行是I love u。你就是小刚,写出这个程序来吧。
(1)代码:
#include<stdio.h>
int main()
{
char a[50];
int i;
printf("输入原文:");
gets(a);
for(i=0;a[i]!='\0';i++)
a[i]=a[i]+4;
a[i]='\0';
printf("\n密文为:");
puts(a);
return 0;
}
运行结果:
(2)代码:
#include<stdio.h>
int main()
{
int i,num;
char a[30];
printf("输入密文:");
gets(a);
printf("输入加密数:");
scanf("%d",&num);
for(i=0;a[i]!='\0';i++)
a[i]=a[i]-num;
a[i]='\0';
printf("译文为:");
puts(a);
return 0;
}
运行结果:
(3)代码:
#include<stdio.h>
void put(char a[],int n);
int main()
{
int num;
char a[30];
printf("输入密文:");
gets(a);
printf("译文为:\n");
for(num=1;num<9;num++)
put(a,num);
return 0;
}
void put(char a[30],int n)
{
int i;
char b[30];
for(i=0;a[i]!='\0';i++)
b[i]=a[i]-n;
b[i]='\0';
puts(b);
}
运行结果:
项目二【字符统计】
下面的程序可以统计出一个字符串中数字字符的个数:
请分别编制程序,完成下面的处理:
(1)统计字母'A'出现的次数;
(2)统计字符串中(大/小写)字母个数;
(3)统计每一个元音字母个数
(4)统计每一个数字字符出现的次数;
提示:可以定义一个数组int a[10],保存’0’-’9’在字符串中出现的次数(例a[0]表示字符’0’的个数)
(5)统计每一个字母出现的个数
(1)代码:
请分别编制程序,完成下面的处理:
(1)统计字母'A'出现的次数;
(2)统计字符串中(大/小写)字母个数;
(3)统计每一个元音字母个数
(4)统计每一个数字字符出现的次数;
提示:可以定义一个数组int a[10],保存’0’-’9’在字符串中出现的次数(例a[0]表示字符’0’的个数)
(5)统计每一个字母出现的个数
(1)代码:
#include<stdio.h>
int main()
{
char str[50];
int i=0,n=0;
printf("输入字符串:");
gets(str);
while(str[i]!='\0')
{
if(str[i]=='A') n++;
i++;
}
printf("其中字母‘A’的个数是:%d\n",n);
return 0;
}
运行结果:
(2)代码:
#include<stdio.h>
int main()
{
char str[50];
int i=0,n=0,m=0;
printf("输入字符串:");
gets(str);
while(str[i]!='\0')
{
if(str[i]>='A'&&str[i]<='Z')
n++;
else if(str[i]>='a'&&str[i]<='z')
m++;
i++;
}
printf("其中大写字母的个数是:%d\n",n);
printf("其中小写字母的个数是:%d\n",m);
return 0;
}
运行结果:
(3)代码:
#include<stdio.h>
int main()
{
char str[50];
int num[10]={0};
int i=0,n;
printf("输入字符串:");
gets(str);
while(str[i]!='\0')
{
if(str[i]>='0'&&str[i]<='9')
{
n=str[i];
num[n]++;
}
i++;
}
i=0;
while(i<10)
{
printf("%d: %d\n",i,num[i]);
i++;
}
return 0;
}
运行结果:
(4)代码:
#include<stdio.h>
int main()
{
char str[50];
int num[10]={0};
int i=0;
printf("输入字符串:");
gets(str);
while(str[i]!='\0')
{
if(str[i]>='0'&&str[i]<='9')
{
num[str[i]-'0']++;
}
i++;
}
for(i=0;i<10;i++)
printf("%d: %d\n",i,num[i]);
return 0;
}
运行结果:
(5)代码:
#include<stdio.h>
int main()
{
char str[100]={"Checking for existence: D:\\C\\codeBlock\\example\\bin\\Debug\\example.exe"};
int num[26]={0};
int i=0;
puts(str);
while(str[i]!='\0')
{
if(str[i]>='a'&&str[i]<='z')
{
num[str[i]-'a']++;
}
else if(str[i]>='A'&&str[i]<='Z')
num[str[i]-'A']++;
i++;
}
printf("各字母出现次数为:\n");
i=0;
while(i<26)
{
printf("%c: %d\n",(char)i+97,num[i]);
i++;
}
return 0;
}
运行结果:
项目三 【字符串复制】
下面的程序,将str1中除空格外的所有字符,复制到了str2中。
请分别编制程序,完成下面的处理:
(1)完整复制字符串;
(2)将str1和str2接起来存放到str3中;
(3)去除str1中的空格,仍保存在str1中;
(4)将str1和str2连接起来,仍存放在str1中;
请分别编制程序,完成下面的处理:
(1)完整复制字符串;
(2)将str1和str2接起来存放到str3中;
(3)去除str1中的空格,仍保存在str1中;
(4)将str1和str2连接起来,仍存放在str1中;
(1)代码:
#include<stdio.h>
int main()
{
char str1[100]="I am happy boy\'s daddy.",str2[100];
int i=0,j=0;
while(str1[i]!='\0')
{
str2[j++]=str1[i++];
}
str2[j]='\0';
printf("%s\n",str2);
return 0;
}
(2)代码:
#include<stdio.h>
int main()
{
char str1[]={"I am a happy "};
char str2[]={"boy\'s daddy."};
char str3[100];
int i=0,j=0,k=0;
while(str1[i]!='\0')
str3[k++]=str1[i++];
while(str2[j]!='\0')
str3[k++]=str2[j++];
str3[k]='\0';
puts(str3);
return 0;
}
(3)代码:
#include<stdio.h>
int main()
{
char str1[50]={"I am a boy."};
int i=0,t=0;
puts(str1);
while(str1[i+t]!='\0')
{
str1[i]=str1[i+t];
if(str1[i]==' ')
{
t++;
continue;
}
i++;
}
str1[i]='\0';
puts(str1);
return 0;
}
运行结果:
(4)代码:
#include<stdio.h>
int main()
{
char str1[40]={"I am a boy."};
char str2[20]={"//注释:测试专用"};
int i=0,j=0;
while(str1[i]!='\0')
i++;
while(str2[j]!='\0')
{
str1[i++]=str2[j++];
}
str2[j]='\0';
puts(str1);
return 0;
}
运行结果:
项目四 【字符串处理函数】
指针是神奇的,指向整型的指针int *p1,可以操作整型数组int a[];指向字符型的指针char *p2,可以操作字符数组(字符串)char str[];更灵活的是,在函数的传递中,指针、数组名在一定程度上可以互换。请编制函数,对字符串的进行各种操作。
提示1:在完成任务时,自编main函数进行测试,测试中,给出的的实际参数可以是以’\0’结束的字符数组,也可以是指向字符的指针。
提示2:在实际项目中,通过包括string.h头文件,可以调用C语言中操作字符串的函数完成相关操作,而不必专门定义。
序 | 功能 | 用数组名作形参 | 用指针作形参 |
1 | 字符串str1和str2连接,连接后的结果存放到str1中 | char *astrcat(char str1[], char str2[]) | char *pstrcat(char *str1, char *str2) |
2 | 去除字符串str中的特定字符c(如空格),结果仍保存到原字符串中 | char *adelchar(char str[], char c) | char *pdelchar(char *str, char c) |
3 | 求字符串str的长度并返回 | int astrlen(char str[]) | int pstrlen(char *str) |
4 | 统计句子str中单词的个数 | 不再重重复,做右边的(下同) | int pwordnum(char *str) |
5 | 去除句子中第一个单词前的空格,返回去除了空格的字符串 |
| char *ptrim(char *str) |
6 | 去除句子中所有多余的空格,返回去除了空格的字符串 |
| char *palltrim(char *str) |
7 | 比较两个字符串,返回值同strcmp() |
| int pstrcmp(const char *str1, const char *str2) |
提示1:在完成任务时,自编main函数进行测试,测试中,给出的的实际参数可以是以’\0’结束的字符数组,也可以是指向字符的指针。
提示2:在实际项目中,通过包括string.h头文件,可以调用C语言中操作字符串的函数完成相关操作,而不必专门定义。
(1)代码和结果:
#include<stdio.h>
char *astrcat(char *str1,char *str2);
int main()
{
char str1[100]={"Hello world,"};
char str2[50]={"good morning!"};
char *str_a=str1;
char *str_b=str2;
astrcat(str_a,str_b);
printf("%s\n",str1);
return 0;
}
char *astrcat(char *str1,char *str2)
{
int i=0;
char *p;
for(p=str1;*p!='\0';p++);
for(i=0;*(str2+i)!='\0';i++,p++)
{
*p=*(str2+i);
}
*p='\0';
return str1;
}
(2)代码和结果:
#include<stdio.h>
char *adelchar(char str[],char c);
int main()
{
char str[40]="Hello,I am Tom,what is your name?";
adelchar(str,' ');
printf("%s\n",str);
return 0;
}
char *adelchar(char str[],char c)
{
int i=0,j=0;
while(str[j]!='\0')
{
if(str[j]!=' ')
{
str[i]=str[j];
i++;
}
j++;
}
str[i]='\0';
return 0;
}
(3)代码和结果:
#include<stdio.h>
int astrlen(char str[]);
int main()
{
char str[40]="Hello world!";
puts(str);
printf("%d\n",astrlen(str));
return 0;
}
int astrlen(char str[])
{
int i;
for(i=0;str[i]!='\0';i++);
return i;
}
(4)代码和结果:
#include<stdio.h>
int pwordnum(char *str);
int main()
{
char str[80]="My phone number is:123456.one,tow,three,F,f and s!";
puts(str);
printf("共%d个单词\n",pwordnum(str));
return 0;
}
int pwordnum(char *str)
{
int i=0,n=0,t=1;
for(i=0;*(str+i)!='\0';i++)
{
if(((*(str+i)>='a'&&*(str+i)<='z')||(*(str+i)>='A'&&*(str+i)<+'Z'))&&(*(str+i)!='\0'))
{
t=1;
}
else if(t==1)
{
t=0;
n++;
}
}
return n;
}
(5)代码和结果:
#include<stdio.h>
char *ptrim(char *str);
int main()
{
char str[20]=" I am Tom.";
puts(str);
printf("去除空格后为:\n%s\n",ptrim(str));
return 0;
}
char *ptrim(char *str)
{
char *p=str,*q=str;
for(p=str;*p==' ';p++);
while(*p!='\0')
*q++=*p++;
*q='\0';
return str;
}
(6)代码和结果:
#include<stdio.h>
char *palltrim(char *str);
int main()
{
char str[30]=" I have a dream.";
puts(str);
printf("去除多余的空格后显示为:\n%s\n",palltrim(str));
return 0;
}
char *palltrim(char *str)
{
int k=0;
char *p=str,*q=str;
for(q=str;*q!='\0';q++)
{
if(*q!=' '||k)
{
*p=*q;
p++;
}
if(*q!=' ')
k=1;
else
k=0;
}
*p='\0';
return str;
}
(7)代码和结果:
#include<stdio.h>
int pstrcmp(char *str1,char *str2);
int main()
{
char str1[20]="apple";
char str2[20]="orange";
int n;
puts(str1);
puts(str2);
n=pstrcmp(str1,str2);
if(n==1)
printf("%s最大\n",str1);
else if(n==-1)
printf("%s最大\n",str2);
else if(n==0)
printf("两字符串相等\n");
return 0;
}
int pstrcmp(char *str1,char *str2)
{
char *p=str1,*q=str2;
int n=0;
while(*p==*q&&*p!='\0'&&*q!='\0')
if(*p==*q)
{
p++;
q++;
}
if(*p>*q)
n=1;
else if(*p<*q)
n=-1;
return n;
}
项目五 【编程处理C++源代码】
在CodeBlocks等IDE中都提供了代码格式整理的功能。我们可以编写程序,处理的数据就是用C写的源代码文件。C源文件是一种文本文件,可以通过程序进行操作。
(1)读入一个C程序,判断其中是否只有一个main()函数,输出“暂时没有发现问题”,或者“没有main()函数”,或者“不能定义多个main()函数”;
提示1:简单处理,可以只比较判断“main()”,考虑实际上的各种可能,main后面的括号中还有其他多种写法。建议按最简单的情形处理。
提示2:建议设计一个函数,将读到的代码与字符串“main()”进行比较。函数用于判断s1是否“包含”在读入的一行s2中,调用时,形参s1处的实参用“main()”即可,这样写提升了“抽象”级别,更容易实现,对应更高的代码质量。
(2)编写一个程序并取名test.c,统计该文件中出现"if","while","for"的次数。
(3)读入一个C程序,使程序中的所有左花括号“{”和右花括号“}”都单独占一行,新程序保存到另一个.c文件中,并在屏幕上显示处理过的程序,显示时加上行号。
(4)读入一个C程序,输入m、n两个数字,从第m行起的n行代码将作为注释使用(即在这些行前面加上”//”),新程序保存到另一个.c文件中。
(1)读入一个C程序,判断其中是否只有一个main()函数,输出“暂时没有发现问题”,或者“没有main()函数”,或者“不能定义多个main()函数”;
提示1:简单处理,可以只比较判断“main()”,考虑实际上的各种可能,main后面的括号中还有其他多种写法。建议按最简单的情形处理。
提示2:建议设计一个函数,将读到的代码与字符串“main()”进行比较。函数用于判断s1是否“包含”在读入的一行s2中,调用时,形参s1处的实参用“main()”即可,这样写提升了“抽象”级别,更容易实现,对应更高的代码质量。
(2)编写一个程序并取名test.c,统计该文件中出现"if","while","for"的次数。
(3)读入一个C程序,使程序中的所有左花括号“{”和右花括号“}”都单独占一行,新程序保存到另一个.c文件中,并在屏幕上显示处理过的程序,显示时加上行号。
(4)读入一个C程序,输入m、n两个数字,从第m行起的n行代码将作为注释使用(即在这些行前面加上”//”),新程序保存到另一个.c文件中。
(1)代码和结果:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int mainstr(char *line,char *str);
int main()
{
char str[7]="main()";
char line[256];
int num=0;
FILE *p=fopen("test.c","r");
if(p==NULL)
{
printf("file cannot open!\n");
exit (1);
}
while(!feof(p))
{
fgets(line,256,p);
num+=mainstr(line,str);
if(num>1)
break;
}
fclose(p);
if(num==0)
printf("缺少main函数!\n");
else if(num==1)
printf("main函数正常\n");
else
printf("main函数超过限制!\n");
return 0;
}
int mainstr(char *line,char *str)
{
int n=0,k;
char *p,*t;
while(*line!='\0')
{
if(*line==*str)
{
k=1;
p=line;
t=str;
while(*t!='\0')
{
if(*t++!=*p++)
{
k=0;
break;
}
}
if(k==1)
n++;
}
line++;
}
return n;
}
例文件:
(2)代码和结果:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int fun_num(char *line,char *key);
int main()
{
char line[256];
char ifstr[6]="if";
char whilestr[6]="while";
char forstr[6]="for";
int if_num=0,while_num=0,for_num=0;
FILE *p=fopen("test.c","r");
if(p==NULL)
{
printf("open error!");
exit(0);
}
while(!feof(p))
{
fgets(line,256,p);
if_num+=fun_num(line,ifstr);
while_num+=fun_num(line,whilestr);
for_num+=fun_num(line,forstr);
}
fclose(p);
printf("if出现%d次,while出现%d次,for出现%d次\n",if_num,while_num,for_num);
return 0;
}
int fun_num(char *line,char *key)
{
int n,num=0;
char *p,*q;
while(*line!='\0')
{
if(*line==*key)
{
n=1;
p=line;
q=key;
while(*q!='\0')
{
if(*q!=*p)
{
n=0;
break;
}
p++;
q++;
}
if(n==1)
num++;
}
line++;
}
return num;
}
检测代码(1)的结果:
(3)代码和结果:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void funstr(char *test1,char *test2);
void putstr(char *test);
int main()
{
funstr("test1.c","test2.c");
printf("输出结果为:\n");
putstr("test2.c");
printf("\n\n结果保存在test2.c中\n");
return 0;
}
void funstr(char *test1,char *test2)
{
char c1,c2;
FILE *pin=fopen(test1,"r");
FILE *pout=fopen(test2,"w");
if(pin==NULL||pout==NULL)
{
printf("open error!\n");
exit(0);
}
c1='\0';
while(!feof(pin))
{
c2=fgetc(pin);
if((c2=='{'||c2=='}')&&(c1!='\n'))
fputc('\n',pout);
else if((c1=='{'||c1=='}')&&(c2!='\n'))
fputc('\n',pout);
c1=c2;
fputc(c2,pout);
}
fclose(pin);
fclose(pout);
}
void putstr(char *test)
{
int n=1;
char line[256];
FILE *p=fopen(test,"r");
if(p==NULL)
{
printf("error!\n");
exit(0);
}
while(!feof(p))
{
printf("%d ",n);
fgets(line,256,p);
printf("%s",line);
n++;
}
fclose(p);
}
(4)代码和结果:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void putfun(int m,int n);
int main()
{
int m,n;
printf("请输入m,n:");
scanf("%d %d",&m,&n);
putfun(m,n);
return 0;
}
void putfun(int m,int n)
{
char line[256];
int i=0;
FILE *pin=fopen("test1.c","r");
FILE *pout=fopen("test2.c","w");
if(pin==NULL||pout==NULL)
{
printf("error!\n");
exit(0);
}
while(!feof(pin))
{
fgets(line,256,pin);
i++;
if(i>=m&&i<m+n)
{
fputs("//",pout);
}
fputs(line,pout);
}
printf("right!\n");
fclose(pin);
fclose(pout);
}
修改结果:
字符串最后一定要加'\0'作为字符串的结束,切记
本课出现了很多重要的算法,好好理解消化