1116. Come on! Let's C 解析

本文介绍了一个简单的抽奖程序,该程序还包含了素数判断的功能。通过不同的输入,程序能够为参与者分配不同的奖品,同时利用素数判断来决定部分奖励的分配。

抽奖,顺带考察了下怎么求素数。

分清情况讨论就好。

#include <iostream>
#include <map>
#include <string>

#define MAX 10010

using namespace std;

map <int, int> ID2RANK;
int Rank[MAX];
int n, m;

string Champion = "Mystery Award";
string Prime = "Minion";
string Everyone = "Chocolate";
string NoEntry = "Are you kidding?";
string Checked = "Checked";


void CheckReward(int ID) {
	switch (ID2RANK[ID])
	{
		
	case 0:printf("%04d: %s\n", ID, &NoEntry[0]); break;
	case 1:printf("%04d: %s\n", ID, &Champion[0]); ID2RANK[ID] = 4; break;
	case 2:printf("%04d: %s\n", ID, &Everyone[0]); ID2RANK[ID] = 4; break;
	case 3:printf("%04d: %s\n", ID, &Prime[0]); ID2RANK[ID] = 4; break;
	case 4:printf("%04d: %s\n", ID, &Checked[0]); break;
	default:
		break;
	}
}

bool isPrime(int num) {
	if (num <= 1) return false;

	for (int i = 2; i * i <= num; i++) {
		if (num % i == 0)
			return false;
	}
	return true;
}


int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> Rank[i];
		if(i==1)
			ID2RANK[Rank[i]] = 1;
		else if (isPrime(i))
			ID2RANK[Rank[i]] = 3;
		else 
			ID2RANK[Rank[i]] = 2;
	}

	cin >> m;
	int temp;
	for (int i = 0; i < m; i++) {
		cin >> temp;
		CheckReward(temp);
	}

	return 0;
}


#!/bin/sh #![allow(missing_abi)] /* # rust shebang by Mahmoud Al-Qudsi, Copyright NeoSmart Technologies 2020-2024 # See <https://neosmart.net/blog/self-compiling-rust-code/> for info & updates. # # This code is freely released to the public domain. In case a public domain # license is insufficient for your legal department, this code is also licensed # under the MIT license. # Get an output path that is derived from the complete path to this self script. # - `realpath` makes sure if you have two separate `script.rs` files in two # different directories, they get mapped to different binaries. # - `which` makes that work even if you store this script in $PATH and execute # it by its filename alone. # - `cut` is used to print only the hash and not the filename, which `md5sum` # always includes in its output. OUT=/tmp/$(printf "%s" $(realpath $(which "$0")) | md5sum | cut -d' ' -f1) # Calculate hash of the current contents of the script, so we can avoid # recompiling if it hasn't changed. MD5=$(md5sum "$0" | cut -d' ' -f1) # Check if we have a previously compiled output for this exact source code. if !(test -x "${OUT}" && test -f "${OUT}.md5" && \ test "${MD5}" = "$(cat "${OUT}.md5")"); then # The script has been modified or is otherwise not cached. # Check if the script already contains an `fn main()` entry point. if grep -Eq '^\s*(\[([^][]*)])*\s*fn\s+main\b' "$0"; then # Compile the input script as-is to the previously determined location. rustc "$0" -o ${OUT} # Save rustc's exit code so we can compare against it later. RUSTC_STATUS=$? else # The script does not contain an `fn main()` entry point, so add one. # We don't use `printf 'fn main() { %s }' because the shebang must # come at the beginning of the line, and we don't use `tail` to skip # it because that would result in incorrect line numbers in any errors # reported by rustc, instead we just comment out the shebang but leave # it on the same line as `fn main() {`. printf "fn main() {//%s\n}" "$(cat $0)" | rustc - -o ${OUT} # Save rustc's exit code so we can compare against it later. RUSTC_STATUS=$? fi # Check if we compiled the script OK, or exit bubbling up the return code. if test "${RUSTC_STATUS}" -ne 0; then exit ${RUSTC_STATUS} fi # Save the MD5 of the current version of the script so we can compare # against it next time. printf "%s" ${MD5} > ${OUT}.md5 fi # Execute the compiled output. This also ends execution of the shell script, # as it actually replaces its process with ours; see exec(3) for more on this. exec ${OUT} "$@" # At this point, it's OK to write raw rust code as the shell interpreter # never gets this far. But we're actually still in the rust comment we opened # on line 2, so close that: */ fn main() { let name = std::env::args().skip(1).next().unwrap_or("world".into()); println!("Hello, {}!", name); } // vim: ft=rust : 解释以下这段代码
最新发布
04-02
<think>嗯,我现在得仔细看看用户提供的这段代码,然后解释它的功能和原理。首先,用户给了一个混合了shell脚本和Rust代码的文件,看起来有点复杂。我需要逐步拆解,理解每一部分的作用。 首先,代码的开头是#!/bin/sh,这是一个shell脚本的shebang,说明这个文件应该用/bin/sh来执行。不过接下来的内容里还有Rust代码,所以这应该是一个结合了shell和Rust的脚本。这种结构我之前见过,可能是一个自编译的脚本,也就是用shell部分来编译Rust代码,然后执行。 接下来,注意到第二行有一个#![allow(missing_abi)],这是Rust的属性,通常用于允许某些编译警告。但这里被包裹在shell的注释中,因为shell会忽略这些行,而Rust编译器在后续处理时会读取这些属性。这很巧妙,因为shell执行时不会处理这些Rust特有的部分,而Rust编译时则会忽略前面的shell脚本部分。 然后看shell脚本部分。用户定义了一个OUT变量,路径在/tmp下,后面跟着一个md5sum的结果。这里用了realpath和which来获取脚本的绝对路径,然后用md5生成哈希值,确保不同路径的同名脚本不会冲突。OUT变量应该用来存放编译后的可执行文件路径,这样可以缓存编译结果,避免重复编译。 接下来计算当前脚本的MD5哈希,保存在MD5变量里。然后检查是否存在之前编译好的可执行文件,并且其MD5和当前脚本的MD5是否一致。如果存在且一致,说明脚本没有修改过,可以直接执行缓存的可执行文件,否则需要重新编译。 如果缓存无效,脚本会检查是否有fn main()函数。这里用了grep命令来搜索,如果存在,就直接用rustc编译脚本;如果不存在,就用printf将shebang行注释掉,并在外面包裹fn main()函数,然后通过管道传给rustc编译。这一步是关键,因为Rust需要一个main函数作为入口,而脚本可能在最后才定义main,或者可能没有,所以需要动态处理。 编译完成后,保存MD5到文件,以便下次比较。如果编译失败,脚本会退出并返回rustc的状态码。最后,使用exec执行编译好的程序,替换当前的shell进程,并传递参数。 在shell脚本之后是Rust代码,被包裹在/* ... */注释中,因为shell会执行到exec时替换进程,不会继续执行后面的内容。而Rust编译器会处理这些代码,因为前面的shell脚本部分已经被处理成注释或包裹在main函数里。 最后的Rust代码定义了main函数,读取命令行参数并打印Hello信息。这应该是一个示例,展示脚本的功能。 总结来说,这个脚本是一个自编译的Rust脚本,利用shell部分处理编译和缓存,使得用户可以直接运行.rs文件,而不需要手动编译。每次运行脚本时,它会检查是否有更改,如果没有则使用缓存的可执行文件,提高效率。这种技巧对于需要快速测试或分发Rust脚本的情况很有用,但可能隐藏了编译的复杂性,用户可能需要注意编译时间和依赖问题。</think>下面分步解释这段自编译Rust脚本的工作原理: 1. **混合式脚本结构** - 文件前部分是shell脚本(`#!/bin/sh`开头) - 后部分是Rust代码(包裹在`/* ... */`注释中) - 通过巧妙的注释设计,同时满足shell和Rust编译器的解析规则 2. **执行流程** ```shell # 1. 计算缓存路径(使用脚本绝对路径的MD5) OUT=/tmp/$(realpath "$0" | md5sum | cut -d' ' -f1) # 2. 计算当前脚本的MD5 MD5=$(md5sum "$0" | cut -d' ' -f1) # 3. 检查是否需要重新编译(对比MD5) if [ 缓存无效 ]; then # 4. 动态生成main函数(如果不存在) # 5. 调用rustc编译 rustc ... -o ${OUT} # 6. 保存新MD5 echo ${MD5} > ${OUT}.md5 fi # 7. 执行编译产物 exec ${OUT} "$@" ``` 3. **关键技术点** - **路径哈希化**:$$ \text{OUT路径} = \text{MD5}(\text{脚本绝对路径}) $$ 确保不同位置同名脚本不会冲突 - **增量编译**:$$ \text{当前MD5} \stackrel{?}{=} \text{缓存MD5} $$ 仅在脚本修改时重新编译 - **动态main函数**: ```rust // 原始脚本内容被包裹在: fn main() { // 原shebang行被注释 原脚本内容 } ``` 4. **Rust代码部分** ```rust /* 这个多行注释会被shell忽略 */ fn main() { let name = std::env::args().nth(1).unwrap_or("world".into()); println!("Hello, {}!", name); // 示例功能 } // vim: ft=rust : 保持编辑器识别 ``` 5. **使用效果示例** ```bash $ chmod +x hello.rs $ ./hello.rs # 输出 Hello, world! $ ./hello.rs Alice # 输出 Hello, Alice! ``` 6. **优势与限制** - ✓ 单文件分发 - ✓ 自动编译缓存 - ✗ 首次运行需要编译时间 - ✗ 依赖rustc环境 - ✗ 调试信息中的行号可能不准确 这个脚本实现了类似脚本语言的开发体验,但实际执行的是编译后的原生二进制,兼顾了开发便利性和执行效率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值