[英]C : removing duplicated letters from string
我正在尝试从字符串中删除每个单词中的重复字母。(我还没有为大写和小写字母指定它)
输入:
Ii feel good todday!!
thhis iss fixed
Output:
I fel god today!
this is fixed
我主要调用这个 function,我必须在另一个 function 中使用结果。 这就是为什么我通过引用来称呼它。
int main(){
char string[100];
printf("Enter a string:");
gets(string);
dup_letters_rule(&string);
return 0;
}
void dup_letters_rule(char *str_[]){
char new_str_[100];
int i=0, j=0;
printf("Fixed duplicates:\n");
while(*str_[i]!='\0'){
if(*str_[i]== *str_[i+1] && *str_[i+1]!='\0'){
while(*str_[i]==*str_[i+1] && *str_[i+1]!='\0'){
i++;
}
*str_[i]=new_str_[j];
j++;
i++;
}
else{
*str_[i]=new_str_[j];
j++;
i++;
}
}
new_str_[j]='\0';
puts(new_str_);
}
它的工作原理如下:
void dup_letters_rule(char *str_[]){
char *new_str_=*str_, *temp=*str_;
temp++;
printf("Fixed duplicates:\n");
while(*new_str_!='\0'){
if(*new_str_== *temp && *temp!='\0'){
while(*new_str_==*temp && *temp!='\0'){
new_str_++;
temp++;
}
putchar(*new_str_);
new_str_++;
temp++;
}
else{
putchar(*new_str_);
new_str_++;
temp++;
}
}
}
但是,我不能在另一个 function 中使用*str_
字符串。
代码可以简化。
我们可以保留一个int
值,它是之前看到的 char 并将其与当前char 进行比较,并且只有在它们不同时才“复制出来”。 (即我们只需要两个指针)。
我们还必须使用tolower
因为Ii
去I
。
尽管可以使用第二个/输出缓冲区,但 function 可以“就地”进行清理。 然后,调用者可以使用清理后的缓冲区。 这是我们通常想要做的。
如果调用者需要保留原始字符串,它可以将原始字符串保存到临时缓冲区并使用临时调用 function
我不得不重构你的代码。 我根据您的示例输入对其进行了测试。 注释如下:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void
dup_letters_rule(char *src)
{
char *dst = src;
int prev = -1;
// rchr -- the "raw" char
// lchr -- the result of tolower(rchr)
// prev -- the previous value of lchr (starts with -1 to force output of
// first char)
for (int rchr = *src++; rchr != 0; rchr = *src++) {
// get lowercase char
int lchr = tolower((unsigned char) rchr);
// output if _not_ a dup
if (lchr != prev)
*dst++ = rchr;
// remember this char for the next iteration
prev = lchr;
}
*dst = 0;
}
int
main(void)
{
char *cp;
char buf[1000];
while (1) {
cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// get rid of newline
buf[strcspn(buf,"\n")] = 0;
// eliminate dups
dup_letters_rule(buf);
// output the clean string
printf("%s\n",buf);
}
return 0;
}
更新:
我可以在 dup_letters_rule function 中打印干净的字符串吗? - 仓鼠
当然,当然。 我们是程序员,所以我们可以做任何我们想做的事情;-)
函数有一个格言:做好一件事
在许多实际(重新)用例中,我们不希望简单/低级 function 进行打印。 那是常态。
但是,我们当然可以为 function 添加打印功能。 我们将printf
从main
移动到 function 本身。
为了两全其美,我们可以使用两个函数。 一个只做转换的人。 并且,第二个调用简单的 function 然后打印结果。
这里有一个微小的变化可以说明这一点。 我重命名了我的 function 并创建了dup_letters_rule
并嵌入了printf
:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void
dup_letters_rule_basic(char *src)
{
char *dst = src;
int prev = -1;
// rchr -- the "raw" char
// lchr -- the result of tolower(rchr)
// prev -- the previous value of lchr (starts with -1 to force output of
// first char)
for (int rchr = *src++; rchr != 0; rchr = *src++) {
// get lowercase char
int lchr = tolower((unsigned char) rchr);
// output if _not_ a dup
if (lchr != prev)
*dst++ = rchr;
// remember this char for the next iteration
prev = lchr;
}
*dst = 0;
}
void
dup_letters_rule(char *buf)
{
dup_letters_rule_basic(buf);
// output the clean string
printf("%s\n",buf);
}
int
main(void)
{
char *cp;
char buf[1000];
while (1) {
cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// get rid of newline
buf[strcspn(buf,"\n")] = 0;
dup_letters_rule(buf);
}
return 0;
}
更新#2:
以及为什么不是
char *dst = *src;
但是char *dst = src;
- 仓鼠
这是基本的 C。 我们希望dst
具有与src
相同的值/内容。 就像我们做了:
int x = 23;
int y = x;
如果我们按照您的建议进行操作,编译器会标记该语句:
bad.c: In function ‘dup_letters_rule_basic’:
bad.c:8:14: warning: initialization of ‘char *’ from ‘char’ makes pointer from integer without a cast [-Wint-conversion]
char *dst = *src;
^
执行char *dst = *src
[正如您所建议的] 是以两种不同的方式使用*
。
执行char *dst
表示dst
被定义为指向char
的指针。
在这里做*src
[它是dst
的初始化器并且是一个表达式], *
是解引用操作符。 它说“获取src
指向的值(一个char
)”。 不是我们想要的。
如果我们不使用初始化器,这可能会更清楚。 我们使用定义(没有初始化器)并使用赋值语句设置dst
的初始值:
char *dst; // define a char pointer (has _no_ initial value)
dst = src; // assign the value of dst from the value of src
赋值 [语句] 可以出现在定义之后和for
循环/语句之前的任何位置。 这是 function 主体的前几行:
char *dst;
int prev = -1;
dst = src;
要从字符串中删除重复的连续字符,请跟踪字符串中的 position,其中下一个字符与其前一个字符不同,并检查当前处理字符与前一个字符(忽略它们的差异case) 除非该字符是字符串的第一个字符,因为第一个字符之前没有任何字符。 如果当前处理字符与前一个字符相同,则移动到字符串中的下一个字符,如果它们不相同,则用当前处理字符覆盖跟踪的 position 处的字符,并将跟踪的 position 指针增加 1。
它的实现:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void remove_consecutive_dup_chars (char * pstr) {
if (pstr == NULL) {
printf ("Invalid input..\n");
return;
}
/* Pointer to keep track of position where next character
* to be write in order to remove consecutive duplicate character.
*/
char * p = pstr;
for (unsigned int i = 0; pstr[i] ; ++i) {
if ((i) && (tolower (pstr[i]) == tolower (pstr[i - 1]))) {
continue;
}
*p++ = pstr[i];
}
/* Add the null terminating character.
*/
*p = '\0';
}
int main (void) {
char buf[256] = {'\0'};
strcpy (buf, "Ii feel good todday!!");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "thhis iss fixed");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "aaaaaa zzzzzz");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
return 0;
}
Output:
I fel god today!
this is fixed
a z
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.