我试图使用行长度包装一行,并一次打印一行(行长度),而不是打印整行作为一个块。我认为在每行长度处添加'n'字符就可以了,于是编写了以下代码:
void wrap(char *tok, int len)
{
int i, h;
char *ss = tok;
for (h = linelen; h < (len + 1); (h + linelen))
{
ss[h] = 'n';
printf("%dn", h);
h += linelen;
}
char *token = strtok(ss, "n");
while (token)
{
printf("%sn", token);
token = strtok(NULL, "n");
}
}
但是这段代码似乎不起作用。还有什么方法可以实现换行?
偷自这篇文章:是否有可能只打印出c字符串的某一部分,而不制作单独的子字符串?
#include <stdio.h>
#include <string.h>
int main(void) {
char *str = "helo world";
int total_len = strlen(str);
int single_len = 3;
for (int i = 0; i < total_len; i += single_len) {
/* print at most first three characters (safe) */
printf("%.*sn", single_len, str + i);
}
return 0;
}
您不需要更改原始字符串,只需要在必要时打印出额外的换行符:
void wrap(char *str, int len, int linelen) {
int i;
for (i = 0; i < len; ++i) {
printf("%c", str[i]);
if (i > 0 && i % linelen == 0) {
printf("n");
}
}
}
如果您的原始字符串中可能有换行符,您可以跟踪当前行的长度,以便下一行被正确换行:
void wrap(char *str, int len, int linelen) {
int i, currlen;
for (i = 0, currlen = 0; i < len; ++i, ++currlen) {
printf("%c", str[i]);
if (str[i] == 'n') {
currlen = 0;
}
if (currlen > 0 && currlen % linelen == 0) {
printf("n");
}
}
}
你的程序似乎想把tok
分解成多个linelen
字节,但是你似乎并不关心你要替换什么字符来实现这一点。这使得您的wrap
例程在原始输入中丢失信息。然后调用strtok
一次打印一个令牌,但是损害已经造成了。
相反,我认为您应该重构代码,以便使用strtok
来查找令牌,并计算打印当前令牌是否会将您置于linelen
之上。如果可以,则打印换行,打印令牌,并根据刚刚打印的令牌的长度计算当前运行的行长度。在同一行上打印的每个令牌都将增加运行行的长度。
void wrap(char *tok, int linelen)
{
int len = 0;
char *ss = tok;
char *token = strtok(ss, " tn");
while (token) {
int tokenlen = strlen(token);
if (len && (len + tokenlen + 1 > linelen)) {
puts("");
len = 0;
}
if (tokenlen) {
printf("%s%s", len ? " " : "", token);
len += 1 + tokenlen;
}
token = strtok(0, " tn");
}
if (len) puts("");
}
你最初的实现没有考虑到如何处理制表符。如果将所有线性空白字符添加到strtok
分隔符中,那么所有制表符将被视为令牌分隔符,并且在换行输入时将被丢弃。正确处理制表符会使行长计算复杂化,因为制表符会导致行长跳转到下一个制表位。