ExamRank02_review



1️⃣ 첫번째 문제

(1) 문제

문장을 두개 입력받았을때, 두문장에 모두 있는 문자만 중복없이 출력하고 '\n'까지 붙여서 출력하시오.(단, 순번은 첫문장기준)
문장이 두개가 아닐시에 '\n'(줄바꿈)문자만 출력하시오.

(2) 문제풀이

#include <unistd.h>

#define TRUE (1)
#define FALSE (-1)

int ft_strlen(char *str)
{
    int len;

    len = 0;
    while (*str++ != '\0')
            len++;
    return (len);
}

int find_word(char c, char *str, int cnt)
{
    while (*str != '\0' && cnt > 0)
    {
        if (c == *str)
            return (TRUE);
        str++;
        cnt--;
    }
    return (FALSE);
}

int main(int argc, char *argv[])
{
    char    *s1;
    char    *s2;
    int     cnt;

    if (argc == 3)
    {
        s1 = argv[1];
        s2 = argv[2];
        cnt = 0;

        while (*s1 != '\0')
        {
            if (find_word(*s1, s2, ft_strlen(s2)) == TRUE && find_word(*s1, s1 - cnt, cnt) == FALSE)
                write(1, s1, 1);
            s1++;
            cnt++;
        }
    }
    write(1, "\n", 1);
}
  • 결과값 출력은 원하는 데로 잘나왔습니다. 하지만 오답으로 처리됐습니다.
  • 아마도 제가 구현한 int find_word(char c, char *str, int cnt)함수는 세번째 인자로 검사할범위의 크기를 인자로 받는데 다음의 이유때문에 시간초과가 난 것 같습니다.
    1. 본함수의 while문안에서 find_word(*s1, s2, ft_strlen(s2))로 작성하면서 반복문을 돌때마다 s2의 길이를 계속해서 확인
    2. 두번째 조건에서 중복문자체크를 할때 s1문자열을 반복적으로 훝어봄
  • 그래서 char *temp를 선언하여 중복문자를 담도록하고 처리하도록 하고 쓸데없는 반복이 없도록 처리하였습니다.
      while (*s1 != '\0')
          {
              if (find_word(*s1, s2) == TRUE && find_word(*s1, temp) == FALSE)
              {
                  write(1, s1, 1);
                  temp[cnt] = *s1;
                  cnt++;
              }
              s1++;
          }
    
    • 이렇게 바꿔주니 정답처리가 잘 되었습니다.
    • write함수를 호출할때마다 시간이 걸리기 때문에 다음과 같이 처리하면 좀 더 빠를 것 같습니다.
       write(1, temp, cnt + 1);
    

1️⃣ 두번째 문제

(1) 문제

  • get_next_line문제가 나오길 기대했지만 아쉽게도 ft_printf문제가 나왔습니다.
  • 그나마 다행인 것은 기존 printf함수의 기능중 일부만 구현하면 됐습니다.
    • %s, %d, %x서식자만 구현
    • 플래그옵션 구현x
    • 오직 .(정밀도) 옵션만 구현

(2) 문제풀이

  • 하지만 시간이 부족해서 %x서식자를 구현하지 못했고 fail하였습니다.
  • 아무리 일부분만 구현한다고해도 ft_printf함수를 짧은시간에 구현하는 것은 쉽지 않았습니다. 그나마 다행인 것은 시험에서는 norminette(규칙)을 무시해도 된다는 것 입니다. (norm규칙중에서 함수당 28줄 제한규칙이 까다로움)

< ft_printf.h >

#ifndef FT_PRINTF_H
# define FT_PRINTF_H

# include <stdarg.h>
# include <unistd.h>

# define TRUE (1)
# define FALSE (-1)

typedef struct tool_s {
    int point;
    int front;
    int back;
    char result[32];
} tool_t;

#endif

< ft_printf.c >

#include "ft_printf.h"

void    *ft_memset(void *str, int value, int size)
{
    unsigned char   *sp;

    sp = str;
    while (size-- > 0)
    {
        *sp = value;
        sp++;
    }
    return (str);
}

int     ft_strlen(char *str)
{
    int cnt;

    cnt = 0;
    while (*str++ != '\0')
        cnt++;
    return (cnt);
}

void	ft_itoa(int num, char *num_version, char *str)
{
	int     num_len;
	int	    cnt;
	int	    nb;

	num_len = ft_strlen(num_version);
	nb = num / num_len;
	cnt = 1;
	while (nb > 0)
	{
		nb /= num_len;
		cnt++;
	}
	str[cnt] = '\0';
	while (cnt > 0)
	{
		str[cnt - 1] = num_version[num % num_len];
		cnt--;
		num /= num_len;
	}
}

int check_word(char c, char *str)
{
    while (*str != '\0')
    {
        if (c == *str)
            return (TRUE);
        str++;    
    }
    return (FALSE);
}

void set_precision(const char **format, tool_t *fg, va_list ap)
{
    while (check_word(**format, "0123456789.") == TRUE)
    {
        if (**format == '.')
            fg->point = 1;
        else if (fg->point == 0)
            fg->front = fg->front * 10 + **format - '0';
        else
            fg->back = fg->back * 10 + **format - '0';
        (*format)++;
    }
}
void print_xd(char c, tool_t *fg, va_list ap, int *len)
{
    int result_len;
    int bigger;

    if (c == 'd')
        ft_itoa(va_arg(ap, int), "0123456789", fg->result);
    else if (c == 'x')
        ft_itoa(va_arg(ap, int), "0123456789abcdef", fg->result);
    result_len = ft_strlen(fg->result);\
    bigger = result_len > fg->back ? result_len : fg->back;
    fg->back = fg->back - result_len;
    while (fg->front - bigger > 0)
    {
        write(1, " ", 1);
        (*len)++;
        fg->front--;
    }
    while (fg->back > 0)
    {
        write(1, "0", 1);
        (*len)++;
        fg->back--;
    }
    write(1, fg->result, result_len);
    (*len) += result_len;    
}

void print_s(tool_t *fg, va_list ap, int *len)
{
    int result_len;
    char *result;

    result = va_arg(ap, char*);
    result_len = ft_strlen(result);
    if (fg->point == 1 && fg->back < result_len)
        result_len = fg->back;
    while (fg->front - result_len > 0)
    {
        write(1, " ", 1);
        (*len)++;
        fg->front--;
    }
    write(1, result, result_len);
    (*len) += result_len;
}

void set_format(const char **format, va_list ap, int *len)
{
    tool_t fg;

    ft_memset(&fg, 0, sizeof(fg));
    set_precision(format, &fg, ap);
    if (**format == 'd')
        print_xd('d', &fg, ap, len);
    else if (**format == 'x')
        print_xd('x', &fg, ap, len);
    else if (**format == 's')
        print_s(&fg, ap, len);
    (*format)++;
}

int ft_printf(const char *format, ...)
{
    va_list ap;
    int     len;

    len = 0;
    va_start(ap, format);
    {
        while (*format != '\0')
        {
            if (*format == '%')
            {
                format++;
                set_format(&format, ap, &len);
            }
            else
            {
                write(1, format, 1);
                len++;
                format++;
            }
        }
    }
    va_end(ap);
    return (len);
}

(3) fail에 대한 고찰

  • 시험은 총 2문제로 두번째문제를 풀지 못하여 시험에 통과하지 못했습니다.(21년 4월 29일 기준)
  • 그 이유에대해서는 (개인적)
    1. 첫번째 문제에서 런타임오류(시간초과)를 고려하지 않고 해결법을 고민하느라 시간이 많이 소모됨
    2. 두번째 문제에서 %d(10진수정수), %x(16진수정수) 서식자의 출력코드는 상당부분이 비슷한데 시간이 촉박해서 코드에 대한 큰 틀을 잡지않고 즉흥적으로 구현함
    3. 정밀도옵션(.)에 대한 지식이 정확하지않아 기존의 printf함수로 테스트를 해가면서 구현하느라 시간이 많이 소모됨
    4. 실수로 오타나거나 문법적으로 실수한 부분때문에 디버깅으로 시간이 많이 소모됨
  • 고쳐야될점 (개인적)
    1. 단순히 출력이되는 코드를 구현하는 것이 아닌 효율(속도)를 최대로 높힐 수 있는 코드를 짤 수 있도록 고민해야될 것 같습니다.
    2. ft_printf와 같이 다소 긴함수는 무작정 코드를 작성하기 보다 먼저 코드의 큰 그림을 구성하고 작성해야겠습니다.
    3. 처음에 코드를 작성할 때부터 문법의 오류나 실수가 나지않도록 연습을 많이해야될 것 같습니다.




© 2021.02. by kirim

Powered by kkrim