如何用空格 printf() 填充值?

Posted

技术标签:

【中文标题】如何用空格 printf() 填充值?【英文标题】:How to pad value with spaces printf()? 【发布时间】:2021-09-19 09:50:56 【问题描述】:

我有一个FFFFAAAACCCC0000 的值,我想使用带有空格的printf() 来打印FFFF AAAA CCCC 0000(基本上是每组4 个字符的间距),但我不知道如何操作,也不知道如何使用@987654325 @也不是write()

我的代码(正在进行中):

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

void    print(char *str)

    int i;
    char a;

    i = 0;
    while (str[i] != '\0')
    
        a = str[i];
        write(1, &a, 1);
        i++;
    


void    print_add(void *addr)

    printf("%016p: ", addr);


void print_hex_value(void *addr)

    printf("%x ", addr);


void print_lit_value(char *addr)

    int i;

    i = 0;
    while (i < 16)
    
        (addr[i] < 32 || addr[i] > 126) ? printf(".") : print(addr[i]);
        i++;
    


void    *ft_print_memory(void *addr, unsigned int size)

    int i;

    i = 0;
    while (i < size)
    
        char buff[17];
        memcpy( buff, &buff[0], 16);
        buff[17] = '\0';
        print_add(addr + i);
        print_hex_value(buff);
        print_lit_value(buff);
        i += 16;
    
    return (addr);  


int main(void)

    char *str = "Salut les aminches c'est cool show mem on fait de truc terrible\1\2";
    ft_print_memory(str, sizeof(str));

目的是打印如下内容:

$> ./ft_print_memory
000000010a161f40: 426f 6e6a 6f75 7220 6c65 7320 616d 696e Bonjour les amin
000000010a161f50: 6368 6573 090a 0963 2020 6573 7420 666f ches...c est fo
000000010a161f60: 7509 746f 7574 0963 6520 7175 206f 6e20 u.tout.ce qu on
000000010a161f70: 7065 7574 2066 6169 7265 2061 7665 6309 peut faire avec.
000000010a161f80: 0a09 7072 696e 745f 6d65 6d6f 7279 0a0a ..print_memory..
000000010a161f90: 0a09 6c6f 6c2e 6c6f 6c0a 2000..lol.lol. .

我在多个部分都遇到了问题,但我决定做一个我想要的通用版本,然后修复所有的废话

【问题讨论】:

真的不太清楚你的意思。您只是想在每组 4 个字符之间插入一个空格,还是想在匹配的组之间插入一个空格? @WilliamPursell 在每组 4 个字符之间 输入是什么?是字符串还是数字?如果您显示不带空格的打印代码会有所帮助。 请提供变量的complete minimal reproducible example,它们的类型以及您当前如何打印它。 memcpy( buff, &amp;buff[0], 16); ??? 【参考方案1】:

与 William Pursell 发布的解决方案的逻辑相同,但具有通用性。

char *insert_chars(char *str, int freq, char ch) 
    int result_length = (strlen(str) / freq) * (freq + 1) + 1;
    char *result = malloc(sizeof(char) * result_length);
    
    int j = 0;
    for (int i = 0; i < length || str[i] != '\0'; i++) 
        result[j++] = str[i];
        
        if ((i + 1) % freq == 0) 
            result[j++] = ch;
        
    
    
    result[j] = '\0';
    
    return result;

【讨论】:

【参考方案2】:
#include <stdio.h>
#include <string.h>

int
main(int argc, char **argv)

        char *s = argc > 1 ? argv[1] : "FFFFAAAACCCC0000";
        char *t = s;
        /* Insert space between every 4th char */
        while( *t )
                putchar(*t++);
                if( t > s && (t - s) % 4 == 0 )
                        putchar(' ');
                
        
        putchar('\n');
        /* Insert space between every group of same chars */
        for( t = s; *t; t++ )
                putchar(*t);
                if( t[0] != t[1] )
                        putchar(' ');
                
        
        putchar('\n');

【讨论】:

我对指针字符串和数组仍然很陌生,为什么你在 while 循环和 putchar 内部做 *t 不回答提出的问题。 @zwol 它确实在问题被编辑之前回答了问题! 我真的很困惑为什么 everyone 将 OP 的“value of [64-bit hexadecimal number]”解释为字符串,而他们从来没有在原文中或编辑后说过任何此类事情。【参考方案3】:

假设您的输入是一个字符串。 此解决方案最大限度地减少了对 I/O 函数的调用次数:

char *s = "......";

int len = strlen(s);
while(len > 4) 
    char slice[6];
    strncpy(slice, s, 4);
    slice[4] = ' ';
    slice[5] = 0;
    fputs(slice, stdout);
    s += 4;
    len -= 4;

fputs(s, stdout);

【讨论】:

如果 size 是 4 的倍数,则不会打印最后一个块 @MM 你可能忽略了最后一行。【参考方案4】:

您可以使用printf() 精度说明符。来自printf()

(可选)。后跟整数或 *,或者两者都不指定转换的精度。在使用 * 的情况下,精度由 int 类型的附加参数指定,该参数出现在要转换的参数之前,但在提供最小字段宽度的参数之后(如果提供的话)。如果此参数的值为负,则将其忽略。如果既没有使用数字也没有使用 *,则精度为零。有关精度的确切影响,请参见下表。

对于s 转换说明符:

s

写入一个字符串 参数必须是指向字符数组初始元素的指针。 Precision 指定要写入的最大字节数。 如果未指定 Precision,则写入每个字节,直到第一个空终止符,但不包括第一个空终止符。如果使用 l 说明符,则参数必须是指向 wchar_t 数组的初始元素的指针,该数组将被转换为 char 数组,就像调用具有零初始化转换状态的 wcrtomb 一样。

你可以这样做:

#include <stdio.h>

int main (void) 
    char *s = "FFFFAAAACCCC0000";
    int nc = 4;

    printf ("%.*s %.*s %.*s %.*s\n", nc, s + (nc * 0), nc, s + (nc * 1), nc, s + (nc * 2), nc, s + (nc * 3));

    // simplified version
    printf ("%.4s %.4s %.4s %.4s\n", s, s + nc, s + (nc * 2), s + (nc * 3));

    return 0;

输出:

 % ./a.out 
FFFF AAAA CCCC 0000
FFFF AAAA CCCC 0000

您还可以使用字段宽度说明符控制一行中打印的字符串之间的空格数。从上面相同的链接:

(可选)整数值或*,指定最小字段宽度。如果需要,结果会用空格字符(默认情况下)填充,右对齐时在左侧,如果左对齐,则在右侧。在使用 * 的情况下,宽度由 int 类型的附加参数指定,该参数出现在要转换的参数之前,如果提供了精度,则参数提供精度。如果参数的值为负,则结果是指定的 - 标志和正的字段宽度。 (注意:这是最小宽度:该值永远不会被截断。)

#include <stdio.h>

int main (void)

        char *s = "FFFFAAAACCCC0000";
        int nc = 4;

        printf ("%.*s %.*s %.*s %.*s\n", nc, s + (nc * 0), nc, s + (nc * 1), nc, s + (nc * 2), nc, s + (nc * 3));

        // simplified version
        printf ("%.4s %.4s %.4s %.4s\n", s, s + nc, s + (nc * 2), s + (nc * 3));

        // Use field width for spaces between the strings

        int space_count = 1 + nc; // for 1 space
        printf ("%.4s%*.4s%*.4s%*.4s\n", s, space_count, s + nc, space_count, s + (nc * 2), space_count, s + (nc * 3));

        space_count = 4 + nc;   // for 4 spaces
        printf ("%.4s%*.4s%*.4s%*.4s\n", s, space_count, s + nc, space_count, s + (nc * 2), space_count, s + (nc * 3));
    
        return 0;

输出:

% ./a.out 
FFFF AAAA CCCC 0000
FFFF AAAA CCCC 0000
FFFF AAAA CCCC 0000
FFFF    AAAA    CCCC    0000

以上代码基于字符串大小为16 个字符(不包括空字符)的假设。你必须照顾小字符串。

【讨论】:

以上是关于如何用空格 printf() 填充值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在C语言中用printf()输出某个值的地址?

如何在C语言中用printf()输出某个值的地址?

如何用c语言printf输出bmp图片的像素信息。

如何用MFC做一个进度条

C语言用如何用scanf输入带有空格的字符串

如何用空格填充 QString?