一个综合性的C语言字符串编程题目,题目各项要求都使用到了比较经常遇到的各种字符串相关操作,比如:字符串分割、字符串拼接、字符串赋值、字符串转整数等
题目介绍:
有字符串s,满足如下要求:
- 字符串s仅允许小写字母、大写字母、数字[0-9]、加号、减号共26+26+10+2=64种符号;
- 加号、减号后继字符只允许数字;
- 从字符串s中取任意连续的字符组成的整数子串,称为s的子整数,如:0, 5, 8, 003, 202, +5, +8, +003, +202, -5, -8, -003, -202;
- 对字符串s,顺次不漏提取一组子整数,构成一个s的一个子整数组合;一个字符串s可以对应多个子整数组合;
编写程序,满足下列功能要求:
- 字符串输入:从键盘输入一个任意长度的字符串;
- 判断合法性:如果字符串不符合上述要求,接受字符串并提示,否则拒绝并提示;
- 字符统计:按照ASCII字符顺序统计字符串字符频次,并显示,未出现的字符不统计;
- 列举字符串的所有的子整数组合,并显示:
- 求解和最小的子整数组合,并显示;
- 按和的升序列举所有的子整数组合,并显示。
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int flag;
int add = 0;
void Init(char s[]) //检查输入
{
int i = 1;
for(i = 0; i < strlen(s); i ++)
{
if((s[i] >= 'a' && s[i] <= 'z') || (s[i] == '-') || (s[i] == '+') || (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'A' && s[i] <= 'Z'))
{
if((s[i] == '-') || (s[i] == '+'))
{
if(s[i+1] < '0' || s[i+1] > '9')
{
flag = 0;
return ;
}
}
}
else
{
flag = 0;
return ;
}
}
return ;
}
void Count(char s[]) //统计各字母出现频率
{
int sum[64] = {0}; //按照ASCII码顺序存储64个字符出现频率
int i;
for(i = 0; i < strlen(s); i ++)
{
if((s[i] == '-') || (s[i] == '+'))
{
if(s[i] == '+')
{
sum[0] ++;
add ++;
}
else if(s[i] == '-')
{
sum[1] ++;
add ++;
}
}
else if((s[i] >= '0' && s[i] <= '9'))
{
int temp = s[i] - 47;
sum[1 + temp] ++;
}
else if((s[i] >= 'A' && s[i] <= 'Z'))
{
int temp = s[i] - 64;
sum[11 + temp] ++;
}
else if((s[i] >= 'a' && s[i] <= 'z'))
{
int temp = s[i] - 96;
sum[37 + temp] ++;
}
else
{
printf("Error!\n");
return ;
}
}
printf("The word frequency is as follows:\n");
for(i = 0;i < 64; i++)
{
if(sum[i] != 0)
{
if(i == 0)
{
printf(" + : %d\n",sum[i]);
}
else if(i == 1)
{
printf(" - : %d\n",sum[i]);
}
else if(i >= 2 && i <= 11)
{
printf(" %d ",i-2);
printf(": %d\n",sum[i]);
}
else if(i >= 12 && i <= 37)
{
char temp;
temp = (char)(i+53);
printf(" %c : %d\n",temp,sum[i]);
}
else if(i >= 38 && i <= 63)
{
char temp;
temp = (char)(i+59);
printf(" %c : %d\n",temp,sum[i]);
}
}
}
printf("\n");
return ;
}
void Display(char *str[],int number[],int m) //输出所有子整数组合,输出和最大的子整数组合,子整数组合排序并输出
{
int min = number[0];
char temp_str[999]; //这里必须设置成char[]类型,char*不行,否则下面strcpy和strcat函数没法用,主要要设置大小,我这里给的999,根据自己需求给
char min_str[999]; //同上,这部分也卡了我挺久的
int temp;
char str_sort[999][999]={0};
int sum_add[999]={0};
int sum_sort[999]={0};
int n = 0;
strcpy(min_str,str[0]);
printf("All combinations are as follows:\n");
int i;
int j;
for(i = 0; i < m;i++)
{
temp = number[i];
strcpy(temp_str,str[i]);
strcpy(str_sort[n],temp_str);
sum_add[n] = temp;
sum_sort[n] = temp;
n++;
printf("%s\n",temp_str);
if(temp < min)
{
min = temp;
strcpy(min_str,temp_str);
}
for(j = i + 1; j < m;j++)
{
temp = temp + number[j];
strcat(temp_str,str[j]);
strcpy(str_sort[n],temp_str);
sum_add[n] = temp;
sum_sort[n] = temp;
n++;
printf("%s\n",temp_str);
if(temp < min)
{
min = temp;
strcpy(min_str,temp_str);
}
}
}
printf("\n");
printf("String of minimum sum: ");
printf("%s\n",min_str);
printf("\n");
int t;
int f[n];
for (j = 0; j < n -1; j++) //根据子整数组合求和大小进行顺序排序
{
for (i = 0; i < n-j-1; i++)
if (sum_sort[i] > sum_sort[i + 1])//比较
{
t = sum_sort[i];
sum_sort[i] = sum_sort[i + 1];
sum_sort[i + 1] = t;//换位
}
}
printf("Sorted results:\n");
for(i = 0;i < n;i++)
{
for(j = 0;j < n;j++)
{
if(sum_add[j] == sum_sort[i] && f[j] != 1)
{
printf("%s\n",str_sort[j]);
f[j] = 1;
}
}
}
return ;
}
void Extract(char s[]) //拆分输入的字符串,剔除其中的字母字符
{
char new_s[strlen(s) + add + 1]; //这块卡了我好久,一开始因为大小未知,就没设置大小,编译器也没报错,但是下面代码运行到下面的语句,寄存器就会错乱
int number[9999] = {0};
char *new_str[9999] = {'\0'};
int m = 0;
int j = 0;
int i = 0;
memset(new_s, 0 ,sizeof(new_s));
while(i < strlen(s)) //就是这个循环,没设置字符数组大小,变量i给我乱跳,debug了好久都弄不清楚为啥乱跳,最后终于弄明白了,就是上面提到的原因
{
if((s[i] < '0' || s[i] > '9') && (s[i] != '-') && (s[i] != '+'))
{
new_s[j++] = ',';
i++;
}
else if(s[i] == '-' || s[i] == '+')
{
new_s[j++] = ',';
new_s[j++] = s[i++];
}
else
{
new_s[j++] = s[i++];
}
}
char *token;
char *tt;
const char c[2] = ",";
int value;
token = strtok( new_s , c);
while(token != NULL)
{
value = strtol(token,&tt,10);
if( tt != token)
{
number[m] = value;
new_str[m] = token;
m++;
}
// if(atoi(token) != 0)
// {
// number[m] = atoi(token);
// new_str[m] = token;
// m++;
// }
token = strtok(NULL,c);
}
Display(new_str,number,m);
return ;
}
int main()
{
char s[9999] = {0};
flag = 1;
gets(s);
Init(s);
if(flag == 1)
{
printf("input success!\n");
printf("\n");
Count(s);
Extract(s);
}
else if(flag == 0)
{
printf("Input Error!\n");
}
else
{
printf("Error!\n");
}
system("pause");
return 0;
}
总结
在编写过程中由于好久不写C语言,同时不允许调包,走了一些弯路,好在最后算是实现了题目要求。感觉是有一些收获的,对C语言字符串相关操作有了进一步认识。
同时总结了一些C语言字符串相关函数,在我发的另一篇文章,链接附在后面,有兴趣的小伙伴可以看一眼。