2012-01-25 5 views
0

У меня есть код C, который должен распечатать все содержимое файла. Программа ранее печатает файл просто отлично, но когда он печатает секунду, я все еще вижу символ Unicode, где определенно не должно быть.ANSI C: isprint() возвращает true для символа, отличного от ASCII?

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 (с новой строкой между странным характером и остальными).

Просто печать всего (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:[email protected]'> ", 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; 
} 
+0

... тоже * если файл пуст *, потому что ваш feof () использование неверно. Отправьте реальный код. – wildplasser

+0

Не могли бы вы показать полный, компилируемый пример, демонстрирующий проблему? – NPE

+2

putchar ((! Isprint (c)?: C)); <- как он компилируется? –

ответ

2

DONT USE feof() (по крайней мере, не так, как вы его используете)

Кроме того, ваше использование егто неправильно. 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:[email protected]'> ", 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; 
} 
+0

Почему я не должен использовать feof()? –

+0

Хорошо, мое использование errno и perror сработало; хотя я только тестировал это, когда файлов там не было. –

+1

feof() возвращает ошибку ** после ее появления **. В этом случае: после того, как последний символ был прочитан, fgetc() возвращает EOF при каждом последующем вызове. Вы «потребляете» первый EOF (и считаете его допустимым символом и печатаете его (он, вероятно, станет 0xff в выходном файле)) И только после этого feof() возвращает не ноль. – wildplasser

0

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

+0

Спасибо. Было бы законным иметь там пустую строку, или есть что-то еще, что я должен сделать для этого эффекта? –

+0

Переместить условие за пределами: 'if (! Condition) putchar (...);' Вы не можете определить пустой символ ('' '') и '\ 0' (или первый элемент пустой строки; типы данных) выводит '\ 0'. – Mario

1

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

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

+0

Hm. Хотя использование 'if (c < 127 && c > 31) putchar (c);' имело тот же самый эффект. –

+0

Нет, символы выше 127 по-прежнему доступны для печати. – Mario

+0

По тому же эффекту я имел в виду, что символ Юникода все еще печатает. –