0

我有一些 C 代码应该打印文件的全部内容。该程序以前可以很好地打印一个文件,但是当它打印一秒钟时,我一直看到一个绝对不应该存在的 Unicode 字符。

int c = fgetc(file);
putchar((!isprint(c) ? : c));

(包装在 a 中while(!feof(file))
应该只打印 ASCII 可打印字符,除非我弄错了。无论如何,它打印的第一件事是\357\277\275,它不是 ASCII,并且不可打印。

该文件仅包含以下内容:foo+bar.foo+t-bar.foo+completely fake

它打印出这个:(�foo+bar.foo+t-bar.foo+completely fake在奇怪的字符和其他字符之间有一个换行符)。

只需将其全部打印(a la putchar(c))将完全相同的字符放在行尾。

我什至尝试过使用另一个文件(通过重命名旧文件并使用指向另一个文件的软链接),但我得到了完全相同的结果。

如果文件为空,它也会执行此操作。

该文件是完全纯文本,用 vim 创建的,没有什么特别之处。

这是原始代码:

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

int main(void)
{
    char *headp = "../include/header";
    char *listp = "../.piclist";
    FILE *head, *list;

    puts("Content-Type: text/html; charset=utf-8\nExpires: 0\n");

    puts("<!DOCTYPE html>\n<html lang='en'>\n<head>");
    puts("\t<title>Foo</title>");
    puts("\t<link rel='stylesheet' href='/css/main.css' />");
    puts("\t<link rel='stylesheet' href='/css/foo.css' />");
    puts("</head>\n<body>");

    head = fopen(headp, "r");
    if (errno) {
            perror("cannot open include/header");
            errno = 0;
    } else {
            while (!feof(head)) putchar(fgetc(head));
            putchar('\n');
    fclose(head);
    }

    list = fopen(listp, "r");
    if (errno) perror("cannot open .piclist");
    else {
    while (!feof(list)) {
            while (!feof(list)) {
                    int c = fgetc(list);
                    putchar((!isprint(c) ? : c));
            }
    }
    fclose(list);
    } /* else */

    fputs("\n<footer>\n\t<hr />\n\t<p>Copyright 2011-2012 the ", stdout);
    fputs("<a href='mailto:foo@example.com'> ", stdout);
    fputs("Foo Bar of Baz</a> of ", stdout);
    fputs("<a href='http://blah.org'>Blah United ", stdout);
    fputs("</a></p>\n</footer>\n</body>\n</html>\n",stdout);

    return 0;
}
4

3 回答 3

2

不要使用 feof() (至少不是你使用它的方式)

另外,您对 errno 的使用是错误的。errno在某些操作指示错误返回后包含可用值(主要以 NULL 或 -1 作为返回值)

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

int main(void)
{
    char *headp = "../include/header";
    char *listp = "../.piclist";
    FILE *head, *list;
    int ch;

    puts("Content-Type: text/html; charset=utf-8\nExpires: 0\n");

    puts("<!DOCTYPE html>\n<html lang='en'>\n<head>");
    puts("\t<title>Warrenton Latin School | Gallery</title>");
    puts("\t<link rel='stylesheet' href='/css/main.css' />");
    puts("\t<link rel='stylesheet' href='/css/gallery.css' />");
    puts("</head>\n<body>");

    head = fopen(headp, "r");
    if (!head) {
            perror("cannot open include/header");
            errno = 0;
    } else {
        while (1) {
            ch = fgetc(head);
            if (ch == EOF) break;
            putchar(ch);
            }
        putchar('\n');
        fclose(head);
    }

    list = fopen(listp, "r");
    if (!list) perror("cannot open .piclist");
    else while (1) {
        ch = fgetc(list);
        if (ch == EOF) break;
        putchar((!isprint(c) ? : c));
    }
    fclose(list);

    fputs("\n<footer>\n\t<hr />\n\t<p>Copyright 2011-2012 the ", stdout);
    fputs("<a href='mailto:warrentonlatinschool@gmail.com'> ", stdout);
    fputs("Warrenton Latin School</a> co-op of ", stdout);
    fputs("<a href='http://warrentonumc.org'>Warrenton United ", stdout);
    fputs("Methodist Church</a></p>\n</footer>\n</body>\n</html>\n",stdout);

    return 0;
}
于 2012-01-25T18:01:34.380 回答
1

忽略代码中可能出现的错误会isprint()认为所有字符都是可打印的,除了0x00-0x1f0x7f.

仍然可以打印 UTF BOM 和 7 位 ANSI 之外的其他字符(尽管它们的含义可能会根据编码而改变)。

于 2012-01-25T17:42:53.080 回答
0

当您将 ?: 的第二个运算符留空时,它等于条件的结果。对于不可打印的字符,isprintc(c) 返回 0,因此三元运算符的条件部分是 !0,等于 1。因此 putchar 尝试打印无效的 ASCII 字符并中断。

于 2012-01-25T17:42:01.473 回答