C语言代码实现URL编码

在 Python,只需要导入 urllib.parse,然后使用 quote 函数即可把任意字符串进行 URL 编码

现在使用 C 语言来实现等效的代码,我在网上找到现成的代码,改代码接收命令行输入参数,然后进行 URL 编码并输出:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>char* urlquote(char* str) {size_t len = strlen(str);char* result = (char*)malloc((3 * len + 1) * sizeof(char));size_t index = 0;for (size_t i = 0; i < len; i++) {char c = str[i];if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' || c == '/') {result[index++] = c;}else {sprintf(&result[index], "%%%02X", (uint8_t)c);index += 3;}}result[index] = '\0';return result;
}int main(int argc, char* argv[]) {if (argc!=2){printf("Usage: urlquote.exe <string>\n\n");return 1;}char* quoted_str = urlquote(argv[1]);printf("%s\n", quoted_str);free(quoted_str);return 0;
}

该代码在 Linux 环境里运行没有问题,输入参数“中”字可以得出正确的编码值:%E4%B8%AD。

然而在 Windows 命令行环境里运行,如果输入半角字符可以得出正确的 URL 编码,但输入字符串只要有中文,得出的结果就截然不同。举个例子,同样的“中”字在 Windows 环境里编码的结果却是:%D6%D0。

这个 D6 D0 是什么?我在其他查询中文编码的网站上得知是 GBK 编码。

“中”字的 UTF-8 编码应该是 E4 B8 AD,三位字节组成。

Windows 和 Linux 环境运行结果不同的原因在于命令行环境的字符编码不同。Linux 以及 C 编译器使用 UTF-8 编码,因此上述代码在 Linux 命令行里输入的参数都能以 UTF-8 编码传入进而转换得出正确的结果。

然而 Windows 的命令行字符编码与本地代码页有关,简体中文的代码页是 GBK(936),Python的 quote 函数实质是按字符串的 UTF-8 字符值进行编码的,上述 C 代码没有考虑什么字符编码环境,仅仅使用当前默认编码,没有正确转换到 UTF-8,所以造成编码结果不同。

因此为了让代码能在 Windows 环境得出正确结果,就必须把传入参数的字符串进行转换成 UTF-8。

由于历史问题,Windows API 库没有一步到位直接把 GBK 转换 UTF-8 的函数,只能 GBK → UniCode → UTF-8 这样来转换。上述代码修改如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <windows.h>char* urlquote(char* gbk_str) {// 先转换UniCodeint size_needed = MultiByteToWideChar(CP_ACP, 0, gbk_str, -1, NULL, 0);wchar_t* wide_str = (wchar_t*)malloc(size_needed * sizeof(wchar_t));MultiByteToWideChar(CP_ACP, 0, gbk_str, -1, wide_str, size_needed);// 再转换UTF-8size_needed = WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, NULL, 0, NULL, NULL);char* utf8_str = (char*)malloc(size_needed);WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, utf8_str, size_needed, NULL, NULL);size_t len = strlen(utf8_str);char* result = (char*)malloc((3 * len + 1) * sizeof(char));size_t index = 0;for (size_t i = 0; i < len; i++) {char c = utf8_str[i];if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' || c == '/') {result[index++] = c;}else {sprintf(&result[index], "%%%02X", (uint8_t)c);index += 3;}}result[index] = '\0';free(wide_str);free(utf8_str);return result;
}int main(int argc, char* argv[]) {if (argc!=2){printf("Usage: urlquote.exe <string>\n\n");return 1;}char* quote_str = urlquote(argv[1]);printf("%s\n", quote_str);free(quote_str);return 0;
}

运行的结果将与 Linux 环境保持一致了,而且与 Python 的 quote 函数相媲美了。

输入参数:"http://xyz.com/?a=壹贰叁&b={\"c=['啊哦呃']\"}"Python的quote结果:
http%3A//xyz.com/%3Fa%3D%E5%A3%B9%E8%B4%B0%E5%8F%81%26b%3D%7B%22c%3D%5B%27%E5%95%8A%E5%93%A6%E5%91%83%27%5D%22%7DC在Windows命令行运行结果:
http%3A//xyz.com/%3Fa%3D%E5%A3%B9%E8%B4%B0%E5%8F%81%26b%3D%7B%22c%3D%5B%27%E5%95%8A%E5%93%A6%E5%91%83%27%5D%22%7D

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/279210.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云演CTF Blog

1、啥也搞不了&#xff0c;扫目录。出来个console 2、有显示锁掉了 3、抓包&#xff0c;改返回包 改成true&#xff0c;放包 不好意思&#xff0c;不会了&#xff0c;哈哈哈哈哈哈哈哈哈 你会的话&#xff0c;请告诉我&#xff0c;大佬

使用国内镜像源安装opencv

在控制台输入命令&#xff1a; pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple 验证安装&#xff1a; step 1&#xff1a; 打开终端&#xff1b;step 2&#xff1a; 输入python&#xff0c;进入Python编译环境&#xff1b;step 3&#xff1a; 粘贴…

Linux——进程中被打开的文件

C语言中有着许多对文件操作的函数&#xff0c;包括其他语言也有&#xff0c;但是从语言来了解文件有点浅显计算机的一切都离不开操作系统&#xff0c;那么文件跟操作系统也有着密切的关系&#xff0c;所以我们从系统层面来了解文件&#xff08;在进程中打开的文件&#xff09;文…

“Java 已死、前端已凉”?技术变革与编程语言前景:Java和前端的探讨

前端已死话题概论 本文讨论了近期IT圈中流传的“Java 已死、前端已凉”言论。我们审视了这些言论的真实性&#xff0c;并深入探讨了技术行业的演变和新兴技术的出现对编程语言和前端开发的影响。通过分析历史发展、当前趋势和未来展望&#xff0c;我们提供了对这些话题更深层次…

三、Spring IoC 容器和核心概念

本章概要 组件和组件管理概念 什么是组件&#xff1f;我们的期待Spring充当组件管理角色&#xff08;IoC&#xff09;组件交给Spring管理优势 Spring IoC 容器和容器实现 普通和复杂容器SpringIoC 容器介绍SpringIoC 容器具体接口和实现类SpringIoC 容器管理配置方式 Spring I…

【Proteus仿真】【51单片机】电子门铃设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使共阴数码管&#xff0c;按键、无源蜂鸣器等。 主要功能&#xff1a; 系统运行后&#xff0c;数码管默认显示第一种门铃音调&#xff0c;可通过K1键切…

OpenAI 承认 ChatGPT 最近的懒惰:由于用户体验到响应缓慢和无用的输出,调查正在进行中

文章目录 一. ChatGPT 指令遵循能力下降引发用户投诉1.1 用户抱怨回应速度慢、敷衍回答、拒绝回答和中断会话 二. OpenAI 官方确认 ChatGPT 存在问题&#xff0c;展开调查三. OpenAI 解释模型行为差异&#xff0c;回应用户质疑四. GPT-4 模型变更受人事动荡和延期影响 一. Chat…

【C++11特性篇】C++11中新增的initializer_list——初始化的小利器

前言 大家好吖&#xff0c;欢迎来到 YY 滴C11系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.探究std::initializer_list是什么…

关于“Python”的核心知识点整理大全23

目录 ​编辑 第&#xff11;0 章 文件和异常 10.1 从文件中读取数据 10.1.1 读取整个文件 pi_digits.txt file_reader.py 10.1.2 文件路径 10.1.3 逐行读取 file_reader.py 10.1.4 创建一个包含文件各行内容的列表 10.1.5 使用文件的内容 pi_string.py 往期快速传…

解决goview栈内存溢出导致打包报错问题

最近搞低代码大屏使用goview打包时遇到问题 报错&#xff1a; vite v4.3.6 building for production... transforming (8931) node_modules\monaco-editor\esm\vs\base\common\navigator.js <--- Last few GCs ---> [24864:000001B515BA39F0] 65979 ms: Scavenge 2002.0…

Linux系统编程(二):文件 I/O(中)

参考引用 UNIX 环境高级编程 (第3版)嵌入式Linux C应用编程-正点原子 1. 一个简单的文件 IO 示例 只读方式打开一个已经存在的文件&#xff08;src_file&#xff09;&#xff0c;然后只写方式打开一个新建文件&#xff08;dest_file&#xff09;&#xff0c;权限设置如下 文件…

什么是第一方数据,如何使用它?

多年来&#xff0c;第一方数据一直是营销行业的话题。 随着用户数据隐私法律法规的不断收紧&#xff0c;营销人员必须接受一个几乎没有数据 cookie 的世界。 我们必须在如何合法和合乎道德地获取客户信息方面更具创造性。 不确定什么是第一方数据&#xff1f;或者不太确定从…