当前位置: 首页 > news >正文

使用C语言将ASCII明文编码为GSM短信体格式

一、背景介绍

GSM(Global System for Mobile Communications)是全球移动通信系统的简称,而GSM 03.38是GSM系统中用于短信编码的标准。GSM 03.38字符集采用7-bit编码,与ASCII的8-bit编码有所不同。为了将ASCII编码的文本转换为GSM短信格式,我们需要进行一系列的转换操作。
在这里插入图片描述

** 二、GSM短信内容格式解析 **

短信内容的基本构成

GSM短信的内容主要包括以下几个部分:

  1. 消息头(Header):包含短信的发送方和接收方的信息,如电话号码、短信中心等。这部分信息通常由移动网络运营商自动处理,用户无需关心。

  2. 消息体(Body):即短信的实际内容,可以是文本、数字、符号等。GSM短信的标准长度是160个字符(7-bit编码),但也可以支持更长的消息,通过连接多条短信实现。

  3. 时间戳(Timestamp):记录短信的发送或接收时间。这个时间戳对于用户了解短信的时效性非常重要。

  4. 编码与字符集

GSM短信的字符集和编码方式对其内容格式有重要影响。以下是一些关键概念:

  1. GSM 03.38字符集:这是一种专为GSM短信设计的字符集,包含了大多数拉丁字母、数字、标点符号和一些特殊字符。这个字符集是7-bit编码的,因此每条短信最多可以包含160个字符。
  2. Unicode编码:为了支持更多语言和字符,GSM短信也可以采用Unicode编码(如UTF-8或UTF-16)。但是,Unicode编码会导致每条短信的字符数减少,因为每个字符需要更多的字节来表示。

3、长短信与连接短信

当一条短信的内容超过160个字符时,它可以被拆分成多条短信进行发送。这种拆分和重新组装的过程对于用户来说是透明的,他们只会看到一条连续的、完整的消息。这种超过160个字符的短信通常被称为“长短信”或“连接短信”。

4、特殊格式与功能

除了基本的文本消息外,GSM短信还支持一些特殊格式和功能,如:

  1. 闪烁文本:通过特定的编码方式,可以使短信中的某些文本在接收方的手机上闪烁显示。
  2. 铃声提示:发送方可以选择特定的铃声作为接收方收到短信时的提示音。
  3. 图形和图片:虽然传统的GSM短信主要支持文本内容,但随着技术的发展,现在也可以发送包含图形和图片的彩信(MMS)。
  4. 链接和嵌入数据:一些高级的短信服务还支持在短信中嵌入链接或其他数据,如位置信息、联系人卡片等。

三、转换步骤

  1. 字符映射:由于ASCII和GSM 03.38字符集并不完全一致,首先需要建立一个ASCII到GSM 03.38的映射表。这个映射表将ASCII字符映射到对应的GSM 03.38字符上。
  2. 7-bit编码:将每个GSM 03.38字符转换为7-bit格式。这意味着每8个字符可以压缩为7个字节。
  3. 处理非GSM字符:对于不在GSM 03.38字符集中的ASCII字符,需要进行特殊处理,如替换或转义。

四、C语言实现

下面是一个使用C语言实现ASCII到GSM 03.38编码的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// ASCII到GSM 03.38的映射表(仅示例,不完整)
unsigned char asciiToGsm[128] = {// ... 其他字符映射'A', 'B', 'C', // ASCII大写字母映射到GSM大写字母// ... 其他字符映射'a', 'b', 'c', // ASCII小写字母映射到GSM小写字母// ... 其他特殊字符和扩展字符映射
};// 将ASCII字符转换为GSM 03.38字符
unsigned char convertAsciiToGsm(unsigned char c) {if (c < 128 && asciiToGsm[c] != 0) {return asciiToGsm[c]; // 如果在映射表中,返回对应的GSM字符} else {return '?'; // 对于不在映射表中的字符,返回'?'作为替换字符}
}// 将ASCII字符串转换为GSM格式并输出
void encodeAsciiToGsm(const char* asciiStr) {unsigned char* gsmStr = (unsigned char*)malloc(strlen(asciiStr) + 1); // 为GSM字符串分配内存for (int i = 0; asciiStr[i] != '\0'; i++) {gsmStr[i] = convertAsciiToGsm((unsigned char)asciiStr[i]); // 转换每个字符}gsmStr[strlen(asciiStr)] = '\0'; // 添加字符串结束符printf("GSM编码: %s\n", gsmStr); // 输出GSM编码的字符串free(gsmStr); // 释放内存
}int main() {const char* asciiMessage = "Hello, World!"; // ASCII明文消息encodeAsciiToGsm(asciiMessage); // 将ASCII消息编码为GSM格式并输出return 0;
}

这段代码定义了一个convertAsciiToGsm函数,用于将单个ASCII字符转换为对应的GSM 03.38字符。encodeAsciiToGsm函数则用于处理整个字符串,并将结果输出。在main函数中,我们提供了一个示例ASCII消息,并调用encodeAsciiToGsm函数进行转换和输出。

为了将每个GSM 03.38字符转换为7-bit格式,并每8个字符压缩为7个字节,我们可以使用位操作来实现。下面是一个示例代码,展示了如何进行这种转换:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// ASCII到GSM 03.38的映射表(仅示例,不完整)
unsigned char asciiToGsm[128] = {// ... 其他字符映射'A', 'B', 'C', // ASCII大写字母映射到GSM大写字母// ... 其他字符映射'a', 'b', 'c', // ASCII小写字母映射到GSM小写字母// ... 其他特殊字符和扩展字符映射
};// 将ASCII字符转换为GSM 03.38字符
unsigned char convertAsciiToGsm(unsigned char c) {if (c < 128 && asciiToGsm[c] != 0) {return asciiToGsm[c]; // 如果在映射表中,返回对应的GSM字符} else {return '?'; // 对于不在映射表中的字符,返回'?'作为替换字符}
}// 将GSM 03.38字符串转换为7-bit编码格式
void encodeGsm7Bit(const unsigned char* gsmStr, unsigned char* encodedData) {int length = strlen((const char*)gsmStr); // 获取字符串长度int septetsCount = (length * 7 + 7) / 8; // 计算需要的7-bit单元数量int byteIndex = 0; // 当前字节的索引unsigned char currentByte = 0; // 当前正在构建的字节int bitIndex = 0; // 当前字节中的位索引for (int i = 0; i < length; i++) {unsigned char gsmChar = gsmStr[i]; // 获取当前GSM字符for (int j = 0; j < 7; j++) {unsigned char bit = (gsmChar >> (6 - j)) & 0x01; // 获取当前字符的第j位currentByte |= bit << bitIndex; // 将位添加到当前字节中bitIndex++; // 增加位索引if (bitIndex == 7) { // 如果当前字节已满encodedData[byteIndex++] = currentByte; // 存储当前字节到编码数据中currentByte = 0; // 重置当前字节bitIndex = 0; // 重置位索引}}}if (bitIndex > 0) { // 处理剩余的位(如果有)encodedData[byteIndex++] = currentByte; // 存储剩余的字节到编码数据中}
}int main() {const char* asciiMessage = "Hello, World!"; // ASCII明文消息unsigned char* gsmStr = (unsigned char*)malloc(strlen(asciiMessage) + 1); // 为GSM字符串分配内存for (int i = 0; asciiMessage[i] != '\0'; i++) {gsmStr[i] = convertAsciiToGsm((unsigned char)asciiMessage[i]); // 转换每个字符}gsmStr[strlen(asciiMessage)] = '\0'; // 添加字符串结束符printf("GSM编码: %s\n", gsmStr); // 输出GSM编码的字符串int septetsCount = (strlen((const char*)gsmStr) * 7 + 7) / 8; // 计算需要的7-bit单元数量unsigned char* encodedData = (unsigned char*)malloc(septetsCount); // 为编码数据分配内存encodeGsm7Bit(gsmStr, encodedData); // 将GSM字符串转换为7-bit编码格式printf("7-bit编码: "); // 输出7-bit编码的数据for (int i = 0; i < septetsCount; i++) {printf("%02X ", encodedData[i]); // 以十六进制格式输出每个字节}printf("\n");free(gsmStr); // 释放内存free(encodedData); // 释放内存return 0;
}

在这个示例代码中,encodeGsm7Bit函数将GSM 03.38字符串转换为7-bit编码格式。它遍历每个GSM字符,并将其转换为7个位,然后将这些位添加到当前正在构建的字节中。当当前字节满时,将其存储到编码数据中,并重置当前字节和位索引。最后,处理剩余的位(如果有)并将其存储到编码数据中。在main函数中,我们首先将ASCII消息转换为GSM字符串,然后调用encodeGsm7Bit函数进行7-bit编码,并输出编码结果。

请注意,这个示例代码仅用于演示目的,实际的转换过程可能更加复杂,需要考虑更多的细节和异常情况。

相关文章:

使用C语言将ASCII明文编码为GSM短信体格式

一、背景介绍 GSM&#xff08;Global System for Mobile Communications&#xff09;是全球移动通信系统的简称&#xff0c;而GSM 03.38是GSM系统中用于短信编码的标准。GSM 03.38字符集采用7-bit编码&#xff0c;与ASCII的8-bit编码有所不同。为了将ASCII编码的文本转换为GSM…...

docker搭建mysql8.0.32,实现主从复制(一主两从)

安装docker的步骤、使用命令就不写了&#xff0c;本文章是基于会使用docker、linux基本命令的基础上来写的。 开始步骤&#xff1a; 1. 拉取 mysql 镜像 docker pull mysql:8.0.32 2. 启动容器并运行mysql a. 准备mysql的配置文件&#xff08;该配置文件是&#xff1a;mysq…...

AOP springboot

1. 2. Around(“execution(* com.example.demo.controller..(…))”) 代表所有的类下面所有的方法任意参数 3....

Python Flask 基础入门第六课: Flask 全局变量 current_app, g 以及 session各自如何使用 有什么差异

全局变量 current_app, g 以及 session 全局变量差异汇总表current_app章节1 current_app - 当前应用实例current_app的基本概念current_app的作用current_app的使用 章节2&#xff1a;current_app的上下文什么是应用上下文&#xff1f;current_app与应用上下文的关系current_a…...

第33节: Vue3 方法与在线检测

UniApp 使用 Vue3 框架时&#xff0c;您可以使用方法和在线检测来处理应用程序中的逻辑和数据。下面是一个示例&#xff0c;演示了如何在 UniApp 中使用 Vue3 框架使用方法和在线检测&#xff1a; <template> <view> <button click"handleClick"&g…...

React学习计划-React16--React基础(二)组件与组件的3大核心属性state、props、ref和事件处理

1. 组件 函数式组件&#xff08;适用于【简单组件】的定义&#xff09; 示例&#xff1a; 执行了ReactDOM.render(<MyComponent/>, ...)之后执行了什么&#xff1f; React解析组件标签&#xff0c;找到了MyComponent组件发现组件是使用函数定义的&#xff0c;随后调用该…...

flink yarn-session 启动失败retrying connect to server 0.0.0.0/0.0.0.0:8032

原因分析&#xff0c;启动yarn-session.sh&#xff0c;会向resourcemanager的端口8032发起请求&#xff1a; 但是一直无法请求到8032端口&#xff0c;触发重试机制会不断尝试 备注&#xff1a;此问题出现时&#xff0c;我的环境ambari部署的HA 高可用hadoop&#xff0c;三个节点…...

.NET面试题(二)

1.c# 中new关键字的作用 实例化对象和调用构造函数&#xff1a;当使用 new 关键字创建一个类的实例时&#xff0c;它会为对象分配内存&#xff0c;并调用相应的构造函数来初始化该对象。    隐藏基类成员&#xff08;方法、属性、事件等&#xff09;&#xff1a;当在派生类中…...

ffplay工具

在编译ffmpeg时&#xff0c;如果系统中包含了SDL库&#xff0c;则会默认编译生成ffplay工具&#xff0c;否则无法生成ffplay工具。 ffplay即可以作为播放器&#xff0c;也可以作为很多图像化音视频数据的分析工具&#xff0c;通过它可以看到视频图像的运动估计方向、音频数据的…...

第36节: Vue3 事件修饰符

在UniApp中使用Vue3框架时&#xff0c;你可以使用事件修饰符来更方便地处理用户交互事件。以下是一个示例&#xff0c;演示了如何在UniApp中使用Vue3框架使用事件修饰符&#xff1a; <template> <view> <button click.prevent"handleClick">Cli…...

如何在本地安装Flask并将其web界面发布到公网上远程访问协同开发

目录 前言 1. 安装部署Flask 2. 安装Cpolar内网穿透 3. 配置Flask的web界面公网访问地址 4. 公网远程访问Flask的web界面 前言 本篇文章讲解如何在本地安装Flask&#xff0c;以及如何将其web界面发布到公网上并进行远程访问。 Flask是目前十分流行的web框架&#xff0c;…...

八:爬虫-MySQL基础

一&#xff1a;MySQL数据库基础 1.MySQL数据库介绍 MySQL是一个[关系型数据库管理系统]&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Rela…...

Android定制ROM简介

Android定制ROM简介 这篇文章是为对自定义ROM、AOSP等词汇不太熟悉的技术爱好者和好奇的人写的。我希望通过向您介绍这个世界来开始博客写作。 在我们将注意力转向定制ROM之前&#xff0c;让我们先了解一些基础知识。 什么是操作系统&#xff1f; 维基百科对此的定义简洁而…...

百模大战中的AI行业:新趋势与未来发展

文章目录 每日一句正能量前言技术进步应用拓展行业变革人才竞争后记 每日一句正能量 人生最重要的价值是心灵的幸福&#xff0c;而不是任何身外之物。 前言 随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;已经成为引领技术革命的重要驱动力之一。在当前的…...

VScode安装C/C++编译器步骤

一、安装C/C插件 二、安装 MinGW-w64 工具链 使用国内源 git clone https://gitee.com/cuihongxi/ubuntu2-mac.git 下载后进入到VScode文件夹下&#xff0c;点击msys2-x86_64-20231026.exe进行安装 完成后&#xff0c;确保选中“立即运行 MSYS2”框&#xff0c;然后选择“完…...

【Date对象】js中的日期类型Date对象的使用详情

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续…...

【PyTorch】代码学习

文章目录 直接定义nn.Sequential(), 然后append(),最后直接net(),少写很多forward&#xff0c;适合直连式网络 直接定义nn.Sequential(), 然后append(),最后直接net(),少写很多forward&#xff0c;适合直连式网络 代码来源&#xff1a;https://github.com/zshhans/MSD-Mixer/b…...

ElasticSeach--springboot中使用

目录 一.引入依赖 二.配置链接信息 三.索引库测试 1.创建索引库 2.查询索引库 3.删除索引库 四.文档测试 1.添加文档 2.修改文档 3.删除文档 4.查询具体文档 5.批量添加文档 五.查询测试 1.查询所有 2.根据属性term匹配查询 3.分页查询 4.排序 5.过滤属性 6.boo…...

(1)(1.9) MSP (version 4.2)

文章目录 前言 1 协议概述 2 配置 3 参数说明 前言 ArduPilot 支持 MSP 协议&#xff0c;可通过任何串行端口进行遥测、OSD 和传感器。这样&#xff0c;ArduPilot 就能将遥测数据发送到 MSP 兼容设备&#xff08;如大疆护目镜&#xff09;&#xff0c;用于屏幕显示&#x…...

mysql 表锁 行锁

目录 表锁&#xff08;Table Lock&#xff09; 行锁&#xff08;Row Lock&#xff09; 进一步通过举例解释 update操作走的是什么锁 表锁示例&#xff1a; 行锁示例&#xff1a; MySQL 中常见的锁类型包括&#xff1a; 表锁&#xff08;Table Lock&#xff09; 是针对整个…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前&#xff0c;首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例&#xff0c;用_OBJECT_TYPE这个结构来解析它&#xff0c;0x80处就是今天要介绍的回调链表&#xff0c;但是先不着急&#xff0c;先把目光…...

归并排序:分治思想的高效排序

目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法&#xff0c;由约翰冯诺伊曼在1945年提出。其核心思想包括&#xff1a; 分割(Divide)&#xff1a;将待排序数组递归地分成两个子…...