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 strlenRust 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] }
CRust
malloc +vec![]
.len()
.get() Option
freeDrop

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 
 →