【问题标题】:Add Carriage-Return utility in C printing garbage?在 C 打印垃圾中添加回车实用程序?
【发布时间】:2014-02-12 04:36:25
【问题描述】:

我有以下 C 语言程序,旨在将 UNIX 文本文件转换为 Windows 格式 (LF->CR LF)。基本上预期的用法是命令行中的addcr infile > outfile

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
    FILE *fp;
    char *buffer;
    int i, flen;
    if(argc<2)
    {
        printf("Usage: addcr filename\n");
        return 0;
    }
    fp=fopen(argv[1], "r");
    if(fp==NULL)
    {
        printf("Couldn't open %s.\n", argv[1]);
        return 0;
    }
    fseek(fp, 0, SEEK_END);
    flen=ftell(fp);
    rewind(fp);
    buffer=(char*)malloc(flen+1);
    fread(buffer, 1, flen, fp);
    fclose(fp);
    buffer[flen]=0;
    for(i=0;i < strlen(buffer);i++)
    {
        if(buffer[i]==0x10)
        {
            printf("%c", '\r');
        }
        printf("%c", buffer[i]);
    }

    free(buffer);
    return 0;
}

但是,有时它会在文件内容的末尾打印出垃圾,这可以通过将其输出与 TYPE 命令进行比较来表明:

C:\Temp>addcr sample.txt
He did not wear his scarlet coat,
                 For blood and wine are red,
               And blood and wine were on his hands
                 When they found him with the dead,
               The poor dead woman whom he loved,
                 And murdered in her bed.
Window
C:\Temp>type sample.txt
He did not wear his scarlet coat,
                 For blood and wine are red,
               And blood and wine were on his hands
                 When they found him with the dead,
               The poor dead woman whom he loved,
                 And murdered in her bed.

C:\Temp>

它似乎有时会在我的环境变量中打印出一些不可预测的字符串部分。我完全不知道是什么原因造成的。有谁知道如何解决这个问题?

【问题讨论】:

    标签: c console text-files line-endings


    【解决方案1】:

    我认为这里发生的情况是输入文件已经有 CRLF 行分隔符,并且您已经以文本模式打开它。然后发生的事情是你使用fread,它会将这些转换为换行符('\n')。

    由于您首先询问文件大小,这将比您读入的翻译文本的长度长 6 个字节。这意味着在您终止位于位置 flen 的缓冲区之前,最后 6 个字节未初始化。

    fread 实际上会返回读取的字节数。你应该注意这个值。

    size_t bytes_read = fread(buffer, 1, flen, fp);
    

    试试看。输出bytes_read的值和flen的值。我敢打赌他们是不同的。此外,您真的不必终止缓冲区并使用strlen 来获取长度。这样做实际上很丑陋。你已经知道长度了——它是bytes_read。所以在你的循环中使用它。

    如果你想避免这种混淆,你应该以二进制模式打开文件——"rb",而不是"r"

    【讨论】:

      【解决方案2】:

      由于stdout 在文本模式下工作,如果您在 Windows 操作系统上运行它,则不应显式编写'\r'。它会自动将 '\n' 转换为 '\r' '\n'(并以正确的顺序进行!)。

      【讨论】:

        【解决方案3】:

        buffer 末尾没有 \0,因此 strlen(buffer) 将继续计数,直到碰巧找到 \0 - 所以它返回的长度会比 buffer 的实际长度略多。

        【讨论】:

        • 我有行缓冲区[flen]=0;在我打电话给 strlen 之前。 (“\0”的 ASCII 值为 0)。但是,按照@paddy 帖子中的建议,我已经发现并解决了实际问题。
        猜你喜欢
        • 1970-01-01
        • 2016-04-30
        • 2016-04-15
        • 1970-01-01
        • 2015-09-20
        • 2017-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多