我在用于简单的基于替换的加密的程序中使用以下方法。该方法专门用于去除加解密 key 中的重复字符。
该方法和程序的其余部分一样有效,它适用于我尝试过的 99% 的键。但是,当我向它传递键 "goodmorning"
或以任何顺序包含相同字母的任何键(例如 "dggimnnooor"
)时,它会失败。此外,包含比 "goodmorning"
更多字符的键,以及包含更少字符的键。
我使用相同的参数通过 lldb
运行了可执行文件,它运行正常。我已经在一台运行 CentOS 的机器上克隆了我的存储库,它可以正常工作。
但是我在编译时没有收到任何警告或错误。
//setting the key in main method
char * key;
key = removeDuplicates(argv[2]);
//return 1 if char in word
int targetFound(char * charArr, int num, char target){
int found = 0;
if(strchr(charArr,target))
found = 1;
return found;
}
//remove duplicate chars
char * removeDuplicates(char * word){
char * result;
int len = strlen(word);
result = malloc (len * sizeof(char));
if (result == NULL)
errorHandler(2);
char ch;
int i;
int j;
for( i = 0, j = 0; i < len; i++){
ch = word[i];
if(!targetFound(result, i, ch)){
result[j] = ch;
j++;
}
}
return result;
}
根据请求:如果将 "feather"
传递给此函数,则生成的字符串将为 "feather"
。
最佳答案
作为R Sahu已经说过,您没有使用 NUL
字符终止您的字符串。现在我不打算解释为什么你需要这样做,但是你总是需要用 NUL
字符来终止你的字符串,也就是 '\0'
。如果你想知道为什么,head over here一个很好的解释。然而,这不是您的代码的唯一问题。
主要问题是您调用的函数 strchr
是为了查明您的 result
是否已经包含一些字符 希望您传递一个 NUL
终止字符串,但您的变量未以NUL
终止,因为您不断向其附加字符。
为了解决您的问题,我建议您改用 map 。映射您已经使用的所有字符,如果它们不在 map 中,则将它们同时添加到 map 和结果中。这更简单(无需调用 strchr
或任何其他函数)、更快(无需每次都扫描所有字符串),最重要的是正确。
这是一个简单的解决方案:
char *removeDuplicates(char *word){
char *result, *map, ch;
int i, j;
map = calloc(256, 1);
if (map == NULL)
// Maybe you want some other number here?
errorHandler(2);
// Add one char for the NUL terminator:
result = malloc(strlen(word) + 1);
if (result == NULL)
errorHandler(2);
for(i = 0, j = 0; word[i] != '\0'; i++) {
ch = word[i];
// Check if you already saw this character:
if(map[(size_t)ch] == 0) {
// If not, add it to the map:
map[(size_t)ch] = 1;
// And to your result string:
result[j] = ch;
j++;
}
}
// Correctly NUL terminate the new string;
result[j] = '\0';
return result;
}
为什么这在其他机器上有效,但在您的机器上却无效?
您是未定义行为的受害者。不同系统上的不同编译器以不同方式处理未定义的行为。例如,GCC 可能决定在这种特殊情况下不做任何事情,并让 strchr
继续在内存中搜索,直到找到 '\0'
字符,这是到底发生了什么。您的程序一直在搜索 NUL
终止符并且永远不会停止,因为谁知道 '\0'
可能在您的字符串之后的内存位置?这既危险又不正确,因为程序没有读取为它保留的内存,例如,另一个编译器可能决定在那里停止搜索,并给你一个正确的结果。然而,这不是理所当然的事情,您应该始终避免未定义的行为。
关于c - 奇怪的行为删除 C 字符串中的重复字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48821528/