是否可以仅使用printf函数来屏蔽字符串?
存在于char数组中的静态字符串。用户将输入一个数字,该数字是用户想要打印的字符数。假设字符串是14个字符并且用户输入20,是否可以屏蔽字符串,以便仅使用printf函数用'*'替换最后6个字符?
答案 0 :(得分:4)
如果你满足于空间而不是想要星号,那么你可以直接进行。
由于你需要星号,答案是“不是真的” - 至少,如果所需的填充量可以任意大。如果填充量永远不会超过N个字节,您可以创建一个N个星号的字符串并解决它。
如果源字符串长于用户指定的N,则您的问题未指定会发生什么。此实现假定字符串的前N个字符应打印而不进行屏蔽。
#include <stdio.h>
#include <string.h>
/* For inclusion in a header file */
extern void mask_string(const char *str, int n, char pad);
static inline int min(int x, int y) { return (x < y) ? x : y; }
static inline int max(int x, int y) { return (x > y) ? x : y; }
void mask_string(const char *str, int n, char pad)
{
char buffer[n+1];
memset(buffer, pad, n);
buffer[n] = '\0';
int len1 = min(strlen(str), n);
int len2 = max(n - (int)strlen(str), 0);
printf("%.*s%.*s", len1, str, len2, buffer);
}
/* Test code */
static void test_mask_string(const char *data, int i)
{
printf("%2d: [", i);
mask_string(data, i, '*');
putchar(']');
putchar('\n');
}
int main(void)
{
char data[] = "suppose the string";
for (int i = 11; i < 24; i++)
test_mask_string(data, i);
return 0;
}
使用GCC 6.2.0在macOS Sierra 10.12.3上测试。
11: [suppose the]
12: [suppose the ]
13: [suppose the s]
14: [suppose the st]
15: [suppose the str]
16: [suppose the stri]
17: [suppose the strin]
18: [suppose the string]
19: [suppose the string*]
20: [suppose the string**]
21: [suppose the string***]
22: [suppose the string****]
23: [suppose the string*****]
printf()
显示的代码有5行代码加上两行内联(单行)函数。我宁愿不消除这些功能,但只要你总是想要星号而且不要超过(比方说)其中的80个,那么你可以将其减少到:
#include <stdio.h>
#include <string.h>
/* For inclusion in a header file */
extern void mask_string(const char *str, int n);
static inline int min(int x, int y) { return (x < y) ? x : y; }
static inline int max(int x, int y) { return (x > y) ? x : y; }
void mask_string(const char *str, int n)
{
printf("%.*s%.*s", min(strlen(str), n), str,
max(n - (int)strlen(str), 0),
"****************************************"
"****************************************");
}
/* Test code */
static void test_mask_string(const char *data, int i)
{
printf("%2d: [", i);
mask_string(data, i);
putchar(']');
putchar('\n');
}
int main(void)
{
char data[] = "suppose the string";
for (int i = 11; i < 24; i++)
test_mask_string(data, i);
return 0;
}
此测试输出与之前相同。
注意使用字符串文字连接。如果我要走这条路,我很想添加一个断言来确保代码没有请求太多的星号:
assert(max(n - strlen(str), 0) <= 80);
甚至使用宏:
#define STARS "****************************************" \
"****************************************"
和
assert(max(n - strlen(str), 0) < sizeof(STARS));
printf("%.*s%.*s", min(strlen(str), n), str,
max(n - strlen(str), 0), STARS);
显然,如果你坚持不使用内联函数,你可以在参数列表中将它们写出printf()
。我认为这不会使代码更清晰。