我需要從字串中洗掉每個重復的子字串,但要區分大小寫。當洗掉一個子字串時,該程序從字串的開頭重新開始。
例子:
char text[1000]="abcdef cde AbCDE";what[1000]="abc";cs;
OUTPUT for cs=1: "def cde AbCDE"
OUTPUT for cs=0: "def cde DE"
cs (區分大小寫) 1 表示關心大小寫,而 cs 0 表示不關心。
#include <ctype.h>
#include <stdio.h>
#include <string.h>
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r len, sub)) != NULL) {
while (p < r)
*q = *p ;
}
while ((*q = *p ) != '\0')
continue;
}
return str;
}
char* remove_all_substrings(char* str, const char* text, int cs) {
int i,e=0;
if(cs==0){
for(i=0;i<strlen(str);i )
str[i]=tolower(str[i]);
}
while(1){
e ;
strremove(str, text);
if(strstr(str,text)==NULL||e==100)break;
}
return str;
}
int main() {
char text[1000] = "abcdef cde AbCDE";;
char what[1000] = "abc";
int cs = 1;
printf("\"%s\"", remove_all_substrings(text, what, cs));
return 0;
}
我得到了 cs=0 的錯誤輸出,因為在我的方法中,我將所有字符從字串轉換為小寫,然后洗掉它們。你能幫我修改我的代碼并給我一些更好的方法來解決這個任務嗎?
- 注意:不允許使用輔助字串。
uj5u.com熱心網友回復:
您已經知道為什么當csvalue 為時會得到錯誤的輸出0。
請注意,函式strcasecmp()和strncasecmp()符合 4.4BSD、POSIX.1-2001,而strcasestr()是非標準擴展。這些函式不是 C 標準的一部分。使用這些可能會導致代碼不可移植。
您已tolower()在代碼中使用,但您正在修改原始字串。tolower()無需修改原始字串,只需在進行不區分大小寫的比較時比較回傳值即可。
你可以做:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* remove_all_substrings (char * str, const char * str_toremove, int cs) {
if (str && str_toremove) {
size_t len = strlen (str_toremove);
int res = -1;
char * ptr = str;
size_t i = 0;
while (str[i] && len) {
if (cs) {
if (str[i] == str_toremove[0]) {
res = 0;
size_t tmp_len = len;
while (--tmp_len) {
if (str[i len - tmp_len] != str_toremove[len - tmp_len]) {
res = -1;
break;
}
}
}
} else {
if (tolower (str[i]) == tolower (str_toremove[0])) {
res = 0;
size_t tmp_len = len;
while (--tmp_len) {
if (tolower (str[i len - tmp_len]) != tolower (str_toremove[len - tmp_len])) {
res = -1;
break;
}
}
}
}
if (res == 0) {
i = i len;
res = -1;
} else {
*ptr = str[i ];
}
}
if (len) {
*ptr = '\0';
}
}
return str;
}
void helper_func (char * str, const char * str_toremove, int cs) {
printf("str : \"%s\", str_toremove : \"%s\", case sensitive : %d\n",
str ? str : "(NULL)", str_toremove ? str_toremove : "(NULL)", cs);
char * res = remove_all_substrings(str, str_toremove, cs);
printf("res : \"%s\"\n\n", res ? res : "(NULL)");
}
int main (int argc, char * argv[]) {
if (argc != 2) {
printf ("Invalid argument\n");
return 0;
}
int cs = atoi (argv[1]);
if ((cs != 0) && (cs != 1)) {
printf ("Invalid commmand line argument value\n");
return 0;
}
const char what[] = "abc";
char text1[] = "abcdef cde AbCDE";;
helper_func (text1, what, cs);
char text2[] = "DuMMyabcd AbCDE";;
helper_func (text2, what, cs);
char text3[] = "idecbt HYTRg HGB jC";
helper_func (text3, what, cs);
char text4[] = "";
helper_func (text4, what, cs);
// test : pass NULL to input string pointer
helper_func (NULL, what, cs);
char text5[] = "abcDEFGHIABC";
// test : pass NULL to toremove string pointer
helper_func (text5, NULL, cs);
helper_func (text5, "", cs);
char text6[] = "abcABC";
helper_func (text6, what, cs);
char text7[] = "xxXXxx";
helper_func (text7, "x", cs);
char text8[] = "aBAcaDAe";
helper_func (text8, "a", cs);
return 0;
}
用法:./a.out <case_sensitive>
其中的case_sensitive值為0或1。0表示不區分大小寫的洗掉,1表示區分大小寫的洗掉。
輸出 - 不區分大小寫的洗掉:
# ./a.out 0
str : "abcdef cde AbCDE", str_toremove : "abc", case sensitive : 0
res : "def cde DE"
str : "DuMMyabcd AbCDE", str_toremove : "abc", case sensitive : 0
res : "DuMMyd DE"
str : "idecbt HYTRg HGB jC", str_toremove : "abc", case sensitive : 0
res : "idecbt HYTRg HGB jC"
str : "", str_toremove : "abc", case sensitive : 0
res : ""
str : "(NULL)", str_toremove : "abc", case sensitive : 0
res : "(NULL)"
str : "abcDEFGHIABC", str_toremove : "(NULL)", case sensitive : 0
res : "abcDEFGHIABC"
str : "abcDEFGHIABC", str_toremove : "", case sensitive : 0
res : "abcDEFGHIABC"
str : "abcABC", str_toremove : "abc", case sensitive : 0
res : ""
str : "xxXXxx", str_toremove : "x", case sensitive : 0
res : ""
str : "aBAcaDAe", str_toremove : "a", case sensitive : 0
res : "BcDe"
輸出 - 區分大小寫的洗掉:
# ./a.out 1
str : "abcdef cde AbCDE", str_toremove : "abc", case sensitive : 1
res : "def cde AbCDE"
str : "DuMMyabcd AbCDE", str_toremove : "abc", case sensitive : 1
res : "DuMMyd AbCDE"
str : "idecbt HYTRg HGB jC", str_toremove : "abc", case sensitive : 1
res : "idecbt HYTRg HGB jC"
str : "", str_toremove : "abc", case sensitive : 1
res : ""
str : "(NULL)", str_toremove : "abc", case sensitive : 1
res : "(NULL)"
str : "abcDEFGHIABC", str_toremove : "(NULL)", case sensitive : 1
res : "abcDEFGHIABC"
str : "abcDEFGHIABC", str_toremove : "", case sensitive : 1
res : "abcDEFGHIABC"
str : "abcABC", str_toremove : "abc", case sensitive : 1
res : "ABC"
str : "xxXXxx", str_toremove : "x", case sensitive : 1
res : "XX"
str : "aBAcaDAe", str_toremove : "a", case sensitive : 1
res : "BAcDAe"
uj5u.com熱心網友回復:
您寫strremove的內容是區分大小寫的(盡管“區分大小寫”可能是一個更好的術語)。
如果要以不區分大小寫的方式洗掉子字串的實體,則無法通過修改子字串并將其傳遞給區分大小寫的函式來實作(除非您愿意遍歷子字串的所有可能的大小寫排列) . 您可以制作 的副本str,將其轉換為小寫,找到 的實體sub,然后使用這些位置洗掉原始 中的子字串str,但我認為這可能會違反針對輔助字串的規則。
您必須撰寫不區分大小寫的strremove. 這并不難;只需使用strcasestr而不是strstr.
但在你這樣做之前,你可能會改變strremove回傳的內容。就目前而言,strremove接受指向字串的指標,修改字串,然后回傳它從未修改過的指標。回傳的值是多余的,實際上呼叫代碼甚至沒有保留它,所以函式也可以回傳void。我建議它回傳一個bool指示它是否找到(并洗掉)子字串的實體;這樣你就可以不用笨拙的搜索了remove_all_substrings。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/426978.html
