2012-01-25 2 views
0

파일의 전체 내용을 인쇄해야하는 C 코드가 있습니다. 이 프로그램은 이전에 파일을 잘 인쇄하지만, 초를 인쇄 할 때 확실히 존재해서는 안되는 유니 코드 문자를 계속 볼 수 있습니다. (A while(!feof(file))에 싸여) ANSI C : isprint()는 비 ASCII 문자에 대해 true를 반환합니까?

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


해야하는에만 인쇄 ASCII 인쇄 가능한 문자는, 내가 틀리지 않는. 그럼에도 불구하고 인쇄 된 첫 번째 것은 ASCII가 아니며 인쇄 할 수없는 \357\277\275입니다. foo+bar.foo+t-bar.foo+completely fake

그리고이 인쇄 :

은 파일에만이 포함 �foo+bar.foo+t-bar.foo+completely fake을 (이상한 문자와 나머지 사이에 줄 바꿈 포함).

단순히 모두 인쇄하면 (aaa putchar(c)) 줄 끝 부분에 똑같은 문자가 표시됩니다.

나는 다른 파일 (예전의 이름을 바꾸고 다른 파일로 소프트 링크를 사용)을 사용해 보았습니다.하지만 똑같은 결과가 나옵니다.

파일이 비어있는 경우에도이 작업을 수행합니다.

파일은 vim으로 만든 완전히 평범한 텍스트이며 특별한 것은 없습니다. ? 당신의 2 운영자 떠날 때

#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

errno를 도 ... 가능한 값을 포함 * 파일이 비어있을 때 * 때문에 당신의 무엇이 일어 났는지를 결정하기 위해 feof () 사용이 잘못되었습니다. 실제 코드를 게시하십시오. – wildplasser

+0

문제를 나타내는 완전한 컴파일 가능한 예제를 보여줄 수 있습니까? – NPE

+2

putchar ((! isprint (c)? : c)); <- 어떻게 컴파일합니까? –

답변

2

DONT 사용에 무엇이 일어 났는지를 결정하기 위해 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()는 ** 발생한 후 ** 오류를 반환합니다. 이 경우 : 마지막 char을 읽은 후 fgetc()은 모든 후속 호출에서 EOF를 반환합니다. 첫 번째 EOF를 "소비"하고 올바른 문자로 간주하고 출력합니다 (출력 파일에서 0xff가 될 것입니다). 그리고 그 후에 만 ​​feof()는 0이 아닙니다. – wildplasser

0

: 빈을,이 조건의 결과에 동일

여기에 원래의 코드입니다. 인쇄 할 수없는 문자의 경우 isprintc (c)는 0을 반환하므로 토렌 연산자의 조건부는! 0 인 값이 1이므로 1입니다. 따라서 putchar은 잘못된 ASCII 문자를 인쇄하고 중단됩니다.

+0

고맙습니다. 거기에 빈 문자열 상수를 사용하는 것이 합법적일까요 아니면 그 효과를 위해 내가해야 할 다른 것이 있습니까? –

+0

조건부 외부로 이동 : if (! condition) putchar (...);'빈 문자열 (' ''')과'\ 0' (또는 빈 문자열의 첫 번째 요소 인 mind 데이터 유형)은'\ 0'을 출력합니다. – Mario

1

isprint()은 가능한 모든 오류를 무시하고 0x00-0x1f0x7f을 제외한 모든 문자를 인쇄 할 수 있다고 간주합니다.

UTF BOM 및 7 비트 ANSI 외부의 다른 문자는 인쇄 할 수 있습니다 (인코딩에 따라 의미가 다를 수도 있음).

+0

흠. 'if (c < 127 && c > 31) putchar (c);'를 사용하더라도 똑같은 효과가있었습니다. –

+0

아니요, 127 자 이상의 문자는 여전히 인쇄 가능합니다. – Mario

+0

동일한 효과로, 유니 코드 문자가 여전히 인쇄되었음을 의미했습니다. –

관련 문제