不使用printf

时间:2018-06-14 20:23:32

标签: c printf

我目前正在使用printf("'%.*s'\n", length, start);打印字符串,其中startconst char*,长度为int

正在打印的字符串有时会包含换行格式\n,这会影响格式,是否可以将它们替换为打印输出中的字符\n,而不是\n个字符。 如果没有,你能帮助一个替代角色的功能吗?

该字符串是malloc'd字符串,其中包含来自不同指针的其他引用,因此无法更改。

编辑:我已经编写了以下代码,我认为我需要它来执行

static void printStr(const char* start, int length) {
  char* buffer = malloc(length * sizeof(char));
  int processedCount = 0;
  for(int i = 0; i < length; i++) {
    char c = start[i];
    if(c == '\n') {
      printf("%.*s\\n", processedCount, buffer);
      processedCount = 0;
    } else {
      buffer[processedCount] = c;
      processedCount++;
    }
  }
  printf("%.*s", processedCount, buffer);
  free(buffer);
}

4 个答案:

答案 0 :(得分:4)

无需分配内存来处理字符串。简单地说,迭代原始的并根据需要打印字符。例如:

#include <stdio.h>

void print(const char * str, int length)
{
    for (int i = 0; i < length; ++i) {
        if (str[i] == '\n') {
            putchar('\\');
            putchar('n');
        } else
            putchar(str[i]);
    }
}

int main()
{
    print("hello\nworld!", 12);
    return 0;
}

答案 1 :(得分:3)

我会以稍微不同的方式实现您的自定义打印功能:

import { of } from "rxjs";
import { delay } from "rxjs/operators";

fakeObservable = of('dummy').pipe(delay(5000));

包装函数

#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>

static int output_escaped(FILE *out, const char *str, const char *end)
{
    int  count = 0;
    while (str < end)
        switch (*str) {
        case '\\': fputs("\\\\", out); count++; break;
        case '\a': fputs("\\a", out);  count++; break;
        case '\b': fputs("\\b", out);  count++; break;
        case '\t': fputs("\\t", out);  count++; break;
        case '\n': fputs("\\n", out);  count++; break;
        case '\v': fputs("\\v", out);  count++; break;
        case '\f': fputs("\\f", out);  count++; break;
        case '\r': fputs("\\r", out);  count++; break;
        default:
            if (isprint((unsigned char)(*str)))
                fputc(*str, out);
            else {
                fprintf(out, "\\x%02x", (unsigned char)(*str));
                count += 3; /* Note: incremented by one later */
            }
        }
        str++;
        count++;
    }
    return count;
}

当您想要将整个事物或仅int escape(const char *str) { if (!stdout || !str) { errno = EINVAL; return -1; } else return output_escaped(stdout, str, str + strlen(str)); } int escapen(const char *str, const size_t len) { if (!stdout || !str) { errno = EINVAL; return -1; } else return output_escaped(stdout, str, str + len); } int fescape(FILE *out, const char *str) { if (!out || !str) { errno = EINVAL; return -1; } else return output_escaped(out, str, str + strlen(str)); } int fescapen(FILE *out, const char *str, const size_t len) { if (!out || !str) { errno = EINVAL; return -1; } else return output_escaped(out, str, str + len); } 首字符打印到len或特定流时,四个包装器可以满足这些情况。全部返回输出的字符数,如果发生错误则返回-1(并设置errno)。

请注意,这会将stdout打印为\,并使用十六进制转义序列\\打印到\x00的其他不可打印字符。如果你想要八进制(\xFF\001)而不是十六进制转义,请使用

\377

代替。

else { fprintf(out, "\\%03o", (unsigned char)(*str)); count += 3; /* Note: incremented by one later */ } 强制转换可确保字符值永远不会为负值。

答案 2 :(得分:1)

这基本上是相同的,但它在内存中使用strchr来确切地看到我们可以在转义序列之前写入多少char,并fwrite将它们全部合并在一起。这可能比一次一个字符输出更快(可能与https://stackoverflow.com/a/37991361/2472827相关。)(未经过彻底测试。)

#include <stdlib.h> /* EXIT_ */
#include <stdio.h>  /* perror fwrite fputs */
#include <string.h> /* strchr */
#include <assert.h>

/** Prints the string, escaping newlines to "\n"; a newline will be added at
 the end.
 @return A non-negative number, otherwise EOF; in the latter case, it shall
 set an error indicator for the stream and (may) set {errno} (IEEE Std
 1003.1-2001-conforming systems?) */
static int printStr(const char* start) {
    const char *so_far = start, *nl;
    size_t nchars;
    assert(start);
    while((nl = strchr(so_far, '\n'))) {
        nchars = nl - so_far;
        if(fwrite(so_far, 1, nchars, stdout) != nchars
            || fwrite("\\n", 1, 2, stdout) != 2) return EOF;
        so_far = nl + 1;
    }
    /* The rest. */
    return fputs(so_far, stdout) == EOF || fputc('\n', stdout) == EOF ? EOF : 1;
}

int main(void) {
    return printStr("Lalala\n\nlalala\n\n") == EOF
        ? perror("string"), EXIT_FAILURE : EXIT_SUCCESS;
}

它不需要length,但你可以通过检查nchars,(如果你的字符串不是null - 终止?)

答案 3 :(得分:1)

您在问题中发布的代码似乎有效,但内存分配失败时潜在的未定义行为除外。它可以简化:不需要临时buffer,您可以直接从提供的数组打印,避免分配:

static void printStr(const char *s, int length) {
    int i, j;
    for (i = j = 0; i < length; i++) {
        if (s[i] == '\n') {
            printf("%.*s\\n", i - j, s + j);
        }
    }
    if (i > j) {
        printf("%.*s", i - j, s + j);
    }
}