C 如何使用格式打印文本

C 如何使用格式打印文本,c,C,我的问题是,当我尝试打印带有“\n”的文本时,这个特殊字符对于printf是不可见的,并且在将其回显到文件中并再次读取后将其放入 #include <stdio.h> #include <string.h> int main() { FILE *f; char *s = (char*) malloc (2919); strcpy(s, "printf 'H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=' |

我的问题是,当我尝试打印带有“\n”的文本时,这个特殊字符对于printf是不可见的,并且在将其回显到文件中并再次读取后将其放入

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

int main()
{   
    FILE *f;
    char *s = (char*) malloc (2919);
    strcpy(s, "printf 'H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=' | base64 -d | gunzip > r"); //Test\nTest after decoding
    system(s);
    f = fopen("r", "r");
    fseek(f, SEEK_SET, 0);
    fread(s, 2919, 1, f);
    printf("%s", s); //puts(s); gives the same result
    fclose(f);
    system("rm r");
    free(s);
    return 0;
}
它看起来像
Test\nTest
。我做错了什么?
学习目的,所以请友好。

您的代码存在以下问题:

  • fseek(f,SEEK\u集,0)没有任何作用,默认情况下,使用
    fopen
    打开的文件位于位置0

  • fread(s,2919,1,f):您不存储读取的字节数。不能正确地为null终止缓冲区,以便printf在最后一个解码字节处停止。你怎么知道文件的大小

  • 编码字符串
    H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=
    解码为
    Test\nTest
    ,后面跟一个
    n
    字符,而不是换行字符。使用
    fread
    从文件
    r
    读取这些字符不会将转义序列
    \n
    转换为实际换行字符。这种转换是编译器在解析字符串和字符文本时的一项功能。如果您打算对文件内容执行此操作,则必须亲自编写转换代码

以下是更正的版本:

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

int main(void) {   
    FILE *f;
    char *s = malloc(2919 + 1);
    char *p;
    int nread;

    strcpy(s, "printf 'H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=' | base64 -d | gunzip > r"); //Test\nTest after decoding
    system(s);
    f = fopen("r", "r");
    nread = fread(s, 2919, 1, f);
    if (nread >= 0) {
        s[nread] = '\0';
        while ((p = strstr(s, "\\n")) != NULL) {
            /* converting \ n sequences to linefeed characters */
            *p = '\n';
            memmove(p + 1, p + 2, strlen(p + 2) + 1);
        }
        printf("%s", s); //puts(s); will not give the same result
    }
    fclose(f);
    system("rm r");
    free(s);
    return 0;
}
#包括
#包括
int main(void){
文件*f;
char*s=malloc(2919+1);
char*p;
国际nread;
strcpy(s,“printf'H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=”| base64-d | gunzip>r”);//解码后测试\n
系统;
f=fopen(“r”、“r”);
nread=fread(s,2919,1,f);
如果(nread>=0){
s[nread]='\0';
而((p=strstrstr(s,“\\n”))!=NULL){
/*将序列转换为换行符\n*/
*p='\n';
memmove(p+1,p+2,strlen(p+2)+1);
}
printf(“%s”,s);//put(s);将不会给出相同的结果
}
fclose(f);
系统(“rm r”);
免费的;
返回0;
}

您编码的文本如下所示:

Test\nTest
这是一个10个字符的字符串,第五个字符为“\”,第六个字符为“n”。这与此不同:

char str[]="Test\nTest";
这是一个9个字符的字符串,第五个字符有换行符


如果要打印换行符,编码字符串需要包含它。或者,您必须解析结果字符串并手动执行换行符替换。

显然,您已经在字符串中的相应位置对字节进行了编码

如果你不想那样,你可以

  • 压缩并编码正确的字符串:

    $ echo $'Test\nTest' | gzip | base64
    H4sIAEs+aFYAAwtJLS7hCgERAF0muOIKAAAA
    $ echo $'Test\nTest' | gzip -n | base64
    H4sIAAAAAAAAAwtJLS7hCgERAF0muOIKAAAA
    
  • 或者根据需要解释字符串中的
    \n
    。但这让一切变得更加复杂


  • @“潜伏者”一针见血


    该编码显然有一个文字反斜杠,而您的代码中没有任何内容 系统命令的管道解释它。有一种方法可以达到目的 解释转义为:“echo-e$(printf “H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=”| base64-d | gunzip) r“

    在回答这个问题时要更详细一点——具体来说,您已经压缩了文本ASCII(或UTF-8)字符:

    T  e  s  t  \  n  T  e  s  t
    
    考虑到您的问题,您(可能)打算压缩一个新行字符(通常由工具从字符串
    \n
    中解释),而不是压缩两个文本字符
    \
    n

    您可以创建不同的gzip输入。这是一个选择。我不知道您是如何生成当前的gzip二进制数据的——如果您发布了这些数据,我们可以看一看并提出修复方案

    或者,正如@Louger所说,您可以在输出上做一些事情,将任何出现的
    \
    n
    转换为换行符,有很多方法可以做到这一点

    但这实际上取决于你想做什么。如果您认为已压缩此文本:

    Test
    Test
    
    Test\nTest
    
    …然后是输入出错了

    如果您认为已压缩此文本:

    Test
    Test
    
    Test\nTest
    
    …(就像字面上的反斜杠和n一样),那么您可能正在尝试添加一些输出处理,以将其转换为真正的新行字符


    这有意义吗?

    只有在文字字符串(源代码中的常量)而不是任何字符串变量中遇到“\n”序列时,C编译器才会将其转换为换行符(ASCII代码10)

    示例:

    char s1[] = "TEST\nTEST";
    printf(s1); // ---> TEST newline TEST.
    
    char s2[] = "TEST\\nTEST"; // s2 = "TEST\nTEST"
    printf(s2); // ---> TEST\nTEST (the characters \ and n are present inside the string)
    
    如您所见,对于
    s1
    ,字符串首先由C编译器解析,然后将
    \n
    转换为换行符。在第二种情况下,转义字符
    \
    阻止了解释,因此字符串
    s2
    正好是
    TEST\nTEST
    ,但现在它不再是一个文本(在代码中显式给出),而是内存中的一个真实字符串。因此,它将不再被解释


    因此,
    printf(s2)
    printf(“TEST\nTEST”)
    不同,因为在前一种情况下没有解释,而在后一种情况下,C编译器看到一个文本并将对其进行解释,将
    \n
    替换为
    换行符

    编码显然有一个文字反斜杠,系统命令管道中没有任何内容解释它。解释转义的一种方法是:
    “echo-e$(printf'H4sIAIM4aFYCAwtJLS6JyQsBklwAMrDLnwsAAAA=”| base64-d | gunzip)>r“
    可能是“\n”之前的一个额外“\”,用-e编码是答案,所以潜伏者的解决方案在我的情况下是最好的。谢谢大家的贡献!虽然您已经识别出OP代码中存在的有效问题,但您还没有解决他实际提出的问题。您的更正无法修复它。从技术上讲,此修复是草率的,因为它可能无法按预期处理
    Foo\\nBar
    ,但OP的实际语义是模糊的。