我知道我們可以通過printf()定義其最小大小來顯示給定的字串。這可以通過這種方式完成,例如:
printf(" s",str);
但是,使用這段代碼,str將顯示最少 20 個字符,如果原始字串少于 20 個字符,則函式以左側空格完成。
有沒有辦法使用除空格以外的其他字符來做到這一點?
uj5u.com熱心網友回復:
如果原始字串少于 20 個字符,則函式以左側空格結束。
有沒有辦法使用除空格以外的其他字符來做到這一點?
不,不是printf()一個人。檔案(例如https://man7.org/linux/man-pages/man3/printf.3.html)明確指出,如果轉換后的值的字符數少于欄位寬度,則該欄位用空格填充在左側或右側,視情況而定。
與許多其他來源相比,語言規范實際上在這一點上不太清楚:
如果轉換后的值的字符數少于欄位寬度,則在欄位寬度的左側(或右側,如果已給出稍后描述的左側調整標志)用空格(默認情況下)填充。
人們可能會采用“默認情況”來表示可以以某種方式指定填充字符的另一種選擇,但仔細閱讀規范并沒有發現任何這樣的選項。那么,最好的解釋是“默認”是指填充的位置(左),而不是填充字符。大多數其他版本的檔案只是省略了“默認”位,大概是因為它比有用更令人困惑。
uj5u.com熱心網友回復:
不,該printf系列無法使用任意填充字符。
一種可能性是使用memset填充字符預填充緩沖區,然后使用sprintf將結果列印到其中的一部分:
char *string = "Hello, world!";
int stringlen = strlen(string);
int fieldlen = 20;
char padchar = '#';
if(stringlen <= fieldlen) {
char buf[fieldlen 1];
memset(buf, padchar, fieldlen);
sprintf(&buf[fieldlen - stringlen], "%s", string);
printf("%s\n", buf);
}
uj5u.com熱心網友回復:
有沒有辦法使用除空格以外的其他字符來做到這一點?
是的,如果該填充字符是'0'并且至少需要 1 個。使用算術填充。
#define N 20
size_t len = strlen(str);
assert(len < N);
// v------- Pad with 0
// |v------ Obtain width from arguments
printf("%0*d%s",(int)(N-len), 0, str);
我們可以為備用填充添加代碼。適合len[0...N]。
size_t len = strlen(str);
#define N 20
assert(len <= N);
char pad[N 1];
memset(pad, pad_char, N-len);
pad[len] = 0;
printf("%s%s",pad, str);
uj5u.com熱心網友回復:
我可能會這樣解決
/* ... mystery content removed ... */
int main(int argc, char **argv)
{
for (int i = 1; i < argc; i )
printf("Left: " PAD_STAR_FMT "\n", PAD_STAR_ARG(argv[i], 20));
for (int i = 1; i < argc; i )
printf("Rite: " PADR_STAR_FMT "\n", PADR_STAR_ARG(argv[i], 20));
return 0;
}
跑:
$ ./pad The quick brown fox "" "supercalifragilisticexpeali"
Left: *****************The
Left: ***************quick
Left: ***************brown
Left: *****************fox
Left: ********************
Left: supercalifragilistic
Rite: The*****************
Rite: quick***************
Rite: brown***************
Rite: fox*****************
Rite: ********************
Rite: supercalifragilistic
PAD_STAR_FMTand宏擴展為一個字串文字,PADR_STAR_FMT它為星號填充的列印作業提供轉換說明符。
PAD_STAR_ARG和PADR_STAR_ARG宏擴展為此轉換說明符的引數。
如您所見,我們將欄位寬度 20 編碼到引數空間而不是格式字串中,因為我們需要能夠使用它進行一些計算,而在格式字串語言中這是不可能的。
在后臺,使用了兩個轉換說明符,并且ARG宏為它們生成了幾個引數(不幸的是,對它們自己的引數進行了多次評估)。
這種方法的好處是我們可以將其改造成一些已經使用的現有代碼,printf而不會干擾該代碼。如果代碼只printf呼叫一次,我們可以保持這種狀態。
我建議清理代碼并使用更好的,也許更短的名稱。我的 if 陳述句也可以是三元運算子。
完整的程式如下:
#include <stdio.h>
#include <string.h>
#include <assert.h>
static char stars[] = {
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
"**************************************************"
};
#define PAD_STAR_FMT "%.*s%.*s"
#define PAD_STAR_ARG(S, N) pad_nstars(S, N), stars, pad_nchars(S, N), (S)
#define PADR_STAR_FMT "%.*s%.*s"
#define PADR_STAR_ARG(S, N) pad_nchars(S, N), (S), pad_nstars(S, N), stars
static int pad_nstars(const char *s, size_t width)
{
assert (width < sizeof stars);
size_t len = strlen(s);
if (len > width)
return 0;
return (int) (width - len);
}
static int pad_nchars(const char *s, size_t width)
{
size_t len = strlen(s);
if (len > width)
return width;
return len;
}
int main(int argc, char **argv)
{
for (int i = 1; i < argc; i ) {
printf("Left: " PAD_STAR_FMT "\n", PAD_STAR_ARG(argv[i], 20));
}
for (int i = 1; i < argc; i ) {
printf("Rite: " PADR_STAR_FMT "\n", PADR_STAR_ARG(argv[i], 20));
}
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507330.html
上一篇:不同節點的處理器之間的MPI通信
下一篇:將空位元組放在C陣列的末尾
