C语言占位符详细介绍

1.printf() 的占位符有许多种类,与 C 语⾔的数据类型相对应。下⾯按照字⺟顺序,颜色标出常⽤的占位符,⽅便大家记忆。

%a :⼗六进制浮点数,字⺟输出为⼩写。
%A :⼗六进制浮点数,字⺟输出为⼤写。
%c :字符。
%d :⼗进制整数。
%e :使⽤科学计数法的浮点数,指数部分的 e 为⼩写。
%E :使⽤科学计数法的浮点数,指数部分的 E 为⼤写。
%i :整数,基本等同于 %d ,除了scanf有一点区别。
%f :⼩数(包含 float 类型和 double 类型)。 float -- %f       double - - %lf
%g :6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的 e
为⼩写。
%G :等同于 %g ,唯⼀的区别是指数部分的 E 为⼤写。
%hd :⼗进制 short int 类型。
%ho :⼋进制 short int 类型。
%hx :⼗六进制 short int 类型。
%hu :unsigned short int 类型。
%ld :⼗进制 long int 类型。
%lo :⼋进制 long int 类型。
%lx :⼗六进制 long int 类型。
%lu :unsigned long int 类型。
%lld :⼗进制 long long int 类型。
%llo :⼋进制 long long int 类型。
%llx :⼗六进制 long long int 类型。
%llu :unsigned long long int 类型。
%Le :科学计数法表⽰的 long double 类型浮点数。
%Lf :long double 类型浮点数。
%n :已输出的字符串数量。该占位符本⾝不输出,只将值存储在指定变量之中。
%o :输出八进制整数
%p 输出指针地址 (⽤来打印地址),注意需要将指针强制转换为  (void *) 避免编译器警告
%s 输出字符串
%u 输出无符号整数 (unsigned int)。
%x 输出十六进制整数
%zd 输出  size_t 类型的值,通常用于表示对象的大小
%% :输出一个百分号,用于输出  % 字符

2.以下就是基本占位符printf的用法

#include 

int main() {

    // %a 和 %A:十六进制浮点数
    float hex_float = 10.125;
    printf("Lowercase hex float: %a\n", hex_float);
    printf("Uppercase hex float: %A\n", hex_float);

    // %c:字符
    char character = 'A';
    printf("Character: %c\n", character);

    // %d 和 %i:十进制整数
    int decimal_int = 123;
    printf("Decimal integer (using %d): %d\n", decimal_int);
    printf("Decimal integer (using %i): %i\n", decimal_int);

    // %e 和 %E:科学计数法的浮点数
    float scientific_float = 1234567.89;
    printf("Scientific float (lowercase e): %e\n", scientific_float);
    printf("Scientific float (uppercase E): %E\n", scientific_float);

    // %f:小数
    float float_num = 3.14159;
    printf("Float number: %f\n", float_num);
    double double_num = 3.141592653589793;
    printf("Double number: %lf\n", double_num);

    // %g 和 %G:根据情况自动选择浮点数表示法
    double auto_float = 12345678.123456;
    printf("Automatic float (lowercase g): %g\n", auto_float);
    printf("Automatic float (uppercase G): %G\n", auto_float);

    // %hd, %ho, %hx, %hu:short int 相关
    short int num = 255;
    printf("Decimal short int: %hd\n", num);  // 输出十进制短整型
    printf("Octal short int: %ho\n", num);   // 输出八进制短整型
    printf("Hexadecimal short int: %hx\n", num);  // 输出十六进制短整型(小写字母)
    printf("Unsigned short int: %hu\n", (unsigned short int)num);  // 输出无符号短整型

    // %ld, %lo, %lx, %lu:long int 相关
    long int l_num = 1234567890;
    printf("Decimal long int: %ld\n", l_num);  // 输出十进制长整型
    printf("Octal long int: %lo\n", l_num);   // 输出八进制长整型
    printf("Hexadecimal long int: %lx\n", l_num);  // 输出十六进制长整型(小写字母)
    printf("Unsigned long int: %lu\n", (unsigned long int)l_num);  // 输出无符号长整型

    // %lld, %llo, %llx, %llu:long long int 相关
    long long int ll_num = 12345678901234567890LL;
    printf("Decimal long long int: %lld\n", ll_num);  // 输出十进制长双整型
    printf("Octal long long int: %llo\n", ll_num);   // 输出八进制长双整型
    printf("Hexadecimal long long int: %llx\n", ll_num);  // 输出十六进制长双整型(小写字母)
     printf("Unsigned long long int: %llu\n", (unsigned long long int)ll_num);  // 输出无符            号长双整型

    // %Le:科学计数法表示的 long double 类型浮点数
    long double long_double_num = 123456789.123456789L;
    printf("Long double scientific: %Le\n", long_double_num);

    // %Lf:long double 类型浮点数
    printf("Long double: %Lf\n", long_double_num);

    // %n:已输出的字符串数量
    int num_chars = 0;
    printf("This is a test string%n", &num_chars);
    printf("Number of characters printed before %n: %d\n", num_chars);

    // %o:八进制整数
    int octal_num = 0123;
    printf("Octal integer: %o\n", octal_num);

    // %p:指针(用来打印地址)
    int *ptr = &decimal_int;
    printf("Pointer address: %p\n", (void *)ptr);

    // %s:字符串
    char str[] = "Hello, World!";
    printf("String: %s\n", str);

    // %u:无符号整数
    unsigned int unsigned_num = 4294967295;
    printf("Unsigned integer: %u\n", unsigned_num);

    // %x:十六进制整数
    int hex_num = 255;
    printf("Hex integer (lowercase): %x\n", hex_num);

    // %zd:size_t 类型
    size_t size = sizeof(int);
    printf("Size of int: %zd\n", size);

    // %%:输出一个百分号
    printf("Percent sign: %%\n");

    return 0;
}

3.在 C 语言中,格式化输出修饰符可以和 printf 等函数中的占位符一起使用,用来控制输出的格式,以下是一些常见的格式化输出修饰符及其使用方法。

一、宽度修饰符

[数字]:指定输出的最小宽度。

  • 对于整数
    int num = 123;
    printf("%5d", num);

    这里的 5 是宽度修饰符,会输出 123,因为 num 的实际长度是 3 位,使用 5 作为宽度修饰符会在左边填充 2 个空格,使输出总宽度为 5 位。

  • 对于浮点数

    float f_num = 3.14;
    printf("%8.2f", f_num);

    这里 8 是总宽度,会输出 3.14,其中 .2 表示保留 2 位小数,总宽度为 8 位,包括数字、小数点和空格,在左边填充 4 个空格。

  • 对于字符串

    char str[] = "hello";
    printf("%10s", str);

    输出 hello,在左边填充 5 个空格,使总宽度为 10 位。

二、精度修饰符

‘.’[数字]:对于不同类型的数据,精度修饰符有不同的含义。

对于浮点数

float f_num = 3.14159;
printf("%.2f", f_num);

这里 .2 表示保留 2 位小数,会输出 3.14。如果和宽度修饰符一起使用:

printf("%8.2f", f_num);

会输出 3.14,先保证总宽度为 8 位,同时保留 2 位小数。

对于字符串

char str[] = "hello world";
printf("%.5s", str);

这里 .5 表示只输出字符串的前 5 个字符,会输出 hello

三、标志修饰符

‘-’:左对齐输出。

对于整数

int num = 123;
printf("%-5d", num);

会输出 123 ,与上面的 %5d 相反,是在右边填充 2 个空格,实现左对齐。

对于浮点数

float f_num = 3.14;
printf("%-8.2f", f_num);

会输出 3.14 ,保留 2 位小数,总宽度为 8 位,在右边填充 4 个空格,实现左对齐。

对于字符串

char str[] = "hello";
printf("%-10s", str);

会输出 hello ,在右边填充 5 个空格,实现左对齐。

四、零填充修饰符

‘0’:使用零而不是空格进行填充。

对于整数

int num = 123;
printf("%05d", num);

会输出 00123,在左边填充 2 个零,总宽度为 5 位。

对于浮点数

float f_num = 3.14;
printf("%08.2f", f_num);

会输出 003.1400,总宽度为 8 位,保留 2 位小数,左边填充 2 个零。

五、符号显示修饰符

‘+’:对于正数显示 + 号。

对于整数

int num = 123;
printf("%+d", num);

会输出 +123,显示正号。对于负数,无论是否使用 + 修饰符,都会显示负号。

对于浮点数

float f_num = 3.14;
printf("%+f", f_num);

会输出 +3.140000,显示正号。

六、空格显示修饰符

(空格):正数前显示一个空格。

  • 对于整数
    int num = 123;
    printf("% d", num);

    会输出 123,正数前面会有一个空格,对于负数,会正常显示负号。

  • 对于浮点数

    float f_num = 3.14;
    printf("% f", f_num);

    会输出 3.140000,正数前面有一个空格。

七、哈希修饰符

‘#’:
  • 对于八进制数
    int oct_num = 10;
    printf("%#o", oct_num);

    会输出 012,会在八进制数前面加 0 前缀。正常使用 %o 输出时,会输出 12

  • 对于十六进制数
    int hex_num = 10;
    printf("%#x", hex_num);

    会输出 0xa,会在十六进制数前面加 0x 前缀。使用 %x 输出时,会输出 a

  • 对于浮点数

    float f_num = 3.0;
    printf("%#g", f_num);

    对于 %g 或 %G,会强制显示小数点,输出 3.00000。对于 %f 会输出 3.000000,效果和不使用 # 相同。

八.动态宽度和精度修饰符(使用 *

  • 可以在 printf 中使用 * 来表示宽度或精度是由一个参数提供的,而不是在格式字符串中直接给出。
  • 用于宽度
    int width = 8;
    int num = 123;
    printf("%*d", width, num);

    这里 width 作为 * 的参数,将 num 以 8 位宽度输出,输出为 123,即左边填充 5 个空格。

  • 用于精度

    int precision = 2;
    float f_num = 3.14159;
    printf("%.*f", precision, f_num);

    这里 precision 作为 * 的参数,将 f_num 保留 2 位小数输出,输出为 3.14

  • 结合前面使用的示例

  • 以下是一个结合多个修饰符的复杂示例:

    long long int large_num = 12345678901234567890LL;
    int width = 20;
    int precision = 5;
    printf("%+#0*.*llx", width, precision, large_num);
  • + 表示正数要显示 + 号。
  • # 表示对于十六进制数要显示 0x 前缀。
  • 0 表示使用零填充。
  • * 表示宽度由 width 变量指定。
  • .* 表示精度由 precision 变量指定。

4. % d 和 % i区别

一、输出功能

%d:通常被认为是用于输出十进制整数的标准占位符。

  • 例如:
    int num = 10;
    printf("The number using %d is: %d", num, num);
  • 这里使用 %d 来输出 num 的值,它会将 num 作为十进制整数显示,输出为 The number using %d is: 10
  • %i
    • 同样用于输出十进制整数,但它有一个额外的特性,即可以自动识别输入的进制。
    • 虽然在 printf 函数中 %i 通常和 %d 一样,仅输出十进制整数,但是当与 scanf 函数结合使用时,%i 可以根据输入数字的前缀来识别不同的进制。
    • 例如:
      int num;
      scanf("%i", &num);

      如果用户输入 010num 将被存储为八进制数对应的十进制值,即 8;如果输入 0x10num 将被存储为十六进制数对应的十进制值,即 16;如果输入 10,则会将其存储为十进制数 10。

二、输入功能

%d:当使用 scanf 函数时,%d 只会将输入解释为十进制整数。

  • 例如:
    int num;
    scanf("%d", &num);
  • 无论用户输入的是 10010 还是 0x10,它都会将输入视为十进制数,尝试将其存储为十进制整数。如果输入 010num 会存储为十进制数 10,而不是八进制数对应的十进制值 8;输入 0x10 会导致存储错误或未预期的结果,因为 %d 不识别十六进制前缀。
  • %i
    • 在 scanf 中,%i 可以根据输入的前缀自动识别进制。
  • 例如:
    int num;
    scanf("%i", &num);
  • 输入 010 时,num 将存储为八进制数 010 的十进制等效值,即 8。
  • 输入 0x10 时,num 将存储为十六进制数 0x10 的十进制等效值,即 16。
  • 输入 10 时,num 将存储为十进制数 10。
  • 总的来说,对于 printf 函数,%d 和 %i 的使用几乎没有区别,都能正确输出有符号的十进制整数;但对于 scanf 函数,%i 更灵活,可根据输入数字的前缀识别进制,而 %d 仅将输入解释为十进制整数。在日常编程中,对于 printf 函数,可根据个人习惯使用 %d 或 %i 输出十进制整数;对于 scanf 函数,如果需要自动识别输入数字的进制,应使用 %i,否则使用 %d 明确表示仅接受十进制输入。

5.scanf() 常⽤的占位符与 printf() 的占位符基本一致

如下:

%c :字符。
%d :整数。
%f float 类型浮点数。
%lf double 类型浮点数。
%Lf long double 类型浮点数。
%s :字符串。
%[ ] :在⽅括号中指定⼀组匹配的字符(⽐如 %[0-9] ),遇到不在集合之中的字符,匹配将会
停⽌。
1.上⾯所有占位符之中,除了 %c 以外,都会⾃动忽略起⾸的空⽩字符 %c 不忽略空⽩字符 ,总是返 回当前第⼀个字符,⽆论该字符是否为空格。
2.如果要强制跳过字符前的空⽩字符,可以写成 scanf(" 空格 %c", &ch) ,即 %c 前加上⼀个空格,表 跳过零个或多个空⽩字符
3.下⾯要特别说⼀下占位符 %s ,它其实不能简单地等同于字符串。它的规则是,从当前第⼀个⾮空⽩ 字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。
4.因为 %s 不会包含空⽩字符,所以⽆法⽤来读取多个单词,除⾮多个 %s ⼀起使⽤。这也意味着, scanf() 不适合读取可能包含空格的字符串,⽐如书名或歌曲名。另外, scanf() 遇到 %s 占位 符,会在字符串变量末尾存储⼀个 空字符 \0
5.scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果。为了防⽌这种情况,使⽤ %s 占位符时,应该指定 读⼊字符串的最⻓⻓度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表⽰读取字符串的最⼤⻓度,后 ⾯的字符将被丢弃。
#include 
int main()
{
 char name[15];
 scanf("%14s", name);
 
 return 0;
上⾯⽰例中, name 是⼀个⻓度为15的字符数组, scanf() 的占位符 %14s 表⽰最多读取⽤⼾输⼊
的14个字符,后⾯的字符将被丢弃,这样就不会有数组溢出的⻛险了。

6.赋值忽略符

有的时候,⽤⼾的输⼊可能不符合预定的格式。
#include 
int main()
{
 int year = 0;
 int month = 0;
 int day = 0;
 scanf("%d-%d-%d", &year, &month, &day);
 printf("%d %d %d\n", year, month, day);
 return 0;
}
上⾯⽰例中,如果⽤⼾输⼊ 2020-01-01 ,就会正确解读出年、⽉、⽇。问题是⽤⼾可能输⼊其他
格式,⽐如 2020/01/01 ,这种情况下, scanf() 解析数据就会失败。
为了避免这种情况, scanf() 提供了⼀个赋值忽略符(assignment suppression character) *
只要把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃。
#include 
int main()
{
 int year = 0;
 int month = 0;
 int day = 0;
 scanf("%d%*c%d%*c%d", &year, &month, &day);
 return 0;
}
上⾯⽰例中, %*c 就是在占位符的百分号后⾯,加⼊了赋值忽略符 * ,表⽰这个占位符没有对应的变量,解读后不必返回。

7.在 C 语言的 printf 和 scanf 函数中,%[] 是一种比较特殊的格式化字符串,主要用于输入或输出一系列字符。以下是关于它的一些使用情况:

一、在 scanf 中的使用

%[] 可以用来读取一个字符集合。

  • 读取特定字符集
    char str[100];
    scanf("%[abc]", str);
  • 这个 scanf 调用会读取输入的字符,只要输入的字符是 ab 或 c 中的任何一个,就会存储到 str 中,直到遇到不在该集合中的字符为止。例如,如果输入是 abcaa,那么 str 将存储 abcaa。如果输入是 abcdefstr 只会存储 abc,因为 d 不在 abc 集合中。
  • 读取范围
    char str[100];
    scanf("%[a-z]", str);
  • 这将读取输入的所有小写字母,并存储到 str 中,直到遇到不在 a-z 范围的字符。例如,如果输入是 abcdefg123str 将存储 abcdefg
  • 取反操作
    char str[100];
    scanf("%[^a-z]", str);
  • 这里的 ^ 表示取反,%[^a-z] 会读取所有不是小写字母的字符,存储到 str 中。如果输入是 123abcstr 将存储 123

二、在 printf 中的使用(较少使用)

在 printf 中使用 %[] 不太常见,但可以通过自定义函数和 %s 占位符结合使用,来实现对字符集合的格式化输出。

#include 
#include 

void print_custom(const char *str) {
    int len = strlen(str);
    for (int i = 0; i < len; i++) {
        if (str[i] >= 'a' && str[i] <= 'z') {
            putchar(str[i]);
        }
    }
}

int main() {
    char str[] = "Hello123World";
    printf("Lowercase letters: ");
    print_custom(str);
    return 0;
}

在这个例子中,print_custom 函数只打印输入字符串中的小写字母。如果想在 printf 中使用 %[] 类似的功能,可能需要自定义这样的函数,因为 printf 本身不直接支持 %[] 进行输出筛选。

三、注意事项

scanf 中的 %[] 注意事项

  • 可能导致缓冲区溢出:如果输入的字符数量超过了存储数组的大小,可能会导致缓冲区溢出。为了避免这种情况,可以使用 %[^\n] 并结合 fgets 来控制输入长度。例如:
    char str[100];
    fgets(str, sizeof(str), stdin);
  • 这会将输入存储在 str 中,最多存储 99 个字符,最后一个留给 \0 终止符。
  • 不会自动添加字符串终止符:scanf 函数在使用 %[] 时不会自动在输入字符串末尾添加 \0 终止符,除非输入结束或者遇到不符合集合的字符。因此,确保存储数组有足够的空间,并手动添加终止符(如果需要)。

四、高级用法

结合 * 进行抑制赋值

char str[100];
int num;
scanf("%*d %[a-z]", str);
  • 这个 scanf 调用会跳过一个整数(%*d 会读取一个整数,但不会存储它),然后将接下来输入的小写字母存储到 str 中。
  • 总之,%[] 提供了一种方便的方式来控制字符的输入和输出,尤其在需要筛选特定字符集合时非常有用,但使用时要注意可能出现的缓冲区溢出问题和终止符的添加,以确保程序的安全性和正确性。

你可能感兴趣的:(C语言基础,c语言,开发语言)