C
1: — CRust
2: — Rust
3: —
4: — CRust
5: — unsafe
1: strlen
C
size_t strlen(const char* s) {
const char* p = s;
while (*p != '\0') p++;
return (size_t)(p - s);
}sNULL → →
Rust
fn strlen(s: &str) -> usize {
s.bytes().take_while(|&b| b != b'\0').count()
}| C strlen | Rust strlen | |
|---|---|---|
| const char* (NULL) | &str () | |
| \0 | ||
LuoguP1035 —
2: strdup
C
char* strdup(const char* s) {
if (s == NULL) return NULL;
size_t len = strlen(s);
char* dup = (char*)malloc(len + 1);
if (dup == NULL) return NULL;
memcpy(dup, s, len + 1);
return dup;
}free → free → UAFfree → double-free
Rust
fn strdup(s: &str) -> String { s.to_string() }C5Rust
3: create_array
C
int* create_array(int n) {
if (n <= 0) return NULL;
int* arr = (int*)malloc((size_t)n * sizeof(int));
if (arr == NULL) return NULL;
for (int i = 0; i < n; i++) arr[i] = 0;
return arr;
}nn*sizeof(int)mallocNULL
Rust
fn create_array(n: usize) -> Vec<i32> { vec![0i32; n] }
fn create_array_with_value(n: usize, val: i32) -> Vec<i32> { vec![val; n] }| C | Rust | |
|---|---|---|
| malloc + | vec![] | |
| .len() | ||
| .get() Option | ||
| free | Drop |
4: sort_array
C
void sort_array(int* arr, int n) {
if (arr == NULL || n <= 1) return;
for (int i = 0; i < n - 1; i++) {
int swapped = 0;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = 1;
}
}
if (!swapped) break;
}
}arrnintO(n)
Rust
fn sort_array_generic<T: Ord>(arr: &mut [T]) {
let n = arr.len();
if n <= 1 { return; }
for i in 0..n-1 {
let mut swapped = false;
for j in 0..n-1-i {
if arr[j] > arr[j+1] { arr.swap(j, j+1); swapped = true; }
}
if !swapped { break; }
}
}
// arr.sort() (timsort, O(n log n))arrnOrdsort
LuoguP1177 — Rust
5: read_file
C
char* read_file(const char* path) {
if (path == NULL) return NULL;
FILE* file = fopen(path, "rb");
if (!file) return NULL;
fseek(file, 0, SEEK_END);
long size = ftell(file); rewind(file);
char* buffer = malloc((size_t)size + 1);
if (!buffer) { fclose(file); return NULL; }
size_t n = fread(buffer, 1, size, file);
if (ferror(file)) { free(buffer); fclose(file); return NULL; }
buffer[n] = '\0'; fclose(file);
return buffer;
}CNULLftellTOCTOU
Rust
fn read_file(path: &str) -> Result<String, io::Error> {
fs::read_to_string(path)
}
//
fn read_file_streaming(path: &str) -> Result<String, io::Error> {
let file = File::open(path)?;
let reader = BufReader::new(file);
let mut result = String::new();
for line in reader.lines() { result.push_str(&line?); result.push('\n'); }
Ok(result)
}Rustio::ErrorNotFoundPermissionDenied?
6: split_string —
C40
char** split_string(const char* str, char delimiter, int* count) {
if (str == NULL || count == NULL) return NULL;
int delim_count = 0;
for (const char* p = str; *p; p++) if (*p == delimiter) delim_count++;
char** result = (char**)malloc((delim_count + 2) * sizeof(char*));
int idx = 0; const char* start = str;
for (const char* p = str; ; p++) {
if (*p == delimiter || *p == '\0') {
size_t len = (size_t)(p - start);
result[idx] = (char*)malloc(len + 1);
memcpy(result[idx], start, len);
result[idx][len] = '\0'; idx++;
if (*p == '\0') break;
start = p + 1;
}
}
result[idx] = NULL;
*count = idx;
return result;
}delim_countmalloc
Rust3
fn split_string(s: &str, delimiter: char) -> Vec<String> {
s.split(delimiter).map(|part| part.to_string()).collect()
}C40Rust 3
filter_positive —
C+
int* filter_positive(const int* arr, int len, int* out_len) {
int count = 0;
for (int i = 0; i < len; i++) if (arr[i] > 0) count++;
int* result = (int*)malloc(count * sizeof(int));
int idx = 0;
for (int i = 0; i < len; i++) if (arr[i] > 0) result[idx++] = arr[i];
*out_len = count; return result;
}Rust1
fn filter_positive(arr: &[i32]) -> Vec<i32> {
arr.iter().copied().filter(|&x| x > 0).collect()
}NULLout_lenVecVecNULL
LuoguP1428 —
NULL→ Option<T>
NULL→ Option<T> Result<T,E>
→ &mut
→ Drop
+→ &[T] &mut [T]
→ Result
goto→ RAII + Drop + ?
→ From/Into trait
→ Arc/Mutex
→