> 文章列表 > 【C/C++】format 格式化方法使用技巧(代码实例,皆可运行)

【C/C++】format 格式化方法使用技巧(代码实例,皆可运行)

【C/C++】format 格式化方法使用技巧(代码实例,皆可运行)

printf

当使用__attribute__((format(printf, ...)))语法时,可以使用printf函数作为一个例子来说明它的作用。下面是一个简单的示例代码:

#include <stdio.h>void my_printf(const char *format, ...) __attribute__((format(printf, 1, 2)));void my_printf(const char *format, ...)
{va_list args;va_start(args, format);vprintf(format, args);va_end(args);
}int main()
{int num = 10;const char *str = "hello";my_printf("num = %d, str = %s\\n", num, str);return 0;
}

在这个示例代码中,my_printf函数使用了__attribute__((format(printf, 1, 2)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。

main函数中,我们调用了my_printf函数,并传递了一个格式化字符串和两个参数。由于我们使用了__attribute__((format(printf, 1, 2)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(printf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

sprintf

好的,下面再举一个例子。假设我们有一个函数my_sprintf,它的作用是将格式化字符串和参数写入一个缓冲区中。我们可以使用__attribute__((format(printf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>void my_sprintf(char *buf, const char *format, ...) __attribute__((format(printf, 2, 3)));void my_sprintf(char *buf, const char *format, ...)
{va_list args;va_start(args, format);vsprintf(buf, format, args);va_end(args);
}int main()
{char buf[100];int num = 10;const char *str = "hello";my_sprintf(buf, "num = %d, str = %s\\n", num, str);printf("%s", buf);return 0;
}

在这个示例代码中,my_sprintf函数使用了__attribute__((format(printf, 2, 3)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。

main函数中,我们调用了my_sprintf函数,并传递了一个缓冲区、一个格式化字符串和两个参数。由于我们使用了__attribute__((format(printf, 2, 3)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(printf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

snprintf

好的,下面再举一个例子。假设我们有一个函数my_snprintf,它的作用是将格式化字符串和参数写入一个缓冲区中,并限制写入的字符数。我们可以使用__attribute__((format(printf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>void my_snprintf(char *buf, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4)));void my_snprintf(char *buf, size_t size, const char *format, ...)
{va_list args;va_start(args, format);vsnprintf(buf, size, format, args);va_end(args);
}int main()
{char buf[100];int num = 10;const char *str = "hello";my_snprintf(buf, sizeof(buf), "num = %d, str = %s\\n", num, str);printf("%s", buf);return 0;
}

在这个示例代码中,my_snprintf函数使用了__attribute__((format(printf, 3, 4)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。

main函数中,我们调用了my_snprintf函数,并传递了一个缓冲区、缓冲区大小、一个格式化字符串和两个参数。由于我们使用了__attribute__((format(printf, 3, 4)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(printf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

fprintf

好的,下面再举一个例子。假设我们有一个函数my_fprintf,它的作用是将格式化字符串和参数写入一个文件中。我们可以使用__attribute__((format(printf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>void my_fprintf(FILE *fp, const char *format, ...) __attribute__((format(printf, 2, 3)));void my_fprintf(FILE *fp, const char *format, ...)
{va_list args;va_start(args, format);vfprintf(fp, format, args);va_end(args);
}int main()
{int num = 10;const char *str = "hello";FILE *fp = fopen("output.txt", "w");my_fprintf(fp, "num = %d, str = %s\\n", num, str);fclose(fp);return 0;
}

在这个示例代码中,my_fprintf函数使用了__attribute__((format(printf, 2, 3)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。

main函数中,我们调用了my_fprintf函数,并传递了一个文件指针、一个格式化字符串和两个参数。由于我们使用了__attribute__((format(printf, 2, 3)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(printf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

vprintf

好的,下面再举一个例子。假设我们有一个函数my_vprintf,它的作用是将格式化字符串和参数写入标准输出中。我们可以使用__attribute__((format(printf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>void my_vprintf(const char *format, va_list args) __attribute__((format(printf, 1, 0)));void my_vprintf(const char *format, va_list args)
{vprintf(format, args);
}void my_printf(const char *format, ...) 
{va_list args;va_start(args, format);my_vprintf(format, args);va_end(args);
}int main()
{int num = 10;const char *str = "hello";my_printf("num = %d, str = %s\\n", num, str);return 0;
}

在这个示例代码中,我们定义了两个函数my_vprintfmy_printfmy_vprintf函数使用了__attribute__((format(printf, 1, 0)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。my_printf函数则是一个包装函数,它调用了my_vprintf函数,并使用可变参数列表来传递参数。

main函数中,我们调用了my_printf函数,并传递了一个格式化字符串和两个参数。由于我们使用了__attribute__((format(printf, 1, 0)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(printf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

fopen

好的,下面再举一个例子。假设我们有一个函数my_fopen,它的作用是打开一个文件,并返回一个文件指针。我们可以使用__attribute__((format(printf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>FILE *my_fopen(const char *format, ...) __attribute__((format(printf, 1, 2)));FILE *my_fopen(const char *format, ...)
{char filename[100];va_list args;va_start(args, format);vsnprintf(filename, sizeof(filename), format, args);va_end(args);return fopen(filename, "w");
}int main()
{int num = 10;const char *str = "hello";FILE *fp = my_fopen("output_%d_%s.txt", num, str);fprintf(fp, "This is a test\\n");fclose(fp);return 0;
}

在这个示例代码中,my_fopen函数使用了__attribute__((format(printf, 1, 2)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。在函数内部,我们使用vsnprintf函数来将格式化字符串和参数转换成一个文件名,并使用fopen函数打开这个文件。

main函数中,我们调用了my_fopen函数,并传递了一个格式化字符串和两个参数。由于我们使用了__attribute__((format(printf, 1, 2)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(printf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

sscanf

好的,下面再举一个例子。假设我们有一个函数my_sscanf,它的作用是从一个字符串中读取格式化数据。我们可以使用__attribute__((format(scanf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>int my_sscanf(const char *str, const char *format, ...) __attribute__((format(scanf, 2, 3)));int my_sscanf(const char *str, const char *format, ...)
{va_list args;va_start(args, format);int ret = vsscanf(str, format, args);va_end(args);return ret;
}int main()
{int num;char str[100];const char *input = "10 hello";int ret = my_sscanf(input, "%d %s", &num, str);printf("ret = %d, num = %d, str = %s\\n", ret, num, str);return 0;
}

在这个示例代码中,my_sscanf函数使用了__attribute__((format(scanf, 2, 3)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。在函数内部,我们使用vsscanf函数来从字符串中读取格式化数据。

main函数中,我们调用了my_sscanf函数,并传递了一个字符串和一个格式化字符串。由于我们使用了__attribute__((format(scanf, 2, 3)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(scanf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

fscanf

好的,下面再举一个例子。假设我们有一个函数my_fscanf,它的作用是从一个文件中读取格式化数据。我们可以使用__attribute__((format(scanf, ...)))语法来指定函数参数的格式,从而帮助编译器检查函数调用时传递的参数是否符合格式化字符串的要求。下面是一个示例代码:

#include <stdio.h>
#include <stdarg.h>int my_fscanf(FILE *fp, const char *format, ...) __attribute__((format(scanf, 2, 3)));int my_fscanf(FILE *fp, const char *format, ...)
{va_list args;va_start(args, format);int ret = vfscanf(fp, format, args);va_end(args);return ret;
}int main()
{int num;char str[100];FILE *fp = fopen("input.txt", "r");int ret = my_fscanf(fp, "%d %s", &num, str);printf("ret = %d, num = %d, str = %s\\n", ret, num, str);fclose(fp);return 0;
}

在这个示例代码中,my_fscanf函数使用了__attribute__((format(scanf, 2, 3)))语法来指定函数参数的格式。这样,编译器就可以检查函数调用时传递的参数是否符合格式化字符串的要求。在函数内部,我们使用vfscanf函数来从文件中读取格式化数据。

main函数中,我们调用了my_fscanf函数,并传递了一个文件指针和一个格式化字符串。由于我们使用了__attribute__((format(scanf, 2, 3)))语法,编译器会检查这个函数调用是否符合格式化字符串的要求。如果我们在格式化字符串中使用了错误的格式化符号,例如%f,编译器就会给出一个警告或错误。

需要注意的是,__attribute__((format(scanf, ...)))语法只在GCC编译器中有效,其他编译器可能不支持这个语法。因此,在编写跨平台代码时,需要谨慎使用这个语法。

生活知识