HackerRank C语言查找奇数等简单题内存分配要求疑问
问题结论
这是HackerRank C语言类编程题的统一标准设定,不存在对题目要求理解偏差的问题。
设定背后的原因
- C语言函数内定义的普通局部变量存储在栈上,函数返回时对应的栈内存会被系统自动回收,如果直接返回这类局部字符数组的指针,主函数拿到的是指向已释放内存的野指针,读写会触发未定义行为,判题系统根本读不到正确结果。
- 平台所有返回字符串的C语言题目都复用同一套判题脚手架:主函数只会接收你返回的
char*类型指针,直接将指针指向的内容写入输出文件,不会额外做内存拷贝或者字符串持久化处理,因此必须要求返回的指针指向的内存在函数退出后依然合法有效。 - 你碰到的找奇数、简单判断类题目只要要求返回字符串结果,都会沿用这套规则,和题目本身的逻辑难度没有任何关系。
实现避坑提示
注意平台给出的动态分配示例代码本身存在错误,不要直接照搬:
示例里的动态分配写法
char* s = malloc(100 * sizeof(char)); s = "dynamic allocation of string";会直接把s指针指向只读常量区的字符串字面量,之前malloc申请的堆内存直接泄漏,属于典型错误写法。
两种合法实现的正确参考:
- 静态分配(本题最推荐,写法最简单):用static关键字修饰字符数组,static修饰的变量存储在全局数据区,生命周期覆盖程序整个运行周期,不会随函数返回销毁。比如本题只需要返回"YES"或者"NO",直接在函数里定义
static char yes[] = "YES"; static char no[] = "NO";,遍历数组找到k就返回yes,遍历完没找到就返回no即可,不需要额外处理内存释放。 - 动态分配:用malloc申请足够存放结果字符串的堆空间(比如存"YES"/"NO"只需要申请4字节,要预留字符串结束符
\0的位置),再用strcpy把目标字符串拷贝到申请的堆内存中再返回,不要直接把指针赋值为字符串字面量。
题目原始代码框架
#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* readline(); char* ltrim(char*); char* rtrim(char*); int parse_int(char*); /* * Complete the 'findNumber' function below. * * The function is expected to return a STRING. * The function accepts following parameters: * 1. INTEGER_ARRAY arr * 2. INTEGER k */ /* * To return the string from the function, you should either do static allocation or dynamic allocation * * For example, * char* return_string_using_static_allocation() { * static char s[] = "static allocation of string"; * * return s; * } * * char* return_string_using_dynamic_allocation() { * char* s = malloc(100 * sizeof(char)); * * s = "dynamic allocation of string"; * * return s; * } * */ char* findNumber(int arr_count, int* arr, int k) { } int main() { FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w"); int arr_count = parse_int(ltrim(rtrim(readline()))); int* arr = malloc(arr_count * sizeof(int)); for (int i = 0; i < arr_count; i++) { int arr_item = parse_int(ltrim(rtrim(readline()))); *(arr + i) = arr_item; } int k = parse_int(ltrim(rtrim(readline()))); char* result = findNumber(arr_count, arr, k); fprintf(fptr, "%s\n", 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 = '\0'; break; } } if (data[data_length - 1] == '\n') { data[data_length - 1] = '\0'; data = realloc(data, data_length); if (!data) { data = '\0'; } } else { data = realloc(data, data_length + 1); if (!data) { data = '\0'; } else { data[data_length] = '\0'; } } return data; } char* ltrim(char* str) { if (!str) { return '\0'; } if (!*str) { return str; } while (*str != '\0' && isspace(*str)) { str++; } return str; } char* rtrim(char* str) { if (!str) { return '\0'; } if (!*str) { return str; } char* end = str + strlen(str) - 1; while (end >= str && isspace(*end)) { end--; } *(end + 1) = '\0'; return str; } int parse_int(char* str) { char* endptr; int value = strtol(str, &endptr, 10); if (endptr == str || *endptr != '\0') { exit(EXIT_FAILURE); } return value; }
内容的提问来源于stack exchange,提问作者Reactoo
相关产品推荐
相关产品推荐

