(공백(blank), 탭, 개행을 포함하여) 입력에서 다음 n개까지의 문자들을 읽고, 주소가 전달인자로 전달되는 배열에 그 결과를 저장하는 함수를 작성하고 테스트 하라.
#include <stdio.h>
#define SIZE 20
char *s_gets(char *st, int n);
int main(void)
{
char str[SIZE];
s_gets(str,SIZE);
puts(str);
}
char *s_gets(char *st, int n)
{
char *ret_val;
ret_val = fgets(st, n, stdin);
return ret_val;
}
n개의 문자들을 읽은 후에 또는 첫 번째 공백, 탭, 개행을 만난 후에 (어느 것이 먼저 일어나더라도) 읽기를 멈추도록 연습01에서 작성한 함수를 수정하고 테스트 하라.
#include <stdio.h>
#include <ctype.h>
#define SIZE 20
char *s_gets(char *st, int n);
int main(void)
{
char str[SIZE];
s_gets(str,SIZE);
puts(str);
}
char *s_gets(char *st, int n)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while(st[i] != '\0' && !isspace(st[i]))
i++;
if(st[i] != '\0')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
한 라인의 입력에서 첫 번째 단어만 읽어 배열에 저장하고, 나머지는 버리는 함수를 작성하고 테스트하라. 선두의 화이트 스페이스는 건너뛰어야 한다. 여기서 단어는 스페이스, 탭, 개행이 들어 있지 않는 연속된 문자들을 말한다.
#include <stdio.h>
#include <ctype.h>
#define SIZE 20
char *s_gets(char *st, int n);
int main(void)
{
char str[SIZE];
s_gets(str,SIZE);
puts(str);
}
char *s_gets(char *st, int n)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while(st[i] != '\0' && !isspace(st[i]))
i++;
if(st[i] != '\0')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
프로그래밍 연습문제 03에서 설명한 함수를, 읽을 수 있는 최대 문자수를 지정하는 제2 매개변수를 받아들이는 것을 제외하여 작성하고 테스트하라.
#include <stdio.h>
#include <ctype.h>
#define size 20
char *s_gets(char *st);
int main(void)
{
char str[size];
s_gets(str);
puts(str);
}
char *s_gets(char *st)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, size, stdin);
if(ret_val)
{
while(*st == ' ')
st++;
while(st[i] != '\0' && !isspace(st[i]))
i++;
if(st[i] != '\0')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
첫 번째 함수 매개변수로 지정되는 문자열에서 두 번째 함수 매개변수로 지정하는 문자가 처음 나타내는 위치를 찾는 함수를 작성하고 테스트 하라. 찾는데 성공하면, 함수는 그 문자를 가리키는 포인터를 리턴한다. (이것은 라이브러리함수 strchr()가 수행하는 기능과 같다.) 루프를 사용하여 함수에 입력 값들을 반복적으로 제공하는 완전한 프로그램을 만들어 작성한 함수를 테스트하라.
#include <stdio.h>
#define SIZE 20
char * str_chr(char *str, char ch);
int main(void)
{
char str[SIZE];
char *res_fgets;
char find_ch = 'j';
char *result_str;
while(1)
{
res_fgets = fgets(str, SIZE, stdin);
if (*res_fgets == '\0' || *res_fgets == '\n')
break;
putchar(find_ch);
putchar('\n');
result_str = str_chr(str, find_ch);
if(result_str)
puts(result_str);
else
puts("문자를 찾지 못했습니다.");
}
return 0;
}
char *str_chr(char *str, char ch)
{
char *fch = str;
while(*fch != ch)
{
if(*fch == '\0' || *fch == '\n')
return NULL;
fch++;
}
return fch;
}
하나의 문자와 하나의 문자열 포인터를 두 개의 함수 매개변수로 사용하는 is_within() 함수를 작성하라. 그 함수는 문자열 안에 그 문자가 들어 있으면 0이 아닌 값(참)을 리턴하고, 그렇지 않으면 0(거짓)을 리턴한다. 루프를 사용하여 함수에 입력값들을 반복적으로 제공하는 완전한 프로그램을 만들어 작성한 함수를 테스트하라.
#include <stdio.h>
#define SIZE 20
int is_within(char ch, char *str);
int main(void)
{
char str[SIZE];
char *res_fgets;
char find_ch = 'j';
int result;
while(1)
{
res_fgets = fgets(str, SIZE, stdin);
if (*res_fgets == '\0' || *res_fgets == '\n')
break;
putchar(find_ch);
putchar('\n');
result = is_within(find_ch, str);
if(result)
puts("찾는 문자가 존재합니다.");
else
puts("문자를 찾지 못했습니다.");
}
return 0;
}
int is_within(char ch, char *str)
{
int result = 0;
while(*str != ch)
{
if(*str == '\0' || *str == '\n')
return 0;
str++;
}
return 1;
}
strncpy(s1, s2, n) 함수는 s2에서 s1으로 정확히 n개의 문자들을 복사한다. 필요하면 s2를 자르거나 여분의 널 문자들로 채운다. 타깃 문자열은 s2의 길이가 n이거나 그 이상이면 널 문자로 종료되지 않을 수도 있다. 이 함수는 s1을 리턴한다. 이와 동일한 기능을 수행하는 함수를 직접 작성하고 mystrncpy()라고 부르라. 루프를 사용하여 함수에 입력 값들을 반복적으로 제공하는 완전한 프로그램을 만들어 작성한 함수를 테스트 하라.
#include <stdio.h>
#define SIZE 20
char *mystrncpy(char *s1, char *s2, int n);
int main(void)
{
char s1[SIZE], s2[SIZE];
char *res_fgets;
char *result_str;
while(1)
{
res_fgets = fgets(s2, SIZE, stdin);
if(*res_fgets == '\0' || *res_fgets == '\n')
break;
result_str = mystrncpy(s1, s2, SIZE);
puts(result_str);
}
return 0;
}
char *mystrncpy(char *s1, char *s2, int n)
{
int i = 0;
while(1)
{
if(i < n && s2[i] != '\0')
{
s1[i] = s2[i];
}
else
{
if(s2[i] == '\0')
{
while(getchar() != '\n')
continue;
}
s1[i] = '\0';
break;
}
i++;
}
return s1;
}
두 개의 문자열 포인터를 전달인자로 사용하는 함수 string_in()를 작성하라. 두 번째 문자열이 첫 번째 문자열 안에 있으면, 포함된 문자열이 시작되는 위치의 주소를 리턴한다. 예를 들어, string_in("hats", "at")은 hats에 있는 a의 주소를 리턴한다. 그렇지 않으면 널 포인터를 리턴한다. 루프를 사용하여 함수에 입력 값들을 반복적으로 제공하는 완전한 프로그램을 만들어 작성한 함수를 테스트하라.
#include <stdio.h>
#define SIZE 20
char *string_in(char *base_str, char *find_str);
int main(void)
{
char base_str[SIZE];
char find_str[SIZE] = "at";
char *res_fgets;
char *result_str;
while(1)
{
res_fgets = fgets(base_str, SIZE, stdin);
if(*res_fgets == '\0' || *res_fgets == '\n')
break;
result_str = string_in(base_str, find_str);
if(result_str)
puts(result_str);
else
puts("문자를 찾지 못했습니다.");
}
return 0;
}
char *string_in(char *base_str, char *find_str)
{
while(*base_str != '\0')
{
int index = 0;
while(base_str[index] == find_str[index])
{
if(base_str[index] == '\0'
|| base_str[index] == '\n')
break;
index++;
}
if(find_str[index] == '\0'
|| find_str[index] == '\n')
return base_str;
base_str++;
}
return NULL;
}
문자열의 내용을 거꾸로 뒤집은 문자열로 대체하는 함수를 작성하라. 루프를 사용하여 함수에 입력을 반복적으로 제공하는 완전한 프로그램을 만들어 작성한 함수를 테스트하라.
#include <stdio.h>
#define SIZE 20
void revers_str(char *str);
int main(void)
{
char str[SIZE];
char *res_fgets;
while(1)
{
res_fgets = fgets(str, SIZE, stdin);
if(*res_fgets == '\0' || *res_fgets == '\n')
break;
revers_str(str);
puts(str);
}
return 0;
}
void revers_str(char *str)
{
char temp_ch;
int size = 0;
while(str[size] != '\0' && str[size] != '\n')
size++;
if(str[size] == '\n')
str[size] = '\0';
size--;
for(int i = 0; i <= size/2; i++)
{
temp_ch = str[i];
str[i] = str[size - i];
str[size - i] = temp_ch;
}
}
문자열을 전달인자로 취하여, 그 문자열에 있는 스페이스들을 모두 제거하는 함수를 작성하라. 빈 라인을 입력할 때까지 라인들을 반복하여 읽는 루프를 사용하는 프로그램을 작성하여 그 함수를 테스트 하라. 프로그램은 그 함수를 각 입력 문자열에 적용하여, 그 결과를 표시해야 한다.
#include <stdio.h>
#include <ctype.h>
#define SIZE 20
void del_space(char *str);
int main(void)
{
char str[SIZE];
char *res_fgets;
while(1)
{
res_fgets = fgets(str, SIZE, stdin);
if(*res_fgets == '\0' || *res_fgets == '\n')
break;
del_space(str);
puts(str);
}
}
void del_space(char *str)
{
int n = 0;
while(str[n] != '\0')
{
if(isspace(str[n]))
{
str[n] = str[n+1];
if(str[n] == '\0')
return;
else
{
str[n+1] = ' ';
del_space(&(str[n+1]));
}
}
n++;
}
}
문자열을 10개까지 또는 EOF를 만날 때까지 읽는 프로그램을 작성하라. 둘중 어느 것이 먼저 일어나더라도 읽기를 멈춘다. 이 프로그램은 사용자가 메뉴로 다음과 같은 5가지 선택권을 제공해야 한다.
1. 문자열들의 원본리스트를 출력한다.
2. 문자열들을 ASCII 조회 순서로 출력한다.
3. 문자열들을 길이가 커지는 순서로 출력한다.
4. 문자열들을 첫 단어의 길이가 커지는 순서로 출력한다.
5. 프로그램을 종료한다.
이 프로그램은 사용자가 종료를 선택할 때까지 계속 실행되어야 한다. 물론 이 프로그램은 메뉴에 제시된 작업을 실제로 수행해야 한다.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LENGTH 10
#define SIZE 40
int print_menu(void);
void print_origin(char (*str)[SIZE]);
void print_orderby_ascii(char (*str)[SIZE]);
void print_orderby_length(char (*str)[SIZE]);
void print_orderby_first_word_length(char (*str)[SIZE]);
int main(void)
{
char str[LENGTH][SIZE];
int eof_flag = 0;
char menu_choose = 0;
for(int i = 0; i < LENGTH; i++)
{
if(eof_flag == 0)
eof_flag = scanf("%s", str[i]);
if(eof_flag == EOF)
{
for(int j = 0; j < SIZE; j++)
str[i][j] = '\0';
}
else
{
eof_flag = 0;
}
}
while(menu_choose != 5)
{
menu_choose = print_menu();
switch(menu_choose)
{
case 1:
print_origin(str);
break;
case 2:
print_orderby_ascii(str);
break;
case 3:
print_orderby_length(str);
break;
case 4:
print_orderby_first_word_length(str);
break;
}
}
return 0;
}
int print_menu(void)
{
int choose;
for(int i = 0; i < 40; i++)
putchar('/');
putchar('\n');
printf("1. 문자열들의 원본리스트를 출력한다.\n");
printf("2. 문자열들을 ASCII 조회 순서로 출력한다.\n");
printf("3. 문자열들을 길이가 커지는 순서로 출력한다.\n");
printf("4. 문자열들을 첫 단어의 길이가 커지는 순서로 출력한다.\n");
printf("5. 프로그램을 종료한다.\n");
while(1)
{
printf(">>");
if(scanf("%d", &choose) != 1)
{
while(getchar() != '\n')
continue;
}
else
{
switch(choose)
{
case 1: case 2:
case 3: case 4:
case 5:
break;
default:
continue;
}
break;
}
}
for(int i = 0; i < 40; i++)
putchar('/');
putchar('\n');
return choose;
}
void print_origin(char (*str)[SIZE])
{
int i = 0;
while (i < LENGTH && str[i][0] != '\0')
{
puts(str[i]);
i++;
}
}
void print_orderby_ascii(char (*str)[SIZE])
{
// strcmp
int i = 0;
char res_str[LENGTH][SIZE];
char temp[SIZE];
while(i < LENGTH && str[i][0] != '\0')
{
strcpy(res_str[i], str[i]);
i++;
}
i = 0;
while(i < LENGTH && str[i][0] != '\0')
{
for(int j = i + 1; j < LENGTH; j++)
{
if(strcmp(res_str[i], res_str[j]) > 0)
{
strcpy(temp, res_str[i]);
strcpy(res_str[i], res_str[j]);
strcpy(res_str[j], temp);
}
}
i++;
}
print_origin(res_str);
}
void print_orderby_length(char (*str)[SIZE])
{
// strlen
int i = 0;
char res_str[LENGTH][SIZE];
char temp[SIZE];
while(i < LENGTH && str[i][0] != '\0')
{
strcpy(res_str[i], str[i]);
i++;
}
i = 0;
while(i < LENGTH && str[i][0] != '\0')
{
for(int j = i + 1; j < LENGTH; j++)
{
if(strlen(res_str[i]) > strlen(res_str[j]))
{
strcpy(temp, res_str[i]);
strcpy(res_str[i], res_str[j]);
strcpy(res_str[j], temp);
}
}
i++;
}
print_origin(res_str);
}
void print_orderby_first_word_length(char (*str)[SIZE])
{
int i = 0, j = 0;
char res_str[LENGTH][SIZE];
char temp[SIZE];
while(i < LENGTH && str[i][0] != '\0')
{
j = 0;
while( !isspace(str[i][j]) )
{
res_str[i][j] = str[i][j];
j++;
}
res_str[i][j-1] = '\0';
i++;
}
i = 0;
while(i < LENGTH && str[i][0] != '\0')
{
for(j = i + 1; j < LENGTH; j++)
{
if(strlen(res_str[i]) > strlen(res_str[j]))
{
strcpy(temp, res_str[i]);
strcpy(res_str[i], res_str[j]);
strcpy(res_str[j], temp);
}
}
i++;
}
print_origin(res_str);
}
EOF를 만날 때까지 입력을 읽어서 단어 수, 대문자 수, 소문자 수, 구두점 수, 숫자 수를 보고하는 프로그램을 작성하라. ctype.h 계열의 함수들을 사용하라.
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
int word_flag = 0;
int number_flag = 0;
int word_cnt = 0;
int up_cnt = 0;
int low_cnt = 0;
int punc_cnt = 0;
int num_cnt = 0;
while(1)
{
printf(">> ");
ch = getchar();
if(ch == EOF)
break;
if(isupper(ch)) up_cnt++;
else if(islower(ch)) low_cnt++;
else if(ispunct(ch)) punc_cnt++;
if(isspace(ch))
{
if(word_flag == 1) word_flag = 0;
else if(number_flag == 1) number_flag = 0;
}
else if(!isspace(ch))
{
if(word_flag == 0 && isalpha(ch))
{
word_flag = 1;
word_cnt++;
if(number_flag == 1)
{
number_flag = 0;
num_cnt--;
}
}
else if(number_flag == 0 && isdigit(ch))
{
number_flag = 1;
num_cnt++;
if(word_flag == 1)
{
word_flag = 0;
word_cnt--;
}
}
}
}
printf("카운트 결과\n");
printf("단어 수 : %d\n", word_cnt);
printf("대문자 수 : %d\n", up_cnt);
printf("소문자 수 : %d\n", low_cnt);
printf("구두점 수 : %d\n", punc_cnt);
printf("숫자 수 : %d\n", num_cnt);
}
명령행 전달인자들을 역순으로 에코하는 프로그램을 작성하라. 예를 들어, 명령행 전달인자들이 see you later로 주어졌다면, 프로그램은 later you see라고 출력해야 한다.
#include <stdio.h>
int main(int argc, char *argv[])
{
for(int i = argc - 1; i > 0; i--)
{
printf("%s ", argv[i]);
}
putchar('\n');
return 0;
}
명령행으로 동작시키는 멱승법(power-law) 프로그램을 적성하라. 명령행의 첫번째 전달인자는 어떤 멱승을 구할 double형 밑수가 되고, 두 번째 전달인자는 정수형 지수가 되어야 한다.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int check_number(char *str);
double pow_func(double base, int exponent);
int main(int argc, char *argv[])
{
double base;
int exponent;
if(check_number(argv[1]) == 0)
{
puts("밑수가 순수한 수가 아닙니다.");
}
else if(check_number(argv[2]) == 0)
{
puts("지수가 순수한 수가 아닙니다.");
}
else
{
base = atof(argv[1]);
exponent = atoi(argv[2]);
printf("멱승의 결과는 %.2lf\n", pow_func(base, exponent));
}
return 0;
}
int check_number(char *str)
{
for(int i = 0; str[i] != '\0'; i++)
{
if(isdigit(str[i]) == 0)
return 0;
}
return 1;
}
double pow_func(double base, int exponent)
{
for(int i = 1; i < exponent; i++)
{
base *= base;
}
return base;
}
문자 분류 함수들을 사용하여 atoi()와 동일한 기능을 수행하는 함수를 작성하라. 이 버전의 경우 입력 문자열이 순수한 수가 아니라면 0의 값을 반환 하도록 하라.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SIZE 10
int atoi_func(char *str);
int main(void)
{
char str[SIZE];
while(1)
{
puts("종료하려면 0을 입력하세요.");
printf(">>");
scanf("%s", str);
if(strcmp(str, "0") == 0)
break;
printf("%d\n", atoi_func(str));
}
}
int atoi_func(char *str)
{
int num = 0;
char digits[] = {'0','1','2','3','4','5','6','7','8','9'};
for(int i = 0; str[i] != '\0'; i++)
{
if(isdigit(str[i]) == 0)
return 0;
num *= 10;
for(int j = 0; j < 10; j++)
{
if(str[i] == digits[j])
{
num += j;
break;
}
}
}
return num;
}
파일 끝에 도달할 때까지 입력을 읽고, 그것을 디스플레이에 에코하는 프로그램을 작성하라. 프로그램은 다음과 같은 명령행 전달인자들을 인식하고 그 기능을 구현해야 한다.
-p : 입력을 그대로 출력한다.
-u : 입력을 모두 대문자로 변경하여 출력한다.
-l : 입력을 모두 소문자로 변경하여 출력한다.
또한 명령행 전달인자가 없다면, 프로그램이 -p 전달인자와 사용된 것처럼 실행되게 하라.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
char option = 'p';
char in, out;
if(argc > 1)
{
if(strcmp(argv[1], "-p") == 0)
option = 'p';
else if(strcmp(argv[1], "-u") == 0)
option = 'u';
else if(strcmp(argv[1], "-l") == 0)
option = 'l';
}
while(1)
{
in = getchar();
if(in == EOF)
break;
switch(option)
{
case 'p':
out = in;
break;
case 'u':
out = toupper(in);
break;
case 'l':
out = tolower(in);
break;
}
putchar(out);
}
putchar('\n');
return 0;
}