다른 파일을 사용하지 않고 파일의 문자를 정렬하려면 어떻게해야합니까? 문자열로 저장하는 방법을 생각해 왔지만 많은 문자가 있다면 어떻게해야합니까? 또한, (ASCII 코드를 기반으로) 주파수 배열을 만드는 것에 대해 생각해 봤지만 파일은 수백 MB가 될 수 있습니다.C 파일의 문자 정렬
감사합니다.
다른 파일을 사용하지 않고 파일의 문자를 정렬하려면 어떻게해야합니까? 문자열로 저장하는 방법을 생각해 왔지만 많은 문자가 있다면 어떻게해야합니까? 또한, (ASCII 코드를 기반으로) 주파수 배열을 만드는 것에 대해 생각해 봤지만 파일은 수백 MB가 될 수 있습니다.C 파일의 문자 정렬
감사합니다.
나는 "문자"란 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;
}
매우 답답한 응답을 해주셔서 대단히 감사합니다. 마지막 줄에 화면에 문자를 인쇄하지 않습니까? – Stefan
@Stefan'stdout' 스트림은 운영체제가 표준 출력으로 정의한 문자에 문자를 씁니다. Windows와 GNU/Linux 같은 스크린이있는 워크 스테이션과 같은 시스템에서'stdout'은 보통 터미널 에뮬레이터이지만 파일이나 파이프의 한쪽으로 리디렉션 될 수 있습니다. 당신의 Q를 명확하게하여 정렬 된 결과를 어디서 쓰는지 말하십시오. 그것들을 같은 파일에 쓰는 것을 의미 했습니까? –
불명확하면 죄송합니다. 예, 동일한 파일에 저장하는 것입니다. – Stefan
단순히 각 문자를 계산합니다. 'size_t counter [256] = {0}; .. counter [c] ++;' – BLUEPIXY
* 문자 *를 실제로 정렬 하시겠습니까? 그래서'Hello World' 파일은'deHllloorw' 파일로 분류됩니까? –
캐릭터를 실제로 의미합니까? 그렇다면 단지 255 개가 될 수 있습니다 (아스키라고 가정). 따라서 빈도 카운트를 유지하십시오. 각 버킷에 int를 사용하면 여전히 1k입니다. 사람들은 파일에서 발생하는 횟수만큼 각 문자를 반복해서 써 넣습니다. –