2014-10-29 2 views
-1

다른 파일을 사용하지 않고 파일의 문자를 정렬하려면 어떻게해야합니까? 문자열로 저장하는 방법을 생각해 왔지만 많은 문자가 있다면 어떻게해야합니까? 또한, (ASCII 코드를 기반으로) 주파수 배열을 만드는 것에 대해 생각해 봤지만 파일은 수백 MB가 될 수 있습니다.C 파일의 문자 정렬

감사합니다.

+2

단순히 각 문자를 계산합니다. 'size_t counter [256] = {0}; .. counter [c] ++;' – BLUEPIXY

+0

* 문자 *를 실제로 정렬 하시겠습니까? 그래서'Hello World' 파일은'deHllloorw' 파일로 분류됩니까? –

+5

캐릭터를 실제로 의미합니까? 그렇다면 단지 255 개가 될 수 있습니다 (아스키라고 가정). 따라서 빈도 카운트를 유지하십시오. 각 버킷에 int를 사용하면 여전히 1k입니다. 사람들은 파일에서 발생하는 횟수만큼 각 문자를 반복해서 써 넣습니다. –

답변

3

나는 "문자"란 C가 "문자"(char)를 부르는 것을 의미한다고 가정합니다. 멀티 바이트 및 와이드 문자 세트는 범위를 벗어납니다. 이 경우 문자는 UCHAR_MAX + 1 (종종 256)이며 문자는 counting sort으로 충분합니다. 본질적으로 당신이해야 할 일은 전체 파일을 읽고, 각 문자의 발생 횟수를 계산하고, 나타나는 각 문자를 여러 번 인쇄하는 것입니다. unsigned long int 배열은 ftell()이 넘는 오프셋보다 크므로 UCHAR_MAX + 1 개의 요소를 길게 만들 수 있습니다. 이유는 그것이 얼마나 많은 고유 한 문자가 가능하기 때문입니다.

#include <stdio.h> 
#include <stdlib.h> // for EXIT_FAILURE 
#include <limits.h> // for *_MAX 

// "unsigned long int" chosen to match the ftell() limit, 
// and numeric variables at top level start out zeroed 
unsigned long int occurrences[UCHAR_MAX + 1]; 

// static assertion to make sure we're on a "sane" platform 
// with INT_MAX larger than UCHAR_MAX 
extern char staticassert1[INT_MAX > UCHAR_MAX ? 1 : -1]; 

int main(const int argc, const char *const *argv) { 
    FILE *infp = NULL; 
    int ch; 

    if (argc < 2) { // ensure a filename was provided 
    fputs("error: no filename\n", stderr); 
    return EXIT_FAILURE; 
    } 
    infp = fopen(argv[1], "rt"); 
    if (!infp) { // ensure the file can be read 
    perror(argv[1]); 
    return EXIT_FAILURE; 
    } 

    // count each character; EOF is a value distinct from 
    // all characters 
    for(ch = fgetc(infp); ch != EOF; ch = fgetc(infp)) { 
    // cast to unsigned because arrays have no negative index 
    occurrences[(unsigned char)ch] += 1; 
    } 

    // once ch becomes EOF, the file has been read 
    // to either its end or an error 
    if (ferror(infp)) { 
    fclose(infp); 
    perror(argv[1]); 
    return EXIT_FAILURE; 
    } 

    // close the successfully read file 
    fclose(infp); 
    infp = NULL; // it's good practice to cut off dangling pointers early 

    // now print all characters in the file in sorted order 
    for (ch = 0; ch <= UCHAR_MAX; ++ch) { 
    for (; occurrences[ch] > 0; --occurrences[ch]) { 
     fputc(ch, stdout); 
    } 
    } 

    return 0; 
} 
+0

매우 답답한 응답을 해주셔서 대단히 감사합니다. 마지막 줄에 화면에 문자를 인쇄하지 않습니까? – Stefan

+1

@Stefan'stdout' 스트림은 운영체제가 표준 출력으로 정의한 문자에 문자를 씁니다. Windows와 GNU/Linux 같은 스크린이있는 워크 스테이션과 같은 시스템에서'stdout'은 보통 터미널 에뮬레이터이지만 파일이나 파이프의 한쪽으로 리디렉션 될 수 있습니다. 당신의 Q를 명확하게하여 정렬 된 결과를 어디서 쓰는지 말하십시오. 그것들을 같은 파일에 쓰는 것을 의미 했습니까? –

+0

불명확하면 죄송합니다. 예, 동일한 파일에 저장하는 것입니다. – Stefan