[질문]System Call인 write()함수로 printf()를 흉내내기?

불량도ㅐㅈㅣ의 이미지

어제 일요일 저녁부터 유닉스 프로그래밍을 짜고 있는데..도저히 감이 안 와서 이렇게 글을 올립니다.

숙제가 모냐하면 cat 명령어를 만들어 보라는 겁니다.

조건이 첫번째 숙제는 stdio.h에 있는 함수만 사용하고,

두번째 숙제는 system call만 이용하라는 겁니다.

C 라이브러리 이용하는 것은 좀 머리에 쥐가 나기 시작하니 풀리던데

system call 이용하는 것은 도저히 모르겠네요.

구현해야 할것 wrote:
$ gcc -o command command.c
$ ./command alpha.txt
This is the file, ALPHA.
$ ./command bravo.txt
This is another file, BRAVO.
$ ./command alpha.txt bravo.txt
This is the file, ALPHA.
This is another file, BRAVO.
$ ./command < alpha.txt
This is the file, ALPHA.
$ ./command alpha.txt charlie.txt bravo.txt
This is the file, ALPHA.
./command: charlie.txt: No such file or directory
This is another file, BRAVO.
$

저 빨간 부분에서 막힙니다.

첫번째 거는 stdio.h errno.h를 이용해 쉽게 풀었지만,

write로 저 문장을 쓰려고 하니 머리가 아프네요.

system call 짠 소스 wrote:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define SIZE 1024

int main(int argc, char *argv[])
{
char buffer[];
char * filename;
size_t nread;
int fd;
int i;

char str[26]="No such file or directory";

char enterkey[1];
enterkey[0] = 10;


...생략...
else
{
for( i=1; i<argc ; i++)
{
filename = argv[i];
if( (fd=open(filename,O_RDONLY)) == -1 )
{
write(2,argv[0],sizeof(argv[0]));
write(2,": ",2);
write(2,filename,sizeof(filename));
write(2,": ",2);
write(2,str,sizeof(str));
write(2,enterkey,sizeof(enterkey));

}

...생략...

printf() 대충 흉내 내본다고 write로 엄청 삽질을 하고 있습니다.

문제를 저걸 실행할경우

결과값 wrote:
$./command alpha.txt charlie.txt bravo.txt
This is the file, ALPHA.
./co: char: No such file or directory
This is another file, BRAVO.

결과 값이 짤려 나옵니다.

그 이유가 궁금해서 알아보니

Quote:
(gdb) display
2: sizeof filename = 4
1: sizeof argv[0] = 4

4byte 밖에 못 읽네요.ㅡ.ㅡ

힌트 좀 주세요...ㅡ.ㅜ

최종호의 이미지

헉,, sizeof 가 아니라 strlen() 을 쓰셔야죵..
sizeof 파라메터로 character pointer 가 들어가니 당연히
포인터의 크기인 4를 리턴한 거죵..
문자열의 길이를 구하려면 strlen() 을 쓰세요.

불량도ㅐㅈㅣ의 이미지

최종호 wrote:
헉,, sizeof 가 아니라 strlen() 을 쓰셔야죵..
sizeof 파라메터로 character pointer 가 들어가니 당연히
포인터의 크기인 4를 리턴한 거죵..
문자열의 길이를 구하려면 strlen() 을 쓰세요.

헛 그게 있었군요....

전 그것도 stdio.h에 있는 함수인줄 알고...ㅡ.ㅡ

감사합니다...^^

문근영 너무 귀여워~~

mach의 이미지

sizeof() == strlen ()?

음 묘한 발상을 하셨네요.

strlen()같은 스트링관련 함수도 사용하지 말라고 했다면,
my_strlen()을 만들어서 쓰면 되겠군요.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

불량도ㅐㅈㅣ의 이미지

mach wrote:
sizeof() == strlen ()?

음 묘한 발상을 하셨네요.

strlen()같은 스트링관련 함수도 사용하지 말라고 했다면,
my_strlen()을 만들어서 쓰면 되겠군요.

컬컬컬....

저두 황당하네요...어제는 왜 그게 생각나지 않았을까?? ㅡ.ㅡ

문근영 너무 귀여워~~

mach의 이미지

그런데, 제목대로,

Quote:
[질문]System Call인 write()함수로 printf()를 흉내내기?

를 만족하는 것이라면,
1. 포매팅(%어쩌구.....)
2. 버퍼링(이게 키포인트인듯)
이 두가지를 만족시키는 것으로 보면 될듯합니다.

sprintf() + write()로 구성하면 될 듯합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

불량도ㅐㅈㅣ의 이미지

mach wrote:
sprintf() + write()로 구성하면 될 듯합니다.

stdio.h 쓰면 안되고 오직 시스템 콜만으로 작성해야 하거든요..ㅡ.ㅡ

문근영 너무 귀여워~~

최종호의 이미지

mach wrote:
sizeof() == strlen ()?

sizeof 는 연산자로 알고 있는데, mach님이 쓴 걸 보니
sizeof == strlen() 으로 쓰지 않고 왜 sizeof() == strlen() 으로 썼을까 궁금해졌습니다.
저도 생각해보니 sizeof 쓸때는 항상 () 와 함께 썼었거든요.

찾아봤더니만 sizeof 가 type의 크기를 알아볼 때는
sizeof(type) 식으로 쓰게 되어 있네요.
unary-expression 의 크기를 알아볼 때는 괄호가 필요 없고요.
근데 sizeof 가 unary operator 라서 상당히 우선 순위가 높기 때문에
대부분 괄호를 필요로 할 듯 하네요.

int size = sizeof(int);
size = sizeof size;
size = sizeof(size);
printf("%d\n", sizeof 1 + 2);
printf("%d\n", sizeof (1 + 2));

흠...

sodomau의 이미지

printf 와 비슷하게 만들기는 그렇게 어렵지 않을텐데요..
포맷 스트링의 내용을 확인하면서
%d 와 같은 directive 가 나올 때마다 포맷 스트링이 저장된
뒤쪽의 스택을 하나씩 쫓아가면서 출력해주면 되니까요...

void Printf(char *fmt, ... )
{
    void *ptr = (void *)fmt;
    char *ch = fmt;
    while(*ch)
    {
        switch(*ch){ 
           ...
           // 디렉티브에 따라서 ptr 값 더해가며 알아서 write()
        }
        ch++;
    }
}

머 적당히 이정도면 쉽게 짜실 수 있을텐데요..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.