为了弄懂sprintf,我写了这个程序,是不是很幼稚。

本文通过一个具体的C语言程序示例,深入探讨了指针的指针概念,解析了如何使用指针来操作字符串,并演示了如何通过指针进行数值转换的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

同时也是为了理解指针的指针,所以写了如下程序并调试之。

百度网盘下载地址:

https://pan.baidu.com/s/1_-IznMWL3z1CROziiD6mCw

#include <stdio.h>

int is_digit(char c) ;

int main (int argc, char *argv[]) {
    int i;
    for (i = 0; i < argc; i++)
        printf ("%s\n", *argv++);

    char *str = "65535";
    
    char **s;
    s = &str;

    i = 0;

    while (is_digit(**s)) {

        i = i * 10 + *((*s)++) - '0';
    }
    
    printf ("\n");
    printf ("%d\t %x\n", i, i);


}

int is_digit(char c) {
    if (c >= '0' && c <= '9') {
        return 1;
    } else {
        return 0;        
    }

}

<think>我们被要求一个C程序,展示sprintf的所有用法。sprintf函数用于将格式化的数据入字符串中。它的原型如下: int sprintf(char *str, const char *format, ...); 我们将通过多个示例来展示不同的格式化用法,包括基本类型、宽度和精度控制、对齐、科学计数法、字符串截取等。 注意:由于sprintf可能存在缓冲区溢出的风险,我们在使用时会确保缓冲区足够大,或者使用snprintf(但题目要求sprintf)。 我们将创建一个程序,包含多个示例,每个示例都打印出格式化后的字符串。 步骤: 1. 包含头文件<stdio.h> 2. 在main函数中,定义足够的缓冲区(例如buf[100]) 3. 使用多个sprintf示例,并打印结果。 示例包括: 1. 整数和浮点数 2. 指定宽度和精度 3. 左对齐和右对齐 4. 字符串格式化 5. 八进制和十六进制 6. 科学计数法 7. 混合格式化 8. 使用*号动态指定宽度和精度 9. 格式化字符 10. 将多个数据格式化为一个字符串 同时,我们也会注意一些特殊用法,比如使用%n来记录已入的字符数(虽然不常用,但也展示)。 最后,我们将输出每个示例的格式化字符串。 注意:由于sprintf不会检查目标缓冲区的大小,因此我们必须确保缓冲区足够大以避免溢出。 程序结构: - 每个示例前打印说明 - 使用sprintf格式化 - 打印结果 我们将使用一个缓冲区,并在每个示例后打印并重置缓冲区(如果需要,也可以使用不同的缓冲区,但这里我们复用同一个,并在每个示例后打印)。 由于sprintf返回入的字符数(不包括结尾的'\0'),我们也可以打印这个返回值。 但是,为了简洁,我们主要展示格式化结果。 开始编程序:</think>### C语言 `sprintf` 函数完整用法示例程序 `sprintf` 是 C 语言中强大的字符串格式化函数,用于将格式化的数据入字符串缓冲区。其函数原型为: ```c int sprintf(char *str, const char *format, ...); ``` - **`str`**:目标字符串缓冲区 - **`format`**:格式控制字符串 - **`...`**:要格式化的数据 - **返回值**:成功入的字符数(不包括结尾的 `\0`) --- ### 完整示例程序 ```c #include <stdio.h> #include <math.h> // 用于数学函数 int main() { char buffer[256]; // 目标缓冲区 // 1. 基本数据类型格式化 int num = 42; float pi = 3.1415926535; double sqrt2 = sqrt(2); char letter = 'A'; sprintf(buffer, "整数: %d, 浮点数: %.2f, 双精度: %.4lf, 字符: %c", num, pi, sqrt2, letter); printf("1. %s\n", buffer); // 2. 字符串拼接 char name[] = "Alice"; int age = 30; sprintf(buffer, "姓名: %s, 年龄: %d", name, age); printf("2. %s\n", buffer); // 3. 数值格式控制 int value = 12345; // 宽度与对齐 sprintf(buffer, "右对齐: [%8d], 左对齐: [%-8d], 补零: [%08d]", value, value, value); printf("3. %s\n", buffer); // 4. 浮点数精度控制 double precise = 3.141592653589793; sprintf(buffer, "默认: %f, 2位小数: %.2f, 科学计数: %.4e", precise, precise, precise); printf("4. %s\n", buffer); // 5. 十六进制和八进制 int hex_num = 255; sprintf(buffer, "十六进制: 0x%X, 小: 0x%x, 八进制: %o", hex_num, hex_num, hex_num); printf("5. %s\n", buffer); // 6. 指针格式化 int var = 100; int *ptr = &var; sprintf(buffer, "变量地址: %p, 值: %d", (void*)ptr, *ptr); printf("6. %s\n", buffer); // 7. 使用%n记录入字符数 int count; char text[] = "Hello World"; sprintf(buffer, "文本: %s%n", text, &count); printf("7. %s (入字符数: %d)\n", buffer, count); // 8. 动态宽度和精度 int width = 10; int precision = 3; sprintf(buffer, "动态控制: %*.*f", width, precision, pi); printf("8. %s\n", buffer); // 9. 混合格式复杂示例 time_t now = time(NULL); struct tm *t = localtime(&now); sprintf(buffer, "%04d年%02d月%02d日 %02d:%02d:%02d | 状态: %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, (num > 40) ? "正常" : "警告"); printf("9. %s\n", buffer); // 10. 安全使用建议(防止缓冲区溢出) char long_str[] = "这是一个非常长的字符串,可能超过缓冲区大小"; int safe_count = snprintf(buffer, sizeof(buffer), "截断测试: %s", long_str); if(safe_count >= sizeof(buffer)) { printf("10. 警告: 需要 %d 字节,缓冲区仅 %zu 字节\n", safe_count + 1, sizeof(buffer)); } printf("10. %s\n", buffer); return 0; } ``` --- ### 关键用法解析 #### 1. 基础格式化 ```c sprintf(buffer, "整数: %d, 浮点数: %.2f", 42, 3.1415); ``` - `%d`:格式化整数 - `%.2f`:保留2位小数的浮点数[^1] #### 2. 宽度和对齐控制 ```c sprintf(buffer, "[%8s] [%-8s]", "右对齐", "左对齐"); ``` - `%8s`:右对齐,宽度8字符 - `%-8s`:左对齐,宽度8字符 - `%08d`:用0填充空白(如`00123`) #### 3. 动态格式控制 ```c int width = 10, prec = 3; sprintf(buffer, "%*.*f", width, prec, 3.141592); // 等效于 "%10.3f" ``` #### 4. 特殊格式符 | 格式符 | 用途 | 示例 | |--------|---------------------|--------------| | `%p` | 指针地址 | `0x7ffd...` | | `%x` | 十六进制(小) | `ff` | | `%X` | 十六进制(大) | `FF` | | `%o` | 八进制 | `377` | | `%e` | 科学计数法 | `3.14e+00` | | `%n` | 记录已入字符数 | 存储到整型变量 | #### 5. 安全注意事项 ```c // 危险:可能溢出 sprintf(small_buf, "%s", long_str); // 安全:使用 snprintf snprintf(buf, sizeof(buf), "%s", long_str); ``` 始终检查返回值: ```c int needed = snprintf(NULL, 0, "格式: %d", large_num); if(needed > buf_size) { // 处理缓冲区不足 } ``` --- ### 程序输出示例 ``` 1. 整数: 42, 浮点数: 3.14, 双精度: 1.4142, 字符: A 2. 姓名: Alice, 年龄: 30 3. 右对齐: [ 12345], 左对齐: [12345 ], 补零: [00012345] 4. 默认: 3.141593, 2位小数: 3.14, 科学计数: 3.1416e+00 5. 十六进制: 0xFF, 小: 0xff, 八进制: 377 6. 变量地址: 0x7ffc..., 值: 100 7. 文本: Hello World (入字符数: 11) 8. 动态控制: 3.142 9. 2023年09月15日 14:30:22 | 状态: 正常 10. 截断测试: 这是一个非常长的字符... ``` > **最佳实践**: > 1. 对用户输入数据使用 `snprintf` 防止缓冲区溢出[^2] > 2. 浮点数精度控制可避免累积误差 > 3. 检查返回值确保格式化成功 > 4. 复杂格式建议分步处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_39410618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值