본문 바로가기
컴퓨터 기초/운영체제 실습

12.head 명령어 실습

by 인생여희 2020. 7. 4.

#.head 명령어 실습 1

*처리 대상은 표준 입력으로만한다. 즉, 실행인자로 파일 이름을 받는 기능은 생략한다.

*출력할 줄의 수는 첫 번째 실행 인자로 전달 받는다.

 

예제

//처리 대상은 표준 입력으로만한다. 즉, 실행인자로 파일 이름을 받는 기능은 생략한다.
//출력할 줄의 수는 첫 번째 실행 인자로 전달 받는다.
#include <stdio.h>
#include <stdlib.h>
static void do_head(FILE *f, long nlines);
int main(int argc, char *argv[]){
if (argc != 2 ) {
fprintf(stderr, "usage: %s n \n" , argv[0]);
exit(1);
}
printf("main 함수 표준파일 입력 -- \n");
//표준파일 입력, atol: 문자를 long 타입의 숫자로 변환하는 함수
//터미널에서 문자입력을 받는다.
do_head(stdin, atol(argv[1]));
exit(0);
}
static void do_head(FILE *f , long nlines){
int c;
if (nlines < 0) {
return;
}
//getc 함수는 버퍼를 만들어서 넘길 필요가 없기때문에 사용하기 편리하다.
//fgetc를 편하게 사용하려면 한 줄의 길이를 제한할 필요가 있다.
while ((c= getc(f)) != EOF) {
//printf("long : %lu \n" , nlines);
//printf("c : %d \n" , c);
/*
위 printf 문 출력 내용
getc의 리턴값은 문자를 정수로 변환한 값을 1바이트씩 리턴한다.
aa
long : 2
c : 97
along : 2
c : 97
along : 2
c : 10
bb
long : 1
c : 98
blong : 1
c : 98
blong : 1
c : 10
*/
//putchar 함수로 표준 출력으로 처리 - 터미널에 입력한 내용을 그대로 쓴다.
if (putchar(c) < 0) {
exit(1);
}
//줄바꿈을 처리
if (c == '\n') {
nlines--;
}
//nlines 가 0이면 함수 중단
if (nlines == 0 ) {
return;
}
}
}
view raw head.c hosted with ❤ by GitHub

결과

 

 

#.head 명령어 실습 2

*파일의 경로를 실행 인자로 받아들이는 기능을 구현

*첫번째 인자는 이전처럼 출력할 라인 수, 두번째 이후 인자를 파일이름으로 간주한다.

 

예제

//파일의 경로를 실행 인자로 받아들이는 기능을 구현
//첫번째 인자는 이전처럼 출력할 라인 수, 두번째 이후 인자를 파일이름으로 간주한다.
#include <stdio.h>
#include <stdlib.h>
static void do_head(FILE *f, long nlines);
int main(int argc, char *argv[]){
long nlines;
//명령어 : /head 5 abc.txt def.txt
//파일을 지정하지 않았으면 오류발생
if (argc < 2 ) {
fprintf(stderr, "usage: %s n \n" , argv[0]);
exit(1);
}
printf("main 함수 표준파일 입력 -- \n");
//표준파일 입력, atol: 문자를 long 타입의 숫자로 변환하는 함수
//터미널에서 문자입력을 받는다.
//터미널에서 인자로 받은 줄 수
nlines = atol(argv[1]);
//터미널에서 줄수, 까지 입력받았다면 표준 입출력 함수 실행
if (argc == 2) {
do_head(stdin, nlines);
}
else{ //*** 이부분 추가 ****
int i;
for (i = 2; i < argc; i++) {
FILE *f;
//파일을 읽기 전용으로 열기
f = fopen(argv[i], "r");
if (!f) {
perror(argv[i]);
exit(1);
}
//출력할 파일과 출력라인 값을 전달.
do_head(f,nlines);
//파일 닫기
fclose(f);
}//for - end
}//else end
exit(0);
}
static void do_head(FILE *f , long nlines){
int c;
if (nlines < 0) {
return;
}
//getc 함수는 버퍼를 만들어서 넘길 필요가 없기때문에 사용하기 편리하다.
//fgetc를 편하게 사용하려면 한 줄의 길이를 제한할 필요가 있다.
while ((c= getc(f)) != EOF) {
//printf("long : %lu \n" , nlines);
//printf("c : %d \n" , c);
/*
위 printf 문 출력 내용
getc의 리턴값은 문자를 정수로 변환한 값을 1바이트씩 리턴한다.
aa
long : 2
c : 97
along : 2
c : 97
along : 2
c : 10
bb
long : 1
c : 98
blong : 1
c : 98
blong : 1
c : 10
*/
//putchar 함수로 표준 출력으로 처리 - 터미널에 입력한 내용을 그대로 쓴다.
if (putchar(c) < 0) {
exit(1);
}
//줄바꿈을 처리
if (c == '\n') {
nlines--;
}
//nlines 가 0이면 함수 중단
if (nlines == 0 ) {
return;
}
}
}
view raw head2.c hosted with ❤ by GitHub

결과

 

#.head 명령어 실습 2 -2 

*파일의 경로를 실행 인자로 받아들이는 기능을 구현

*첫번째 인자는 이전처럼 출력할 라인 수, 두번째 이후 인자를 파일이름으로 간주한다.

 

예제2-2

#include <stdio.h>
#include <stdlib.h>
static void do_head(FILE *f, long nlines);
int main(int argc, char *argv[]){
FILE *readFile;
//오직 실행파일명 + 줄수 + 파일명
if (argc < 2) {
fprintf(stderr, "usage: %s 예)실행파일명 + 줄수 + 파일명 \n" , argv[0]);
exit(1);
}
//파일을 읽기 전용으로 열기
readFile = fopen(argv[2] , "r");
//NULL 이면 파일 읽기 실패
if (readFile == NULL) {
fprintf(stderr, "usage: %s 파일 열기 실패 \n" , argv[2]);
exit(1);
}
//표준파일 입력, atol: 문자를 long 타입의 숫자로 변환하는 함수
//터미널에서 문자입력을 받는다.
do_head(readFile , atol(argv[1]));
//파일 닫기
fclose(readFile);
exit(0);
}
static void do_head(FILE *f, long nlines){
printf("file : %p \n" , f);
printf("nlines : %ld \n" , nlines);
//줄 수가 0 보다 작으면 리턴
if (nlines < 0) {
fprintf(stderr, "usage: %s \n" , "줄 수를 입력해주세요");
exit(1);
}
/*
- getc
- 설명
스트림에서 한 문자를 읽어온다.
문자를 읽어온 스트림의 내부 파일 위치 표시자가 현재 가리키는 문자를 리턴한다.
그리고 내부 파일 표시자는 그 다음 문자를 가리키게 된다.
- 인자
문자를 읽어올 스트림의 FILE 객체를 가리키는 포인터
- 리턴값
읽어들인 문자는 int 값으로 리턴된다.만일 파일 끝에 도달하거나, 읽기 오류가 발생한다면 함수는 EOF 를 리턴하고 이에 대응하는 오류 혹은 EOF 표시자가 설정된다. 여러분은 ferror이나 feof함수를 통해 각각 어떤 오류가 발생했는지, 파일 끝에 도달하였는지 알 수 있다.
*/
for (; ; ) {
//printf("start!\n");
int c = getc(f);
//printf("c : %d \n" , c);
//결과 : 문자 a를 입력하고 엔터치면 97 과 10 출력한다.
//getc의 리턴값은 문자를 정수로 변환한 값을 1바이트씩 리턴한다.
//문자의 마지막을 만났을때
if (c == EOF) {
break;
}
//엔터문자(줄바꿈) 만나면 nlines 변수 값 -1
if (c == '\n') {
nlines--;
}
//커멘드 라인에서 입력한 줄수를 다 출력하면 빠져나온다.
if (nlines == 0) {
break;
}
//출력하기
int p = putchar(c);
//printf("p : %d \n" , p);
//출력한 1byte 정수값을 리턴함
//오류처리
if (p < 0) {
exit(1);
}
} // for - end
printf("\n");
}
view raw head2.c hosted with ❤ by GitHub

 

 

 

#.head 명령어 실습 3

*위에서 작성중인 head 명령어 소스에 getopt_long()을 사용해서

*옵션을 처리하는 기능을 추가하는 기능.

 

예제

//위에서 작성중인 head 명령어 소스에 getopt_long()을 사용해서
//옵션을 처리하는 기능을 추가하는 기능.
/*
출력할 줄 수를 지정하는 -n
동일한 의미의 롱 옵션 --lines
간단한 헬프 메시지를 표시하는 --help
*/
#include <stdio.h>
#include <stdlib.h>
// [1] : getopt_long 함수를 사용하기 위해 상수를 정의하고, getopt를 include 한다.
#define _GNU_SOURCE
#include <getopt.h>
static void do_head(FILE *f, long nlines);
extern char *optarg; //현재 처리중인 옵션의 파리미터
extern int optind, //현재 처리중인 옵션의 argv 인덱스
opterr, //이값이 참이면 getopt가 에러 메시지를 표시
optopt; //현재 처리 중인 옵션 문자
#define DEFAULT_N_LINES 10
// [2] : 긴옵션을 정의하기 위해 struct 옵션의 배열을 만들고 각 긴 옵션에 해당하는 요소를 정의하였다.
//배열의 마지막에는 모든 멤버를 0으로 대입한 요소를 넣어야 한다.
//required_argument : 반드시 파리미터를 취함, no_argument: 파리미터를 취하지 않음
//세번째 인자에 null을 입력하면 네번재 인자의 값이 반환된다.
static struct option longopts[] ={
{"lines" , required_argument, NULL, 'n'},
{"help" , no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[]){
int opt;
long nlines = DEFAULT_N_LINES;
//[3] :getopt_long : 커멘드 라인 옵션을 해석하는 api
//항상 루프와 사용하고 호출될때마다 인자로 넘겨진 다음 옵션 문자를 반환한다.
//잘못된경우 ? 를 반환한다. 인자로 넘겨진 모든 옵션을 반환했으면 -1을 반환한다.
while((opt = getopt_long(argc,argv, "n:" , longopts , NULL)) != -1){
switch(opt){
// -n 옵션과 --lines 옵션을 처리한다. 옵션의 파라미터값은 optarg에 들어 있어
// 여기서 출력할 줄 수를 얻는다.
case 'n' :
nlines = atol(optarg);
break;
case 'h' :
//명령어 사용법 출력
fprintf(stdout, "usage : %s [-n LINES] [FILE...] \n " ,argv[0]);
exit(0);
break;
case '?' :
//명령어 사용법 출력
fprintf(stdout, "usage : %s [-n LINES] [FILE...] \n " ,argv[0]);
exit(1);
break;
}
}
//[7] : getopt_long에 의한 파싱이 끝난 시점에서 optind가 argc와 같다는 것은
// 옵션 이외에 추가적인 인자를 지정하지 않았음을 의미한다.
//optind는 getopt()나 getopt_long이 마지막으로 처리한 인자의 인덱스를 가지고 있기 때문이다.
//옵션 이외에 대상 파일을 지정하지 않은경우, 표준 입력에서 읽도록 했다.
if(optind == argc){
do_head(stdin, nlines);
}else{
int i;
//[8]
for (i = optind ; i < argc; i++) {
FILE *f;
//파일을 읽기 전용으로 열기
f = fopen(argv[i], "r");
if (!f) {
perror(argv[i]);
exit(1);
}
//출력할 파일과 출력라인 값을 전달.
do_head(f,nlines);
//파일 닫기
fclose(f);
}//for - end
}
exit(0);
}
static void do_head(FILE *f , long nlines){
int c;
if (nlines < 0) {
return;
}
//getc 함수는 버퍼를 만들어서 넘길 필요가 없기때문에 사용하기 편리하다.
//fgetc를 편하게 사용하려면 한 줄의 길이를 제한할 필요가 있다.
while ((c= getc(f)) != EOF) {
//putchar 함수로 표준 출력으로 처리 - 터미널에 입력한 내용을 그대로 쓴다.
if (putchar(c) < 0) {
exit(1);
}
//줄바꿈을 처리
if (c == '\n') {
nlines--;
}
//nlines 가 0이면 함수 중단
if (nlines == 0 ) {
return;
}
}
}
view raw head3.c hosted with ❤ by GitHub

결과

 

#.head 명령어 실습 3-2

*위에서 작성중인 head 명령어 소스에 getopt_long()을 사용해서

*옵션을 처리하는 기능을 추가하는 기능.

 

예제 3-2

//위에서 작성중인 head 명령어 소스에 getopt_long()을 사용해서
//옵션을 처리하는 기능을 추가하는 기능.
/*
출력할 줄 수를 지정하는 -n
동일한 의미의 롱 옵션 --lines
간단한 헬프 메시지를 표시하는 --help
*/
#include <stdio.h>
#include <stdlib.h>
#define _GUN_SOURCE
#include <getopt.h>
static void do_head(FILE *f, long nlines);
extern char *optarg; //현재 처리중인 옵션의 파리미터
extern int optind, //현재 처리중인 옵션의 argv 인덱스
opterr, //이값이 참이면 getopt가 에러 메시지를 표시
optopt; //현재 처리 중인 옵션 문자
#define DEFAULT_N_LINES 10
// [2] : 긴옵션을 정의하기 위해 struct 옵션의 배열을 만들고 각 긴 옵션에 해당하는 요소를 정의하였다.
//배열의 마지막에는 모든 멤버를 0으로 대입한 요소를 넣어야 한다.
//required_argument : 반드시 파리미터를 취함, no_argument: 파리미터를 취하지 않음
//세번째 인자에 null을 입력하면 네번재 인자의 값이 반환된다.
static struct option longopts[] = {
{"lines" , required_argument, NULL, 'n'},
{"help" , no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[]){
FILE *readFile;
int opt;
long linesNumber = DEFAULT_N_LINES;
//[3] :getopt_long : 커멘드 라인 옵션을 해석하는 api
//항상 루프와 사용하고 호출될때마다 인자로 넘겨진 다음 옵션 문자를 반환한다.
//잘못된경우 ? 를 반환한다. 인자로 넘겨진 모든 옵션을 반환했으면 -1을 반환한다.
while((opt = getopt_long(argc, argv, "n:" , longopts, NULL)) != -1)
{
printf("opt - d : %d \n" , opt);
printf("opt - c : %c \n" , opt);
printf("optarg : %s \n" , optarg);
switch(opt){
case 'n' :
linesNumber = atol(optarg);
break;
case 'h' :
//명령어 사용법 출력
fprintf(stdout, "usage : %s [-n LINES] [FILE...] \n " ,argv[0]);
exit(0);
break;
case '?' :
//명령어 사용법 출력
fprintf(stdout, "usage : %s [-n LINES] [FILE...] \n " ,argv[0]);
exit(1);
break;
}
}
printf("optind : %d \n" , optind);
//[7] : getopt_long에 의한 파싱이 끝난 시점에서 optind가 argc와 같다는 것은
// 옵션 이외에 추가적인 인자를 지정하지 않았음을 의미한다.
//optind는 getopt()나 getopt_long이 마지막으로 처리한 인자의 인덱스를 가지고 있기 때문이다.
if(optind == argc){
fprintf(stdout, "usage : %s 인자를 지정하세요 \n " ,argv[0]);
exit(1);
}
//오직 실행파일명 + 줄수 + 파일명
if (argc < 2) {
fprintf(stderr, "usage: %s 예)실행파일명 + 줄수 + 파일명 \n" , argv[0]);
exit(1);
}
//파일을 읽기 전용으로 열기
readFile = fopen(argv[2] , "r");
//NULL 이면 파일 읽기 실패
if (readFile == NULL) {
fprintf(stderr, "usage: %s 파일 열기 실패 \n" , argv[2]);
exit(1);
}
//표준파일 입력, atol: 문자를 long 타입의 숫자로 변환하는 함수
//터미널에서 문자입력을 받는다.
do_head(readFile , linesNumber);
//파일 닫기
fclose(readFile);
exit(0);
}
static void do_head(FILE *f, long nlines){
printf("file : %p \n" , f);
printf("nlines : %ld \n" , nlines);
//줄 수가 0 보다 작으면 리턴
if (nlines < 0) {
fprintf(stderr, "usage: %s \n" , "줄 수를 입력해주세요");
exit(1);
}
/*
- getc
- 설명
스트림에서 한 문자를 읽어온다.
문자를 읽어온 스트림의 내부 파일 위치 표시자가 현재 가리키는 문자를 리턴한다.
그리고 내부 파일 표시자는 그 다음 문자를 가리키게 된다.
- 인자
문자를 읽어올 스트림의 FILE 객체를 가리키는 포인터
- 리턴값
읽어들인 문자는 int 값으로 리턴된다.만일 파일 끝에 도달하거나, 읽기 오류가 발생한다면 함수는 EOF 를 리턴하고 이에 대응하는 오류 혹은 EOF 표시자가 설정된다. 여러분은 ferror이나 feof함수를 통해 각각 어떤 오류가 발생했는지, 파일 끝에 도달하였는지 알 수 있다.
*/
for (; ; ) {
//printf("start!\n");
int c = getc(f);
//printf("c : %d \n" , c);
//결과 : 문자 a를 입력하고 엔터치면 97 과 10 출력한다.
//getc의 리턴값은 문자를 정수로 변환한 값을 1바이트씩 리턴한다.
//문자의 마지막을 만났을때
if (c == EOF) {
break;
}
//엔터문자(줄바꿈) 만나면 nlines 변수 값 -1
if (c == '\n') {
nlines--;
}
//커멘드 라인에서 입력한 줄수를 다 출력하면 빠져나온다.
if (nlines == 0) {
break;
}
//출력하기
int p = putchar(c);
//printf("p : %d \n" , p);
//출력한 1byte 정수값을 리턴함
//오류처리
if (p < 0) {
exit(1);
}
} // for - end
printf("\n");
}
view raw head3.c hosted with ❤ by GitHub

 

 

예제파일

 

test2.zip
0.01MB

 

#.homework 

1.이전장에서 만든 \t 나 \n 을 출력해주는 기능을 cat 명령어의 옵션으로 켜고 끌 수 있게 작성하라.

2.파일의 마지막 몇 줄을 출력하는 tail 명령어를 구현하라. 출력하는 줄의 수는 고정값으로 한다.

 

 

 

#.이전장에서 만든 \t 나 \n 을 출력해주는 기능을 cat 명령어의 옵션으로 켜고 끌 수 있게 작성하라.

풀이

// \t -> '탭' 이나 \n -> '개행'으로 출력해주는 기능을 cat 명령어의 옵션으로 켜고 끌 수 있게 작성
// 예) 명령어 : ./head -sy test.txt 또는 ./head -sn test.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//인자 처리 라이브러리
#define _GUN_SOURCE
#include <getopt.h>
extern char *optarg; //현재 처리 중인 옵션의 파라미터
//현재 처리중인 옵션의 argv 인덱스,에러, 현재 처리 중인 옵션 문자
extern int optind, opterr, optopt;
//커멘드 라인 인자 옵션 구조체
static struct option longopts[] = {
{"show" , required_argument, NULL, 's'}, //보이게, 숨기게
{"help" , no_argument , NULL, 'h'}, //도움말
{0, 0, 0, 0}
};
int main(int argc, char *argv[]){
FILE* readFile;
unsigned char buf[2] = "";
long lSize;
int opt;
//show 옵션의 파라미터 y인지 n 인지
char *yn;
//인자 개수 및 내용 출력
printf("argc : %d \n" , argc);
for (int i =0 ; i < argc; i++) {
printf("argv [%d] : %s] \n" , i , argv[i]);
};
//인자의 개수가 맞지 않을때
if (argc != 3) {
fprintf(stdout, "usage:인자의 개수가 잘못되었습니다. \n %s -sy test.txt 또는 -sn test.txt 형식입니다. \n" , argv[0]);
}
//커멘드라인 인자 처리
//getopt_long : 커멘드 라인 옵션을 해석하는 api
//항상 루프와 사용하고 호출될때마다 인자로 넘겨진 다음 옵션 문자를 반환한다.
//잘못된경우 ? 를 반환한다. 인자로 넘겨진 모든 옵션을 반환했으면 -1을 반환한다.
while((opt = getopt_long(argc, argv, "s:" , longopts , NULL)) != -1){
switch(opt){
case 's' :
//:s[파라미터]
yn = optarg;
break;
//도움말
case 'h' :
fprintf(stdout, "usage: \n %s -sy test.txt 또는 -sn test.txt 형식입니다. \n" , argv[0]);
exit(1);
break;
//?
case '?' :
fprintf(stdout, "usage: \n %s -sy test.txt 또는 -sn test.txt 형식입니다. \n" , argv[0]);
exit(1);
break;
}
}
//getopt_long에 의한 파싱이 끝난 시점에서 optind가 argc와 같다는 것은
//옵션 이외에 추가적인 인자를 지정하지 않았음을 의미한다.
//optind는 getopt()나 getopt_long이 마지막으로 처리한 인자의 인덱스를 가지고 있기 때문이다.
if(optind == argc){
fprintf(stdout, "usage : %s 인자를 지정하세요 \n " ,argv[0]);
exit(1);
}
//argv[2]에 파일명이 존재
//파일열기 - 읽기전용
readFile = fopen(argv[2], "r");
//파일 열기 오류 처리
if (readFile == NULL) {
fprintf(stdout, "%s 오류가 발생했습니다." , argv[2]);
exit(1);
}
//파일 크기 구하기
fseek(readFile, 0 , SEEK_END);
lSize = ftell(readFile);
rewind(readFile);
printf("##파일사이즈 : %ld byte\n" , lSize);
printf("##개행, 탭표시 유무 yn : %s\n" , yn);
//파일 읽기
for (; ; ) {
int readByteNum = fread(buf, sizeof(char) , 1 , readFile);
//파일 다읽으면 빠져나오기
if (readByteNum == 0) {
break;
}
//파라미터가 y면 리턴값 0
int y = strcmp(yn, "y");
//커멘드 라인의 옵션이 y이면
if(y == 0){
int retN = strcmp((const char *)buf, "\n"); // \n 문자열 비교
int retT = strcmp((const char *)buf, "\t"); // \t 문자열 비교
//개행표시
if(retN == 0){
// \n -> 개행 으로 출력
fwrite("개행", sizeof(char) * 6 , 1 , stdout);
//탭표시
}else if(retT == 0){
// /t -> 탭으로 출력
fwrite("탭", sizeof(char) * 3 , 1 , stdout);
}
}
//터미널에 표준출력
fwrite(buf, sizeof(char) , 1 , stdout);
}
//파일 닫기
fclose(readFile);
exit(0);
}
view raw head.c hosted with ❤ by GitHub

결과

 

#.파일의 마지막 몇 줄을 출력하는 tail 명령어를 구현하라. 출력하는 줄의 수는 고정값으로 한다.

풀이

//파일의 마지막 몇 줄을 출력하는 tail 명령어를 구현하라. 출력하는 줄의 수는 고정값으로 한다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//파일의 마지막 4줄 읽기
#define lastTailNum 4
int main(int argc, char *argv[]){
FILE* readFile;
unsigned char buf[2] = "";
long lSize;
int totalLine = 0;
//인자 개수 및 내용 출력
printf("argc : %d \n" , argc);
for (int i =0 ; i < argc; i++) {
printf("argv [%d] : %s] \n" , i , argv[i]);
};
//인자의 개수가 맞지 않을때
if (argc != 2) {
fprintf(stdout, "usage:인자의 개수가 잘못되었습니다. \n %s test.txt 또는 test.txt 형식입니다. \n" , argv[0]);
}
//argv[2]에 파일명이 존재
//파일열기 - 읽기전용
readFile = fopen(argv[1], "r");
//파일 열기 오류 처리
if (readFile == NULL) {
fprintf(stdout, "%s 오류가 발생했습니다." , argv[2]);
exit(1);
}
//파일 크기 구하기
fseek(readFile, 0 , SEEK_END);
lSize = ftell(readFile);
rewind(readFile);
printf("##파일사이즈 : %ld byte\n" , lSize);
//파일 읽기 - 파일의 전체 행 개수 구하기
for (; ; ) {
int readByteNum = fread(buf, sizeof(char) , 1 , readFile);
//파일 다읽으면 빠져나오기
if (readByteNum == 0) {
break;
}
int retN = strcmp((const char *)buf, "\n"); // \n 문자열 비교
//개행 체크
if(retN == 0){
totalLine += 1;
}
}
//파일 읽은 위치 처음으로 되돌리기
rewind(readFile);
// 마지막 n 번째 줄 까지 출력
int lastOutLine = 0;
int nowNum = 0;
lastOutLine = totalLine - lastTailNum;
for (; ; ) {
int readByteNum = fread(buf, sizeof(char) , 1 , readFile);
//파일 다읽으면 빠져나오기
if (readByteNum == 0) {
break;
}
//마지막 n 번째 줄 출력하기
if(lastTailNum <= totalLine){
if((lastOutLine <= nowNum) && (nowNum < totalLine)){
//터미널에 표준출력
fwrite(buf, sizeof(char) , 1 , stdout);
}
//개행 체크
int retN = strcmp((const char *)buf, "\n"); // \n 문자열 비교
if(retN == 0){ nowNum += 1; }
}else {
//전체 출력
//터미널에 표준출력
fwrite(buf, sizeof(char) , 1 , stdout);
}
} // for - end
printf("last tail num : %d \n" , lastTailNum);
printf("tatal line : %d \n" , totalLine);
fclose(readFile);
exit(0);
}
view raw tail.c hosted with ❤ by GitHub

결과

 

 

 

 

 

참고:모두를 위한 리눅스 프로그래밍