카테고리 없음

C언어 17주차 과제

yooongs 2021. 2. 7. 17:47

# 제출안내

 1. 방법 : 본인 블로그에 작성 후 본 게시판에 링크를 업로드

           또는 본 게시판에 작성. 제목은 '투자노트 금융공학 퀀트 프로그래밍 과정 x주차과제' 등으로 작성 

           (※ 본 게시판에 작성한 내용은 주기적으로 삭제 및 정리되오니 강의 내용을 가지고 

              있으시려면 본인 블로그에 작성하시오)

 2. 양 : 최종과제 스크린샷 1장 이상 첨부. 스크린샷을 반드시 첨부하시오.

 3. 기한 : 매주 일요일 오후 12시 전까지

 

 ​

# 기본과제 및 제출 양식

1. 문자열 편집을 위해 string.h 를 인클루드 하고 다음 문항에 답하시오. (2시간 소요)

  가. 문자 배열 "dhfl rhrl siasia"을 선언하시오.

  나. strtok 함수의 사용법은 아래와 같다.

 

    자른결과물 = strtok(원래문자열, 자를기준이되는 구분자 문자);

 

    이를 암기하시오. 또한, '가'에서 만든 문자열을 공백 " "를 기준으로 잘라 출력해보시오.

    https://dojang.io/mod/page/view.php?id=376 를 참조하시오.

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char a[30] = "dhfl rhrl siasia";
char* b;
b = strtok(a, " ");

while (b != NULL)
{
printf("%s\n", b);
b = strtok(NULL, " ");
}

return 0;
}

실행 결과

  다. '나'에서 자른 문자열을 result[3]을 만들고 잘린 문자를 각각 변수에 대입해보시오.

    https://dojang.io/mod/page/view.php?id=379를 참조하시오.

 

  라. '다'에서 만든 result[0], result[1], result[2] 를 printf로 출력하여 확인하시오. 

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char a[30] = "dhfl rhrl siasia";
char* result[3] = { NULL, };
int i = 0;
char* b = strtok(a, " ");

while (b != NULL)
{
result[i] = b;
i++;
b = strtok(NULL, " ");
}

printf("첫 번째 문장 :%s\n", result[0]);
printf("두 번째 문장 :%s\n", result[1]);
printf("세 번째 문장 :%s\n", result[2]);
return 0;
}

실행 결과

 

2. 다음 문항에 답하시오. (2시간 소요)

  가. 문자 포인터로 "dhfl rhrl siasia"을 선언하시오.

  나. strtok를 이용하여 공백문자 " "를 기준으로 잘라보시오. 이렇게 하면 오류가 나면서 실행이 안됨을 확인하시오. 또한 왜 실행이 되지 않는지 설명해보시오.

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *a = "dhfl rhrl siasia";
strtok(a, " ");
return 0;
}

-> 오류 (이유 : 문자열 포인터로 선언함과 동시에 " "로 초기화하면, 그 문자는 read only 영역에 저장되는데, 말 그대로 읽기만 할 수 있는 영역이기 때문에 오류 발생)

  다. '가'로 돌아가서, 문자 포인터를 만들고 malloc으로 문자 30개 분량의 메모리를 할당하시오. 

    strcpy로 문자포인터에 "dhfl rhrl siasia"을 넣으시오.

  라. strtok를 이용하여 공백문자 " "를 기준으로 잘라보시오. 이렇게 하면 오류가 없이 실행이 됨을 확인하시오. 또한 왜 실행이 되는지 설명해보시오.

: 동적 할당을 통해 메모리 할당 시 메모리 수정이 가능하다.

  마. 잘라낸 결과물을 result[3] 에 각각 저장하시오. 또한, result[0], result[1], result[2] 를 printf로 출력하여 확인하시오. 이후, 할당받은 메모리를 free하는 것을 잊지 말고 구현하시오.

  바. 문자열을 처리하기 위해, 1번문항의 문자배열을 이용한 방법과 2번문항의 문자포인터를 이용한 방법을 비교하고 장단점을 50자 이상 적어보시오.

: 문자 포인터 이용 시 메모리의 낭비 없이 사용 가능

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *a = "dhfl rhrl siasia";
char *b = (char *)malloc(sizeof(char) * 30);
char* result[3] = { NULL, };
int i = 0;

strcpy(b, a);
char *c = strtok(b, " ");

while (c != NULL)
{
result[i] = c;
i++;
c = strtok(NULL, " ");
}

printf("첫 번째 문장 :%s\n", result[0]);
printf("두 번째 문장 :%s\n", result[1]);
printf("세 번째 문장 :%s\n", result[2]);

free(b);
return 0;
}

실행 결과

 

3. 다음과 같은 문자 배열이 있다. (2시간 소요)

  Date[] = 2020-07-03(금요일);

  Time[] = 12:34:56;

  가. year,month,day,dow 를 저장할 적절한 데이터형으로 변수를 선언하시오. dow는 요일임.

  나. Date를 -또는 (또는 )으로 자르시오. 자른 결과물을 year,month,day,dow에 넣으시오.

    https://dojang.io/mod/page/view.php?id=378 를 참조하시오.

  다. hour,min,sec를 저장할 적절한 데이터형으로 변수를 선언하시오.

  라. Time를 :으로 자르시오. 자른 결과물을 hour,min,sec에 넣으시오.

  마. 가~라에서 만든 결과물을 이용하여, 다음과 같은 내용을 담은 문자열을 만드시오.

   "오늘은 2020년 07월 03일 금요일이고, 현재시간은 12시 34분 56초 입니다"

    힌트 : strcat를 이용하시오.

  바. '마'에서 만든 문자열을 printf해보시오.

 

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char Date[] = "2020-07-03(금요일)";
char Time[] = "12:34:56";
char* year, * month, * day, * dow; // dow = 요일
char* hour, * min, * sec;
char* result = (char *)malloc(100);

year = strtok(Date, "-()");
month = strtok(NULL, "-()");
day = strtok(NULL, "-()");
dow = strtok(NULL, "-()");

hour = strtok(Time, ":");
min = strtok(NULL, ":");
sec = strtok(NULL, ":");

strcpy(result, "오늘은 ");
strcat(result, year);
strcat(result, "년");
strcat(result, month);
strcat(result, "월");
strcat(result, day);
strcat(result, "일");
strcat(result, dow);
strcat(result, "이고, 현재시간은 : ");
strcat(result, hour);
strcat(result, "시");
strcat(result, min);
strcat(result, "분");
strcat(result, sec);
strcat(result, "초 입니다.");

printf("%s", result);


return 0;
}

 

실행 결과

 

# 심화과제 제출 양식( 안해도 됨 )

 

1. C에서는 문자열 치환 함수가 없다. 따라서, 치환을 위해서는 치환 함수를 직접 작성하여야 한다.

  가. http://mwultong.blogspot.com/2006/10/c-string-replace-all.html 를 참조하여 치환 함수를 구현해보시오. 자신이 구현할 수 없는 경우 소스를 그대로 복제하여 사용하여도 무방함.

  나. 문자열 "오리고기냠냠 돼지고기냠냠 소고기냠냠 닭고기냠냠"을 선언하시오.

  다. 공백을 기준으로 나누어, 변수에 저장하시오.

  라. "고기"를 "불고기"로 바꾸어 보고, 이를 출력해 보시오.

  마. "냠냠"을 "쩝쩝"으로 바꾸어보고, 이를 출력해 보시오.

  바. 치환은 구현방법을 몰라도 누군가 짜 놓은 위 함수를 이용하면 됨을 확인하고, 소스를 보관하도록 하시오.

 

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* replaceAll(char* s, const char* olds, const char* news) {
    char* result, * sr;
    size_t i, count = 0;
    size_t oldlen = strlen(olds); if (oldlen < 1) return s;
    size_t newlen = strlen(news);

    if (newlen != oldlen) {
        for (i = 0; s[i] != '\0';) {
            if (memcmp(&s[i], olds, oldlen) == 0) count++, i += oldlen;
            else i++;
        }
    }
    else i = strlen(s);

    int x = i + 1 + count * (newlen - oldlen);
    result = (char*)malloc(x);
    if (result == NULL) return NULL;

    sr = result;
    while (*s) {
        if (memcmp(s, olds, oldlen) == 0) {
            memcpy(sr, news, newlen);
            sr += newlen;
            s += oldlen;
        }
        else *sr++ = *s++;
    }
    *sr = '\0';

    return result;
}

int main() {
    char s[] = "오리고기냠냠 돼지고기냠냠 소고기냠냠 닭고기냠냠";
    char* s2;
    char* s3;
    printf("원본 : %s\n", s);
    s2 = replaceAll(s, "고기", "불고기");
    if (s2 != NULL) {
        printf("치환 : %s\n", s2);
    }
    else fputs("Replace String Error...\n", stderr);

    s3 = replaceAll(s2, "냠냠", "쩝쩝");
    if (s3 != NULL) {
        printf("치환 : %s\n", s3);
    }
    else fputs("Replace String Error...\n", stderr);
    
    return 0;
}

 

실행 결과

소스를 직접 구현하는데에 어려움이 있어 구글링을 통해 그냥 썼다. 프린트로 만들어 함수를 이해하고 암기했음.

size_t : size_t는 해당 시스템에서 어떤 객체나 값이 포함할 수 있는 최대 크기의 데이터를 표현하는 타입으로 반드시 unsigned 형으로 나타낸다. 

C99에서의 size_t의 정의 : size_t can store the maximum size of a theoretically possible object of any type.

 

memcmp 함수 원형과 설명
memcpy 함수 원형과 설명

 

 

2. 다음 소스는 네이버 모 카페의 가입인사 게시판의 태그 중 일부이다.

  소스 : http://tujanote.cafe24.com/bbs/board.php?bo_table=club&wr_id=1428

  이를 이용하여 회원의 아이디를 수집하는 프로그램을 구현하고자 한다.

 

  가. 전체 소스를 char[] 또는 char* 변수를 이용하여 하나의 변수에 넣으시오. (소스에있는 "는 모두 삭제하여야 함. 한글 등을 이용하여 "를 공백또는 '로 일괄변환하시오)

  나. 아이디가 들어있는 부분은 다음과 같다.

    <a href="#" class="m-tcol-c" onclick="ui(event, 'angelpes78',3,'내버들','11786850','', 'false', 'true', 'goodhakwon', 'false', '146'); return false;">내버들</a><span class="mem-level">

    이를 이용하기 위해 ui(event, 를 기준으로 자르시오. (이렇게 하면 10+1개의 문자열로 분리된다.)

  다. 잘라온 부분을 ,를 기준으로 다시 자르시오. 그러면, 세번째 값에 ID가 들어가게 된다.

  라. '다'를 이용하여 ID를 10개 추출하시오.

  마. 추출한 ID에 영어,숫자 이외의 문자가 있는지 검사하고, 있다면 모두 지우시오. 예를들어, '는 지워야함.

  바. 추출한 ID에 @naver.com을 붙여 이메일 배열을 만드시오.

  사. '다'에서, 닉네임을 추출하고 닉네임 배열을 만드시오.

  아. 만든 ID와 닉네임 배열을 출력해보시오.

  자. '닉네임(이메일)'님, 경품에 당첨되셨습니다! 를 출력하는 스팸메시지를 만들어 보시오.

 

#pragma warning (disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {
    char* htmlCode = (char *)malloc(100000);

    strcpy(htmlCode, "~17주차 재료~");


    char* userID[10]; // 10명의 유저 아이디를 담을 변수
    char* userNickName[10]; // 10명의 유저 닉네임을 담을 변수
    char* userEmail[10]; // 생성해 낼 메일들을 담을 변수

    for (int i = 0; i < 10; i++) { 
        userID[i] = strstr(htmlCode, "ui(event,");
        htmlCode = userID[i] + 1;
    }
    
    for (int i = 0; i < 10; i++) {
        userNickName[i] = userID[i];
        for (int j = 0; j < 3; j++) {
            userNickName[i] = strchr(userNickName[i], ',');
            userNickName[i]++;
        }
        userNickName[i] = strchr(userNickName[i], '\'');
        userNickName[i]++;
        strtok(userNickName[i], "\'");
    }
    
    printf("추출한 ID 목록\n");

    for (int i = 0; i < 10; i++) {
        userID[i] = strchr(userID[i], '\'');
        userID[i]++;
        strtok(userID[i], "\'");
        printf("%d. %s\n", i+1, userID[i]);
    }

       
    printf("\n생성한 이메일 목록\n");
    for (int i = 0; i < 10; i++) {
        userEmail[i] = (char*)malloc(30);
        strcpy(userEmail[i], userID[i]);
        strcat(userEmail[i], "@naver.com");
        printf("%d. %s\n", i+1, userEmail[i]);
    }
   
    printf("\n");
    for (int i = 0; i < 10; i++) {
        printf("%s(%s)님 경품에 당첨되셨습니다. 축하합니다!\n", userNickName[i],userEmail[i]);
    }

    for (int i = 0; i < 10; i++) {
        free(userEmail[i]);
    }
    return 0;
}

실행 결과
모식도 

 

구조를 짜는게 헷갈려서 글로 풀어 대충 가닥을 잡은 뒤 구글+답지를 참조하여 해결했다.

 

처음엔 ID분리 -> 출력 , 이메일 생성 -> 출력 이런식으로 했는데 자꾸 오류가 났었음.

왜그런가 했더니 ID분리 과정에서 strtok으로 이미 userID를 원본과 다르게 수정해놓고, 이메일 생성시에 그것을 다시 가져다 쓰려고 하다보니 생긴 문제였다.

 

그리고 마지막으로 free(htmlCode); 를 넣어 main() 처음에 해준 동적 메모리 할당을 해주려고 했는데 자꾸 오류가 난다..이건 뭔지 모르겠음