C语言中的输出函数printf解析


printf 是 C 语言中一个非常常用的输出函数,用于向标准输出(通常是屏幕)打印格式化的字符串。这个函数定义在 <stdio.h> 头文件中,所以使用前需要包含这个头文件。

基本语法

int printf(const char *format, ...);

参数说明

  • const char *format:这是一个字符串,包含了你想要输出的内容和一些特殊格式化符号(如 %d, %s 等),用来指定后续参数的类型和输出格式。
  • ...:这是可变数量的额外参数,这些参数的类型和顺序必须与格式字符串中指定的一致。

返回值

  • 成功时返回输出的字符数。
  • 如果发生错误,则返回一个负数。

常用格式化符

  • %d%i:整型
  • %f:浮点型
  • %c:字符型
  • %s:字符串
  • %x%X:无符号十六进制整数(小写或大写字母)
  • %o:无符号八进制整数
  • %u:无符号十进制整数
  • %%:输出百分号本身

示例

#include <stdio.h>

int main() {
    int num = 42;
    float flt = 3.14;
    char str[] = "Hello, world!";
    
    // 输出整数
    printf("The number is: %d\n", num);
    
    // 输出浮点数
    printf("The float is: %f\n", flt);
    
    // 输出字符串
    printf("The string is: %s\n", str);
    
    // 输出多个数据
    printf("Number: %d, Float: %.2f, String: %s\n", num, flt, str);
    
    return 0;
}

在这个示例中:

  • %d 用于输出整数 num
  • %f 用于输出浮点数 flt%.2f 表示输出到小数点后两位。
  • %s 用于输出字符串 str
  • 所有的输出都以换行符 \n 结束,确保每次输出后光标移动到下一行。

printf 函数非常灵活,可以满足大多数基本的输出需求。不过需要注意的是,如果提供的参数与格式字符串不匹配,可能会导致未定义的行为。因此,在使用 printf 时,确保格式字符串与实际参数相匹配是非常重要的。

接下来我们继续探讨 printf 函数的一些高级用法和注意事项。

高级用法

1. 字段宽度

你可以指定输出字段的最小宽度。如果实际输出的字符数小于指定的宽度,空缺部分将被填充为空格(默认是右对齐)。

printf("%10d\n", 123);  // 输出为 "       123",总宽度为10个字符
2. 左对齐

通过在格式化符前加一个减号 -,可以使输出左对齐。

printf("%-10d\n", 123);  // 输出为 "123       ",总宽度为10个字符
3. 精度控制

对于浮点数,可以通过指定精度来控制小数点后的位数。

printf("%.2f\n", 3.14159);  // 输出为 "3.14"
4. 填充字符

除了默认的空格填充外,还可以指定其他字符进行填充。

printf("%010d\n", 123);  // 输出为 "0000000123",使用0填充
5. 组合使用

可以组合使用上述特性来实现复杂的格式化输出。

printf("%-10.2f\n", 3.14159);  // 输出为 "3.14      "

注意事项

1. 格式字符串与参数不匹配

如果格式字符串中的格式化符数量与实际提供的参数数量不匹配,会导致未定义行为。例如:

printf("%d %d\n", 1);  // 缺少一个参数,可能导致程序崩溃或输出错误结果
2. 安全性问题

使用 printf 时,如果格式字符串来自用户输入,可能会导致格式字符串漏洞(Format String Vulnerability)。为了避免这种情况,应该始终使用固定的格式字符串。

char input[] = "%s %d";
char name[] = "Alice";
int age = 30;

// 不安全的做法
printf(input, name, age);

// 安全的做法
printf("%s %d\n", name, age);
3. 返回值检查

虽然 printf 的返回值通常不会被检查,但在某些情况下,检查返回值可以帮助发现输出错误。

int result = printf("Hello, world!\n");
if (result < 0) {
    fprintf(stderr, "Error in printf\n");
}
实际应用示例

下面是一个更复杂的示例,展示了如何使用 printf 进行格式化的输出:

#include <stdio.h>

int main() {
    char name[] = "Alice";
    int age = 30;
    float height = 5.6;
    char grade = 'A';

    // 输出个人信息
    printf("Name: %-10s Age: %3d Height: %.2f Grade: %c\n",
           name, age, height, grade);

    // 输出表格
    printf("%-10s%-5s%6s%5s\n", "Name", "Age", "Height", "Grade");
    printf("%-10s%-5d%6.2f%5c\n", name, age, height, grade);

    return 0;
}

在这个示例中:

  • 使用了左对齐和固定宽度来格式化输出。
  • 输出了一个简单的表格,每列都有固定的宽度。

下面是 printf 函数的一些更高级的特性和用法,以及一些常见的应用场景。

更高级的用法

1. 动态字段宽度和精度

你可以在格式化符中使用星号 * 来动态指定字段宽度和精度。这些值可以从参数列表中获取。

#include <stdio.h>

int main() {
    int width = 10;
    int precision = 2;
    float value = 3.14159;

    // 动态指定字段宽度
    printf("%*d\n", width, 123);  // 输出为 "       123"

    // 动态指定精度
    printf("%.*f\n", precision, value);  // 输出为 "3.14"

    // 同时动态指定字段宽度和精度
    printf("%*.*f\n", width, precision, value);  // 输出为 "       3.14"

    return 0;
}
2. 指定基数

对于整数输出,可以指定不同的基数(二进制、八进制、十六进制)。

#include <stdio.h>

int main() {
    int number = 255;

    // 十进制输出
    printf("Decimal: %d\n", number);  // 输出为 "255"

    // 八进制输出
    printf("Octal: %o\n", number);  // 输出为 "377"

    // 十六进制输出(小写)
    printf("Hexadecimal (lowercase): %x\n", number);  // 输出为 "ff"

    // 十六进制输出(大写)
    printf("Hexadecimal (uppercase): %X\n", number);  // 输出为 "FF"

    return 0;
}
3. 指定前缀

对于八进制和十六进制输出,可以指定前缀。

#include <stdio.h>

int main() {
    int number = 255;

    // 八进制输出带前缀
    printf("Octal with prefix: %#o\n", number);  // 输出为 "0377"

    // 十六进制输出带前缀(小写)
    printf("Hexadecimal (lowercase) with prefix: %#x\n", number);  // 输出为 "0xff"

    // 十六进制输出带前缀(大写)
    printf("Hexadecimal (uppercase) with prefix: %#X\n", number);  // 输出为 "0XFF"

    return 0;
}

常见应用场景

1. 日志记录

在开发过程中,经常需要记录日志信息。使用 printf 可以方便地格式化输出日志。

#include <stdio.h>
#include <time.h>

void log_message(const char *message) {
    time_t now = time(NULL);
    char *time_str = ctime(&now);
    // 去掉最后的换行符
    time_str[strcspn(time_str, "\n")] = '\0';
    printf("[%s] %s\n", time_str, message);
}

int main() {
    log_message("This is an info message.");
    log_message("This is a warning message.");
    log_message("This is an error message.");

    return 0;
}
2. 数据表格

生成数据表格时,使用 printf 可以方便地对齐数据。

#include <stdio.h>

void print_table_header() {
    printf("%-10s%-10s%-10s\n", "Name", "Age", "Salary");
    printf("%-10s%-10s%-10s\n", "-----", "---", "------");
}

void print_table_row(const char *name, int age, float salary) {
    printf("%-10s%-10d%-10.2f\n", name, age, salary);
}

int main() {
    print_table_header();
    print_table_row("Alice", 30, 50000.00);
    print_table_row("Bob", 25, 45000.00);
    print_table_row("Charlie", 35, 55000.00);

    return 0;
}
3. 错误处理

在处理错误时,可以使用 printf 输出错误信息。

#include <stdio.h>
#include <errno.h>
#include <string.h>

void handle_error(int err_code) {
    if (err_code != 0) {
        printf("Error occurred: %s\n", strerror(err_code));
    }
}

int main() {
    int err_code = ENOENT;  // 文件不存在错误
    handle_error(err_code);

    return 0;
}

printf 是一个功能强大的函数,可以用于多种场景下的格式化输出。通过合理使用格式化符和各种修饰符,可以实现复杂而灵活的输出效果。

下面是一个综合运用 printf 函数的实用案例。这个案例将展示如何在一个简单的图书管理系统中使用 printf 进行格式化的输出,包括输出图书列表、添加新书、查找书籍等功能。

图书管理系统示例

结构定义

首先,定义一个结构体来表示一本书的信息。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_BOOKS 100
#define MAX_TITLE_LENGTH 50
#define MAX_AUTHOR_LENGTH 50

typedef struct {
    int id;
    char title[MAX_TITLE_LENGTH];
    char author[MAX_AUTHOR_LENGTH];
    float price;
} Book;

Book books[MAX_BOOKS];
int book_count = 0;
输出图书列表

定义一个函数来输出所有图书的信息,使用 printf 进行格式化输出。

void print_books() {
    printf("%-5s%-50s%-50s%-10s\n", "ID", "Title", "Author", "Price");
    printf("%-5s%-50s%-50s%-10s\n", "--", "-----", "------", "-----");

    for (int i = 0; i < book_count; ++i) {
        printf("%-5d%-50s%-50s%-10.2f\n",
               books[i].id, books[i].title, books[i].author, books[i].price);
    }
}
添加新书

定义一个函数来添加新的图书信息。

void add_book() {
    if (book_count >= MAX_BOOKS) {
        printf("Book list is full.\n");
        return;
    }

    Book new_book;
    new_book.id = book_count + 1;

    printf("Enter the title of the book: ");
    scanf(" %[^\n]", new_book.title);

    printf("Enter the author of the book: ");
    scanf(" %[^\n]", new_book.author);

    printf("Enter the price of the book: ");
    scanf("%f", &new_book.price);

    books[book_count++] = new_book;
    printf("Book added successfully.\n");
}
查找书籍

定义一个函数来根据书名查找书籍。

void find_book_by_title() {
    char title[MAX_TITLE_LENGTH];
    printf("Enter the title of the book to search: ");
    scanf(" %[^\n]", title);

    int found = 0;
    for (int i = 0; i < book_count; ++i) {
        if (strcmp(books[i].title, title) == 0) {
            printf("Book found:\n");
            printf("%-5d%-50s%-50s%-10.2f\n",
                   books[i].id, books[i].title, books[i].author, books[i].price);
            found = 1;
            break;
        }
    }

    if (!found) {
        printf("Book not found.\n");
    }
}
主函数

定义主函数来提供用户交互界面。

int main() {
    int choice;

    while (1) {
        printf("\nBook Management System\n");
        printf("1. Add a new book\n");
        printf("2. Print all books\n");
        printf("3. Find a book by title\n");
        printf("4. Exit\n");
        printf("Enter your choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                add_book();
                break;
            case 2:
                print_books();
                break;
            case 3:
                find_book_by_title();
                break;
            case 4:
                printf("Exiting...\n");
                return 0;
            default:
                printf("Invalid choice. Please try again.\n");
        }
    }

    return 0;
}

解释

  1. 结构定义:定义了一个 Book 结构体来存储图书的信息,包括 ID、标题、作者和价格。
  2. 输出图书列表print_books 函数使用 printf 输出图书列表,确保各列对齐。
  3. 添加新书add_book 函数允许用户输入新书的信息,并将其添加到图书列表中。
  4. 查找书籍find_book_by_title 函数允许用户输入书名来查找书籍,并输出找到的书籍信息。
  5. 主函数:提供了一个简单的命令行界面,让用户选择操作。

这个示例展示了如何在实际应用中综合使用 printf 函数进行格式化的输出,希望对你有所帮助!

😍😍 海量H5小游戏、微信小游戏、Web casualgame源码😍😍
😍😍试玩地址: https://www.bojiogame.sg😍😍
😍看上哪一款,需要源码的csdn私信我😍

————————————————

​最后我们放松一下眼睛
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

极致人生-010

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

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

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

打赏作者

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

抵扣说明:

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

余额充值