ANSI C: isprint () возвращает true для не-ASCII символа? - PullRequest
0 голосов
/ 25 января 2012

У меня есть некоторый C-код, который должен печатать все содержимое файла.Ранее программа печатала файл очень хорошо, но когда он печатает секунду, я продолжаю видеть символ Unicode там, где его определенно не должно быть.

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

while(!feof(file)))
Должен толькопечатать печатные символы ASCII, если я не ошибаюсь.Несмотря на это, первое, что он печатает, это \357\277\275, который не является ASCII и не пригоден для печати. ​​

Файл содержит только это: foo+bar.foo+t-bar.foo+completely fake

и печатает это:�foo+bar.foo+t-bar.foo+completely fake (с новой строкой между странным символом и остальными).

Простая печать всего этого (а-ля 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;
}

Ответы [ 3 ]

2 голосов
/ 25 января 2012

НЕ ИСПОЛЬЗУЙТЕ feof () (по крайней мере, не так, как вы его используете)

Кроме того, вы неправильно используете errno.errno only содержит используемое значение после того, как какая-то операция показала возврат ошибки (в основном 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;
}
1 голос
/ 25 января 2012

Игнорирование возможных ошибок в вашем коде isprint() считает все символы печатаемыми, кроме 0x00 - 0x1f и 0x7f.

Такие вещи, как UTF BOM и другие символы вне 7-битного ANSI, все еще могутбыть напечатанным (несмотря на то, что их значение может меняться в зависимости от кодировки).

0 голосов
/ 25 января 2012

Когда вы оставляете 2-й оператор?: Пустым, он равен результату условия. Для непечатаемых символов isprintc (c) возвращает 0, поэтому условная часть оператора trenary равна! 0, что равно 1. Поэтому putchar пытается вывести недопустимый символ ASCII и разрывается.

...