C语言代码如何实现打印命令行参数中唯一不重复字符?
核心代码段逻辑解析
这段代码实现去重的核心是利用了桶标记法:因为标准ASCII字符的取值范围是0~255,程序开头定义的int used[255] = {0}就是充当标记桶的作用,数组下标对应字符的ASCII值,数组值0表示对应字符从未出现,1表示对应字符已经出现过。
接下来逐行拆解核心代码的运行逻辑:
j = 0;:初始化当前遍历字符串的下标,从字符串的第一个字符开始遍历while(argv[i][j]):C语言字符串默认以\0(ASCII值为0)作为结束标识符,只要argv[i][j]的值不为0,就说明还没遍历到当前字符串的末尾,继续执行循环if(!used[(unsigned char)argv[i][j]]):- 把当前字符强制转为
unsigned char是为了避免带符号的字符值为负数时,出现数组下标越界的问题 - 以字符的ASCII值为下标读取
used数组的对应值,如果值为0,说明这个字符之前从未出现过,满足打印条件
- 把当前字符强制转为
used[(unsigned char)argv[i][j]] = 1;:进入if分支后,立刻把used数组对应下标的值设为1,标记该字符已经出现过,后续再遇到相同字符时就不会再进入if分支write(1, &argv[i][j], 1);:调用系统调用write向标准输出(文件描述符1对应屏幕输出)打印当前这个首次出现的字符,打印长度为1字节j++;:下标自增,继续遍历当前字符串的下一个字符
举个实际运行的示例更易理解:假设传入的两个参数分别是hello和world
遍历第一个字符串
hello时:
- h首次出现,打印h,标记h对应的ASCII值位置为1
- e首次出现,打印e,标记e对应的ASCII值位置为1
- l首次出现,打印l,标记l对应的ASCII值位置为1
- 第二个l对应的标记已经为1,跳过不打印
- o首次出现,打印o,标记o对应的ASCII值位置为1
遍历第二个字符串world时:- w首次出现,打印w,标记w对应的ASCII值位置为1
- o对应的标记已经为1,跳过不打印
- r首次出现,打印r,标记r对应的ASCII值位置为1
- l对应的标记已经为1,跳过不打印
- d首次出现,打印d,标记d对应的ASCII值位置为1
最终输出结果为helowrd,完全符合无重复、按出现顺序输出的要求。
内容的提问来源于stack exchange,提问作者Ajo Mathew
相关产品推荐
相关产品推荐

