- no.1 字符统计
- no.2 删除指定字符
- no.3 情书解密
- no.4 字符串处理函数
- no.5 编程处理C++源代码
NO.1 字符统计
编写一函数,由实参传来一个字符串,统计此字符串中字母、数字、空格和其它字符的个数,在主函数中输入字符串以及输出上述的结果。
代码
#include<stdio.h>
#include<string.h>
#include<ctype.h>
/** 字符统计函数fltj(char str[], int a[])
*统计str[]中字母、数字、空格及其他字符数目并将结果放入数组a[]
* 输入:str[],a[];
* 输出:a[]
*/
void fltj(char str[], int a[])
{
int ll,i;
ll=strlen(str); //ll赋值为字符串长度(真实长度,不含'\0')
for (i=0; i<ll; i++)
{
if (isalpha(str[i])) a[0]++; //统计字母个数
else if (isdigit(str[i])) a[1]++; //统计数字个数
else if (isspace(str[i])) a[2]++; //统计空格数
else a[3]++;
}
}
int main()
{
static char str[60];
static int a[4]= {0,0,0,0};
gets(str);
fltj(str,a);
printf("%s char:%d digit:%d space:%d other:%d",str,a[0],a[1],a[2],a[3]);
return 0;
}
执行结果
NO.2 删除指定字符
有一行文字,要求删去某一个字符。此行文字和要删去的字符均由键盘输入,要删去的字符以字符形式输入(如输入a表示要删去所有的 a字符)。
代码
#include<stdio.h>
int main()
{
/*str1表示原来的一行文字,str2表示删除指定字符后的文字*/
char str1[100],str2[100];
char ch;
int i=0,k=0;
printf("please input an sentence:\n");
gets(str1);
scanf("%c",&ch);
for (i=0; str1[i]!='\0'; i++)
if (str1[i]!=ch)
{
str2[k]=str1[i];
k++;
}
str2[k]='\0';
printf("\n%s\n",str2);
return 0;
}
执行结果
NO.3 情书解密
背景:小明让同学传纸条给小丽。小丽接到会心一笑,大家却不知所云。纸条上写着M
p
s
z
i
pszi
psziy,两人暗中约定是,真实字符为实际字符前面的第4个!M
p
s
z
i
pszi
psziy是神马意思?推算一下,或从ASCII码表中查一下,自然是I love u。
(1)小明请你写一个程序,在给小丽写情书时,再不用费功夫自己“翻译”,原信中每一个字符加密为其后的第4个字符。例,输入I love u,输出M
p
s
z
i
pszi
psziy。
(2)小丽请你写一个程序,在看小明的情书时,让程序帮着“解密”。因为有同学知道了他们俩人的“加密”手段,决定纸条由人传,加密数字(1-9)用两人约好的手势传,所以解密时,需要将加密数字作为程序输入。例,输入M
p
s
z
i
pszi
psziy(回车)4,输出I love u
(3)小刚常帮着传纸条,想知道俩人的秘密,但不知道加密数字,于是写了一个程序,可以列出所有可能的情况。例,输入M
p
s
z
i
pszi
psziy,多行输出中必然有一行是I love u。你就是小刚,写出这个程序来吧。
代码一
#include<stdio.h>
#include<string.h>
#define SIZE 20
int main()
{
char ming[SIZE];
int i;
printf("XiaoMing means:\n");
gets(ming);
for(i=0;ming[i]!='\0';i++)
ming[i]+=4;
printf("XiaoMing says:\n");
puts(ming);
return 0;
}
执行结果
代码二
#include<stdio.h>
#include<string.h>
#define SIZE 20
int main()
{
char li[SIZE];
int i,n;
printf("XiaoLi receives:\n");
gets(li);
printf("Input encrypted number:\n");
scanf("%d",&n);
for(i=0;li[i]!='\0';i++)
li[i]-=n;
printf("XiaoLi gets:\n");
puts(li);
return 0;
}
执行结果
代码三
#include<stdio.h>
#include<string.h>
#define SIZE 20
int main()
{
char li[SIZE],putli[SIZE]; //也可以用putli[SIZE]={'\0'}初始化
int i,n;
memset(putli,'\0',SIZE); //初始化putli[]字符数组
printf("XiaoLi receives:\n");
gets(li);
do
{
printf("Input encrypted number:\n");
//fflush(stdin);
scanf("%d",&n);
for(i=0; li[i]!='\0'; i++)
putli[i]=li[i]-n;
putli[i]='\0';
printf("XiaoLi gets:\n");
puts(putli);
}
while(n!=0);
return 0;
}
执行结果
小结
如果内循环结束没有putli[i]='\0';
,那么后面会跟着一堆乱码,从而影响结果。
NO.4 字符串处理函数
请编制函数,对字符串的进行各种操作。
序 | 功能 | 用数组名作形参 | 用指针作形参 |
---|---|---|---|
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[]) | |
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) |
代码一:编制字符串连接函数
/**< 编制字符串连接函数 */
#include <stdio.h>
#include<string.h>
char *astrcat(char *str1, char *str2);
int main()
{
char s1[50],s2[25]; //不可直接赋值s1[50]="……",否则还要添加指针变量进行操作,因为此时s1[50]被当做常量了
strcpy(s1,"I am handsome!");
strcpy(s2,"She is so delicious!");
puts(s1);
puts(s2);
astrcat(s1,s2); //不可写成s1=astrcat(s1,s2),因为s1是字符数组不是指针变量,不能直接赋值,但可以写成下面这样
/**<
char *p1,*p2;
p1=s1;
p2=s2;
p1=astrcat(p1,p2);
*/
puts(s1);
return 0;
}
/** char *astrcat(char str1[], char str2[])
*字符串str1和str2连接,连接后的结果存放到str1中
* input:str1[],str2[]
*
* return:str1[]
*/
char *astrcat(char *str1, char *str2)
{
int i=0,j=0;
while(*(str1+i)!='\0')
i++;
while(*(str2+j)!='\0')
{
*(str1+i)=*(str2+j);
j++;
i++;
}
*(str1+i)='\0';
return str1;
}
执行一
代码二:字符串中删除指定字符的函数(参见NO.2)
代码三:求字符串str的长度并返回
/**< 编制求字符串str的长度函数 */
#include <stdio.h>
#include<string.h>
int pstrlen(char *str);
int main()
{
char s[]="The sun shines.";
puts(s);
printf("长度为 %d\n",pstrlen(s));
return 0;
}
/** int pstrlen(char *str)
*求字符串str的长度并返回
* input:char *str
* return:int n
*/
int pstrlen(char *str)
{
int n=0;
while(str[n]!='\0')
n++;
return n;
}
代码四:统计句子str中单词的个数
/**< 编制统计句子str中单词个数的函数 */
#include <stdio.h>
#include<string.h>
int pwordnum(char *str);
int main()
{
char s[]="The sun shines.";
int n;
n=pwordnum(s);
puts(s);
printf("\n单词数:%d",n);
return 0;
}
/** int pstrlen(char *str)
*统计句子str中单词的个数
* input:char *str
* return:int
*/
int pwordnum(char *str)
{
int n=0,i=0,word=0; //word作为是否遇到过空格的标志,遇到置0否则为1
while(str[i]!='\0')
{
if(str[i]==' ')
word=0;
else if(word==0)
{
n++;
word=1;
}
i++;
}
return n;
}
代码五:去除句子中第一个单词前的空格,返回去除了空格的字符串
#include <stdio.h>
#include<string.h>
char *ptrim(char *str);
int main()
{
char s[]=" The sun shines.";
puts(s);
puts(ptrim(s));
return 0;
}
/** char *ptrim(char *str)
*去除句子中第一个单词前的空格,返回去除了空格的字符串
* input:char *str
* return:char *str
*/
char *ptrim(char *str)
{
int i=0,j=0;
while(str[i]==' ')
i++;
while(str[i]!='\0')
{
str[j++]=str[i];
i++;
}
str[j]='\0';
return str;
}
代码六:去除句子中所有多余的空格,返回去除了空格的字符串
#include <stdio.h>
#include<string.h>
char *palltrim(char *str);
int main()
{
char s[]=" The sun shines.";
puts(s);
puts(palltrim(s));
return 0;
}
/** char *palltrim(char *str)
*去除句子中所有多余的空格,返回去除了空格的字符串
* input:char *str
* return:char *str
*/
char *palltrim(char *str)
{
int i=0,j=0;
while(str[i]!='\0')
{
if(str[i]!=' ')
str[j++]=str[i];
i++;
}
str[j]='\0';
return str;
}
代码七:比较两个字符串,返回值同strcmp()
#include <stdio.h>
#include<string.h>
int pstrcmp(const char *str1, const char *str2);
int main()
{
char s1[]="The sun shines",s2[]="The sun rises";
puts(s1);
puts(s2);
printf("\n比较结果:%d",pstrcmp(s1,s2));
return 0;
}
/** int pstrcmp(const char *str1, const char *str2)
*比较两个字符串,返回值同strcmp()
* input:const char *str1, const char *str2
* return:int
*/
int pstrcmp(const char *str1, const char *str2)
{
int i=0,flag=0; //默认两个字符串相等
while(str1[i]==str2[i]&&(str1[i]!='\0'&&str2[i]!='\0'))
i++;
if(str1[i]>str2[i])
flag=1;
else if(str1[i]<str2[i])
flag=-1;
//if(str1[i]=='\0'&&str2[i]=='\0')
// flag=0;
return flag;
}
NO.5 编程处理C++源代码
(1)读入一个C程序,判断其中是否只有一个main()函数,输出“暂时没有发现问题”,或者“没有main()函数”,或者“不能定义多个main()函数”;
提示1:简单处理,可以只比较判断“main()”,考虑实际上的各种可能,main后面的括号中还有其他多种写法。建议按最简单的情形处理。
提示2:建议设计一个函数,将读到的代码与字符串“main()”进行比较。函数用于判断s1是否“包含”在读入的一行s2中,调用时,形参s1处的实参用“main()”即可,这样写提升了“抽象”级别,更容易实现,对应更高的代码质量。
代码一
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int appear(const char *s1, const char *s2);
int main()
{
int i;
char str1[200],str2[]="main()";
FILE *fp;
fp=fopen("test.c","r"); //只读方式打开
if(fp==NULL)
{
printf("Can not open file!");
exit(1); //exit函数包含在stdlib.h中,exit(1)表示异常退出
}
//下面此读取为全部读取,计算量稍大于后一种
i=0;
while(!feof(fp))
{
fscanf(fp,"%c",&str1[i]);
i++;
}
str1[i]='\0'; //可不要,因为文件结束字符即为'\0'
/**< 循环读取还可用fgets函数
while(!feof(fp))
{
fgets(str1,200,fp); //读取一行,当读取 (n-1) 个字符,或者读取到换行符,或者到达文件末尾时,它会停止,具体视情况而定。
num+=appear(str1,str2);
if(num>1) //如果str2字符串出现超过1次,停止循环不必再读取
break;
}
*/
fclose(fp);
printf("文件test.c共 %d 个\"main()\"字符串\n",appear(str1,str2));
return 0;
}
//定义出现次数appear()函数
int appear(const char *s1, const char *s2)
{
int i=0,k=0,flag=0,count=0;
while(s1[i]!='\0')
{
if(s1[i]==s2[0]) //首字母m对上
{
for(k=1;k<6;k++) //看后面5个字符ain()
{
if(s1[i+k]!=s2[k]) //有一个对不上标志位置0,否则标志位置1
{
flag=0;
break;
}
else
flag=1;
}
if(flag==1) //跟s2全部对上了计数加一
count++;
}
if(count>1)
break;
i++;
}
return count;
}
小结1
巧用状态变量flag,与字符串不相等的时候少些计算,省得先循环求出一段字符串再来和已知字符串比较。
(2)编写一个程序并取名test.c,统计该文件中出现"if",“while”,"for"的次数。
代码二
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int appear(const char *s1, const char *s2);
int main()
{
int num[3]={0};
char str1[200],str2[]="if",str3[]="while",str4[]="for";
FILE *fp;
fp=fopen("test.c","r"); //只读方式打开
if(fp==NULL)
{
printf("Can not open file!");
exit(1); //exit函数包含在stdlib.h中,exit(1)表示异常退出
}
/**< 循环读取用fgets函数 */
while(!feof(fp))
{
fgets(str1,200,fp); //读取一行,当读取 (n-1) 个字符,或者读取到换行符,或者到达文件末尾时,它会停止,具体视情况而定。
num[0]+=appear(str1,str2); //num[0]存放“if”出现次数
num[1]+=appear(str1,str3); //num[1]————“while”次数
num[2]+=appear(str1,str4); //num[2]————“for”次数
}
fclose(fp);
printf("文件test.c共 %d 个\"if\"字符\n",num[0]);
printf("文件test.c共 %d 个\"while\"字符\n",num[1]);
printf("文件test.c共 %d 个\"for\"字符\n",num[2]);
return 0;
}
//定义出现次数appear()函数
int appear(const char *s1, const char *s2)
{
int i=0,k=0,flag=0,count=0;
while(s1[i]!='\0')
{
if(s1[i]==s2[0]) //首字母m对上
{
for(k=0;s2[k]!='\0';k++)
{
if(s1[i+k]!=s2[k]) //有一个字符对不上,标志位置0,否则标志位置1
{
flag=0;
break;
}
else
flag=1;
}
if(flag==1) //跟s2全部对上了计数加一
count++;
}
if(count>1)
break;
i++;
}
return count;
}
(3)读入一个C程序,使程序中的所有左花括号“{”和右花括号“}”都单独占一行,新程序保存到另一个.c文件中,并在屏幕上显示处理过的程序,显示时加上行号。
代码三
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void formatpgm(char* ,char* );
void showpgm(char*);
int main()
{
formatpgm("source.c","target.c");
printf("花括号占单行处理后的程序:\n");
showpgm("target.c");
return 0;
}
//花括号占单行处理函数
void formatpgm(char *sourcefile,char *targetfile)
{
char ch1,ch2;
FILE *fp1=fopen(sourcefile,"r");
if(fp1==NULL)
{
printf("Source file read error!\n");
exit(1);
}
FILE *fp2=fopen(targetfile,"w");
if(fp2==NULL)
{
printf("Target file write error!\n");
exit(1);
}
ch1='\0';
while(!feof(fp1))
{
ch2=fgetc(fp1);
if((ch2=='{'||ch2=='}')&&ch1!='\n') //当前读的是花括号且前一个字符不是换行,“···{”
fputc('\n',fp2);
else if((ch1=='{'||ch1=='}')&&ch2!='\n') //前一个读到花括号且当前读的不是换行,“{···”
fputc('\n',fp2);
fputc(ch2,fp2);
ch1=ch2;
}
fclose(fp2);
fclose(fp1);
}
void showpgm(char *s)
{
int i=1;
char str[256];
FILE *fp=fopen(s,"r");
if(fp==NULL)
{
printf("Source file read error!\n");
exit(1);
}
while(!feof(fp))
{
fgets(str,256,fp);
printf("%d\t%s",i,str);
i++;
}
}
小结3
格式处理函数中循环读取字符时,ch1类似于一个状态变量用法,有3种状态:换行符,花括号,其他字符。用来配合ch2
(4)读入一个C程序,输入m、n两个数字,从第m行起的n行代码将作为注释使用(即在这些行前面加上”//”),新程序保存到另一个.c文件中。
代码四
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void notepgm(char* ,char* ,int ,int);
int main()
{
int m,n;
printf("输入要注释的行:\n");
scanf("%d %d",&m,&n); //注释掉m到n行
notepgm("source.c","target.c",m,n);
return 0;
}
//注释掉m到n行的函数
void notepgm(char *sourcefile,char *targetfile, int m, int n)
{
int i=1;
char ch2[256];
FILE *fp1=fopen(sourcefile,"r");
if(fp1==NULL)
{
printf("Source file read error!\n");
exit(1);
}
FILE *fp2=fopen(targetfile,"w");
if(fp2==NULL)
{
printf("Target file write error!\n");
exit(1);
}
while(!feof(fp1))
{
fgets(ch2,256,fp1);
if(i>=m&&i<=n)
fputs("//",fp2);
fputs(ch2,fp2);
i++;
}
fclose(fp2);
fclose(fp1);
}
(5)(拓展)读入一个C++程序,整理其格式,使其按规范排版,包括:①所有左花括号“{”和右花括号“}”都单独占一行;②每个语句单独占一行;③各行采用统一的缩格排放(每遇一个“{”,其下一行的程序,在第一个有意义的符号前的空格数增加4,每遇一个“}”,其下一行的程序,在第一个有意义的符号前的空格数减少4。