题目描述
串的处理
在实际的开发工作中,对字符串的处理是最常见的编程任务。本题目即是要求程序对用户输入的串进行处理。具体规则如下:
1. 把每个单词的首字母变为大写。
2. 把数字与字母之间用下划线字符(_)分开,使得更清晰
3. 把单词中间有多个空格的调整为1个空格。
输入
例如:
用户输入:
you and me what cpp2005program
输出
则程序输出:
You And Me What Cpp_2005_program
输入 this is a 99cat 输出 This Is A 99_cat#include <stdio.h> #include <string.h> // 自定义字符判断函数 int is_letter(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } int is_digit(char c) { return c >= '0' && c <= '9'; } char to_upper(char c) { if (c >= 'a' && c <= 'z') { return c - ('a' - 'A'); // 将小写字母转换为大写,小写字母的ASCII码比对应的大写字母大32. } return c; // 如果不是小写字母,返回原字符 } int is_lower(char c) { return c >= 'a' && c <= 'z'; } int main() { char input[1001]; char output[2001]; // 输出字符串可能更长(因为可能添加下划线) int i, j = 0; //下面代码在之前的题中解释过了,移除末尾换行符的代码永远不变 // 读取一行输入 fgets(input, 1000, stdin); // 移除末尾的换行符 int len = strlen(input); if (len > 0 && input[len-1] == '\n') { input[len-1] = '\0'; len--; } int in_word = 0; // 标记是否在单词中 int prev_is_space = 1; // 标记前一个字符是否为空格,初始为1表示单词开始 char prev_char = 0; // 记录前一个字符 for (i = 0; i < len; i++) { char c = input[i];//一直到该步骤,所有字符都是通式,没有变 // 处理多个连续空格:只保留一个空格 if (c == ' ') { // 如果前一个字符不是空格,则添加一个空格 if (!prev_is_space) { output[j++] = ' '; prev_is_space = 1; } // 标记不在单词中 in_word = 0;//如果是空格,则不在单词中。 prev_char = ' ';//将该字符即下一个字符的前一个字符标记为' ' continue; } // 不在单词中的第一个非空格字符是单词首字母 if (!in_word) { // 如果是字母,转换为大写 if (is_letter(c)) { output[j++] = to_upper(c); } else { output[j++] = c; } in_word = 1; prev_is_space = 0;前一个字符不是空格 } // 在单词中的处理 else { // 处理数字和字母之间加下划线 if (prev_char != 0) { // 如果前一个字符是数字,当前字符是字母,则添加下划线 if (is_digit(prev_char) && is_letter(c)) { output[j++] = '_'; } // 如果前一个字符是字母,当前字符是数字,则添加下划线 else if (is_letter(prev_char) && is_digit(c)) { output[j++] = '_'; } } // 添加当前字符到输出 output[j++] = c; prev_is_space = 0; } prev_char = c; } // 如果最后一个字符是空格,移除它 if (j > 0 && output[j-1] == ' ') { j--; } output[j] = '\0'; // 添加字符串结束符 // 输出结果 printf("%s\n", output); return 0; }一.根据样例输入来解析上述代码:
该处理思路主要是,从原数组中提取元素,按照题目条件赋值到另一个数组中,最后只需要输出该数组output【】
主函数:
1.将完整单词的第一个改为大写,然后剩余单词字母全部赋值到output数组中
首先初始化表示单词首字母的标志变量in_word = 0;如果一开始(肯定是首字母)有字符是小写的不是大写的,此时就要调用字符判断函数,将小写字母转换成大写字母。之后就要将in_word转换成1,因为后面的就不是首字母了。但是在找到下一个首字母的时候,要将其再转换成0.同时,要将该字符即下一个字符的前一个字符prev_is_space=0.(是字符,不是空格)
因为一开始的字符肯定是该行字符的首字母,所以就要将其赋值给输出数组的第一个output[j],一开始定义j=0.之后不满足首字母的条件了,就要执行下面的else语句了。将后面的不需要变化的单词直接赋值给输出数组,j++;这些都是字符不是空格,所以prev_is_space = 0;一直到该完整单词结束,开始出现空格,如果空格很多,则想办法减少空格到一个。
2.将多个空格减少到只有一个空格。思路是:将检测到的一个空格赋给输出数组,然后开始将字母再赋给输出数组
只有整个单词结束后的第一个空格才是我们要找的空格,是赋给输出数组的空格,所以前一个必须是字符,不可能是空格,刚好有个标志变量prev_is_space 用来判断是否是空格,所以就用它来作为if条件语句的判断,并将这第一个空格赋给输出数组。同时不要忘了将标志变量prev_is_space转换成1.因为prev_is_space该变量有作用,所以在每一次赋值后面都要加上。
同时不要忘记标记空格不在完整的单词中,这样才能明白下一次就是完整单词的首字母了in_word,然后就可以进行和上述一样的操作了,即给首字母大写,然后再重复进行即可.
3.之后就是在数字和字母之间加下划线。这时就要用到prev_char这个标志变量了,因为要确定前一个字符是数字,当前字符是字母,才可以加下划线。具体在上述代码中。
因为prev_char肯定不是0,所以也可以不用加上述if语句。
为什么要设置前一个字符为标志变量,而不是当前字符和后一个字符呢?
因为当前字符已将明确了,是if语句中的条件判断;同时,读取下一个字符的时候,当前字符为下一个字符的前一个字符,非常明确。而后一个字符还不知道,所以不能设后一个字符为标志变量。
因为根据题目要求,前一个字符和后一个字符有着密切的关系,根据这些关系来进行转换,运行,达到要求。这时就要设置前一个字符的标志变量。
二.我写代码的思路:
没有想到标志变量,(该题中,标志变量是关键)所以写的很麻烦,很混乱。很多一样的循环,并列用了很多次,这肯定不对。而且我写的代码不适用于任何情况,只适用于样例输入。因为没有标志变量,所以每次循环只能针对特定情况才能用。
因为我的思路是没有输出数组,还是原来数组,但是通过计算空格数将完整的单词通过赋值移到前面来,只保留一个空格。下一次再计算新的空格数,再将下一组单词移到前面来,所以一次循环只能处理一组单词,不能处理所有情况,而且非常麻烦。而且还有点小错误……🤭
#include<stdio.h> int main() { char input[81]; gets(81); int i; int count1=1; for(i=0;input[i]!='\0';i++){ if(input[i]==' '&&input[i+1]==' '){ count1++; } if(input[i]!=' '&&input[i+1]==' '){ break; } } for(i=0;input[i]!='\0';i++) if(i=0){ input[i]=input[i]+32; }else{ if((input[i]==' ')&&(input[i+1]>='a'&&input[i+1]<='z')){ input[i+1]=input[i+1]+32; } } } int j; for(i=0;input[i]!='\0';i++){ if(input[i]==' '&&input[i+1]==' '){ m=i; break; } } for(i=m;input[i+count1]!=' ';i++){ for(j=m;input[i]==input[j]&&input[i]!=' ';j++){ input[i-count1]=input[i]; input[i]=' '; //应该让该程序结束了,因为已经把一个完整的单词全移过去了 if(input[i+count1]==' '){ break; } } } int count2=1; for(i=m;input[i]!='\0';i++){ if(input[i]==' '&&input[i+1]==' '){ count2++; } if(input[i]!=' '&&input[i+1]==' '){ break; } } int n; for(i=m;input[i]!='\0';i++){ if(input[i]==' '&&input[i+1]==' '){ n=i; break; } } for(i=n;input[i+count2]!=' ';i++){ for(j=n;input[i]==input[j]&&input[i]!=' ';j++){ input[i-count2]=input[i]; input[i]=' '; if(input[i+count2]==' '){ break; } } } printf("%s",input); return 0; }