C语言 为什么我的超精简字符串(HackerRank)问题的解决方案在我的计算机上工作正常,但在HackerRank中给



当我在Hackerrank中运行我的代码时,它失败了6/16测试用例,但是当我在计算机上尝试相同的测试用例时,它工作正常。

这是我在计算机上运行的代码:(我使用Clion作为IDE,最新的MinGW作为编译器。

我使用在 HackerRank 上失败的测试用例之一初始化字符串。

#include <string.h>
#include <stdio.h>
//#include <stdlib.h>
char* superReducedString(char* s);
int contain(char *S,char find);
void copyWithout(char *S,char *T,char trash);
int countWithout(char *S,char trash);
int findSize(char *S);
void fillString(char *S,char filler);
int main(){
char s[] = {"ppffccmmssnnhhbbmmggxxaaooeeqqeennffzzaaeeyyaaggggeessvvssggbbccnnrrjjxxuuzzbbjjrruuaaccaaoommkkkkxx"};
char *result = superReducedString(s);
printf("%s",result);
}
int findSize(char *S){
int i = 0;
while(*(S+i) != ''){
i++;
}
return i;
}
void fillString(char *S,char filler){
int i = 0;
while(*(S+i) != ''){
*(S+i) = filler;
i++;
}
}
void copyWithout(char *S,char *T,char trash){
fillString(T,'0');
int i = 0;
int count = 0;
while(*(S+i) != ''){
if(*(S+i) != trash){
*(T+count) = *(S+i);
count++;
}
i++;
}
}
int countWithout(char *S,char trash){
int i = 0;
int count = 0;
while(*(S+i) != ''){
if(*(S+i) != trash){
count++;
}
i++;
}
return count;
}
int contain(char *S,char find){
int i = 0;
int flag = 0;
while(*(S+i) != ''){
if(*(S+i) == find){
flag = 1;
}
i++;
}
return flag;
}
char* superReducedString(char* s){
static char empty[] = "Empty String";
static char result[1024];
int flag = 1;
char temp[findSize(s)];
fillString(temp,'0');
int i,j;//Loop variable.
i = 0;
while(*(s + i) != ''){
j = 0;
//Checking if adjacent numbers is same. If it is changing them to '0'.
while(s[j] != '') {
if (s[j] == s[j + 1]) {
*(s + j) = '0';
*(s + j + 1) = '0';
}
j++;
}
if(contain(s,'0') == 0){ //If there is no zero in original string that means nothing changed.
return s;
}else{
copyWithout(s,temp,'0');//If there are zeros in it, copy it to a temp char array without zeros.
}
strcpy(s,temp);//Copy temp to s again for swapping.
i++;
}
int count = countWithout(s,'0'); //Calculate the size of original string without zeros.
char finalString[count];//Initialize a new string with the calculated size.
copyWithout(s,finalString,'0'); //Copy original string to finalString without zeros to obtain a clear zeroless string.
strcpy(result,finalString);//copy finalstring to static result string to return it.
i = 0;
while(*(result+i) != ''){ //Check if result string consists of zeroes. If it is code will return empty string.
if(*(result+i) != '0'){
flag = 0;
}
i++;
}
if(flag == 0){
return result;
}else{
return empty;
}
}

这是我在HackerRank上运行的代码:

#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* superReducedString(char* s);
int contain(char *S,char find);
void copyWithout(char *S,char *T,char trash);
int countWithout(char *S,char trash);
int findSize(char *S);
void fillString(char *S,char filler);
char* readline();
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* s = readline();
char* result = superReducedString(s);
fprintf(fptr, "%sn", result);
fclose(fptr);
return 0;
}
char* readline() {
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true) {
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line) {
break;
}
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == 'n') {
break;
}
alloc_length <<= 1;
data = realloc(data, alloc_length);
if (!data) {
data = '';
break;
}
}
if (data[data_length - 1] == 'n') {
data[data_length - 1] = '';
data = realloc(data, data_length);
if (!data) {
data = '';
}
} else {
data = realloc(data, data_length + 1);
if (!data) {
data = '';
} else {
data[data_length] = '';
}
}
return data;
}
int findSize(char *S){
int i = 0;
while(*(S+i) != ''){
i++;
}
return i;
}
void fillString(char *S,char filler){
int i = 0;
while(*(S+i) != ''){
*(S+i) = filler;
i++;
}
}
void copyWithout(char *S,char *T,char trash){
fillString(T,'0');
int i = 0;
int count = 0;
while(*(S+i) != ''){
if(*(S+i) != trash){
*(T+count) = *(S+i);
count++;
}
i++;
}
}
int countWithout(char *S,char trash){
int i = 0;
int count = 0;
while(*(S+i) != ''){
if(*(S+i) != trash){
count++;
}
i++;
}
return count;
}
int contain(char *S,char find){
int i = 0;
int flag = 0;
while(*(S+i) != ''){
if(*(S+i) == find){
flag = 1;
}
i++;
}
return flag;
}
char* superReducedString(char* s){
static char empty[] = "Empty String";
static char result[1024];
int flag = 1;
char temp[findSize(s)];
fillString(temp,'0');
int i,j,k;//Loop variable.
i = 0;
while(*(s + i) != ''){
j = 0;
while(s[j] != '') {
if (s[j] == s[j + 1]) {
*(s + j) = '0';
*(s + j + 1) = '0';
}
j++;
}
if(contain(s,'0') == 0){
return s;
}else{
//    printf("temp0 = %s s0 = %sn",temp,s);
copyWithout(s,temp,'0');
//    printf("temp1 = %s s1 = %sn",temp,s);
}
//printf("%sn",temp);
strcpy(s,temp);
i++;
}
int count = countWithout(s,'0');
char finalString[count];
copyWithout(s,finalString,'0');
strcpy(result,finalString);
i = 0;
while(*(result+i) != ''){
if(*(result+i) != '0'){
flag = 0;
}
i++;
}
if(flag == 0){
return result;
}else{
return empty;
}
}

唯一的区别是main函数和HackerRank用于获取输入的函数。

我不知道这是否有帮助,但有时我的代码可能会为相同的输入给出错误的答案。 我的意思是:

input = "acdqglrfkqyuqfjkxyqvnrtysfrzrmzlygfveulqfpdbhlqdqrrqdqlhbdpfqluevgylzmrzrfsytrnvqyxkjfquyqkfrlacdqj">

虽然它应该给出"acdqgacdqj"作为答案,但它给出"acdqgacdqjÑ" 最后一个字符随机更改。

但是对于其他输入,无论我运行多少次,它都会在我的计算机上给出正确的答案。

char temp[findSize(s)]; fillString(temp,'0');无效
  • 。在fillString中,您迭代直到元素等于''temp是未初始化的 - 你不能指望它有任何特定的值(甚至读取未初始化的值也是未定义的行为(。
  • char finalString[count];count太小 - 它不考虑零终止字符。copyWithout(s,finalString,'0');不是复制零终止字符。这会导致strcpy(result,finalString);在搜索时越界访问数组。零终止字符。

使用 C 字符串时,您通常会在代码中的任何地方看到一个神奇的+ 1

建议:

  • 不喜欢使用可变长度数组(大小表达式不是常量表达式的数组(。首选使用动态分配。
  • findSize只是strlen...
  • fillString只是memset(string, value, strlen(string));
  • 使用编译器时,请始终启用所有选项。使用gcc时,您可以使用gcc -g -Wall -Wextra -fsanitize=address sourcefile.c- cleanitize 将允许真正快速地找到堆栈变量上的所有越界访问。使用valgrind查找动态分配泄漏。
  • 我建议将copyWithout中的参数顺序更改为(destination, source, fill),以便与strcpy(destination, source)相同 - 即目的地是第一位的。

似乎将部分代码修复为:

char* superReducedString(char* s){
...
// char temp[findSize(s)];
char temp[findSize(s) + 1];
// fillString(temp,'0');
memset(temp, '0', findSize(s));
temp[findSize(s)] = '';
...
char finalString[count + 1];//Initialize a new string with the calculated size.
memset(finalString, '0', count);
finalString[count] = '';
}

足以让我-fsanitize停止错误。

我不知道你的错误到底在哪里,但从输出中可以清楚地看出你正在使用未初始化的内存。在您的计算机上,未初始化的内存纯属巧合地包含一个零,而在用于测试的计算机上则不包含。

一般来说,如果你有一个问题"它在计算机A上工作,但在计算机B上不起作用",那么代码中未定义的行为通常是答案,在这里它最像未初始化的内存。

最新更新