모두의 코드
모두의 코드

총 42 개의 강의로 준비된 씹어먹는 C 언어 강좌를 통해 C 언어의 처음부터 끝까지 배우실 수 있습니다! 특히 악명 높은 C 언어의 포인터나, 어려운 개념들을 충실히 짚고 넘어갑니다.

이 강좌는 2010년에 완결되었지만, 지속적으로 개선 및 보완하고 있습니다.

C 언어 문법을 아시는 분들이라면, 씹어먹는 C++ 강좌를 통해 C++ 기초 부터 최근의 C++ 17 까지 모든 내용을 배우실 수 있습니다. C 언어와 C++ 의 기본적인 문법이 비슷하기 때문에, C 언어를 어느 정도 아는 독자를 가정하여 쓰여져 있습니다.

이 강좌는 2020년에 완결되었고 총 50 개의 강좌가 준비되어 있습니다.

사이트 내에서 검색 하기
C 언어 레퍼런스
표준 입출력 라이브러리 stdio.h
문자열 관련 라이브러리 string.h
시간 관련 라이브러리 time.h
C ++ 레퍼런스
문자열 라이브러리 string
알고리즘 라이브러리 algorithm
최근 댓글
기존 utils.h와 utility.cpp를 최대한 살리는 방향으로 진행해 봤습니다. 우선 밑에 포아송분포님이 말씀해주신대로 using std::string;에서 빠진 세미클론(;)을 넣어주시고 나머지 부분은 아래와 같습니다. #include <iostream> #include <fstream> #include "utils.h" class Cell; class Table; class Cell { protected: int x, y; Table* table; string data; public: virtual string stringify(); virtual int to_numeric(); Cell(string data, int x, int y, Table* table); }; Cell::Cell(string data, int x, int y, Table* table) : data(data), x(x), y(y), table(table) {} string Cell::stringify() { return data; } int Cell::to_numeric() { return 0; } class Table { protected: // 행 및 열의 최대 크기 int max_row_size, max_col_size; // 데이터를 보관하는 테이블 // Cell* 을 보관하는 2차원 배열이라 생각하면 편하다 Cell*** data_table; public: Table(int max_row_size, int max_col_size); ~Table(); // 새로운 셀을 row 행 col 열에 등록한다. void reg_cell(Cell* c, int row, int col); // 해당 셀의 정수값을 반환한다. // s : 셀 이름 (Ex. A3, B6 과 같이) int to_numeric(const string& s); // 행 및 열 번호로 셀을 호출한다. int to_numeric(int row, int col); // 해당 셀의 문자열을 반환한다. string stringify(const string& s); string stringify(int row, int col); virtual string print_table() = 0; }; Table::Table(int max_row_size, int max_col_size) : max_row_size(max_row_size), max_col_size(max_col_size) { data_table = new Cell * *[max_row_size]; for (int i = 0; i < max_row_size; i++) { data_table[i] = new Cell * [max_col_size]; for (int j = 0; j < max_col_size; j++) { data_table[i][j] = NULL; } } } Table::~Table() { for (int i = 0; i < max_row_size; i++) { for (int j = 0; j < max_col_size; j++) { if (data_table[i][j]) delete data_table[i][j]; } } for (int i = 0; i < max_row_size; i++) { delete[] data_table[i]; } delete[] data_table; } void Table::reg_cell(Cell* c, int row, int col) { if (!(row < max_row_size && col < max_col_size)) return; if (data_table[row][col]) { delete data_table[row][col]; } data_table[row][col] = c; } int Table::to_numeric(const string& s) { // Cell 이름으로 받는다. int col = s[0] - 'A'; int row = atoi(s.c_str() + 1) - 1; if (row < max_row_size && col < max_col_size) { if (data_table[row][col]) { return data_table[row][col]->to_numeric(); } } return 0; } int Table::to_numeric(int row, int col) { if (row < max_row_size && col < max_col_size && data_table[row][col]) { return data_table[row][col]->to_numeric(); } return 0; } string Table::stringify(const string& s) { // Cell 이름으로 받는다. int col = s[0] - 'A'; int row = atoi(s.c_str() + 1) - 1; if (row < max_row_size && col < max_col_size) { if (data_table[row][col]) { return data_table[row][col]->stringify(); } } return 0; } string Table::stringify(int row, int col) { if (row < max_row_size && col < max_col_size && data_table[row][col]) { return data_table[row][col]->stringify(); } return ""; } std::ostream& operator<<(std::ostream& o, Table& table) { o << table.print_table(); return o; } class TxtTable : public Table { string repeat_char(int n, char c); // 숫자로 된 열 번호를 A, B, .... Z, AA, AB, ... 이런 순으로 매겨준다. string col_num_to_str(int n); public: TxtTable(int row, int col); // 텍스트로 표를 깨끗하게 출력해준다. string print_table(); }; TxtTable::TxtTable(int row, int col) : Table(row, col) {} // 텍스트로 표를 깨끗하게 출력해준다. string TxtTable::print_table() { string total_table; int* col_max_wide = new int[max_col_size]; for (int i = 0; i < max_col_size; i++) { unsigned int max_wide = 2; for (int j = 0; j < max_row_size; j++) { if (data_table[j][i] && data_table[j][i]->stringify().length() > max_wide) { max_wide = data_table[j][i]->stringify().length(); } } col_max_wide[i] = max_wide; } // 맨 상단에 열 정보 표시 total_table += " "; int total_wide = 4; for (int i = 0; i < max_col_size; i++) { if (col_max_wide[i]) { int max_len = std::max(2, col_max_wide[i]); total_table += " | " + col_num_to_str(i); total_table += repeat_char(max_len - col_num_to_str(i).length(), ' '); total_wide += (max_len + 3); } } total_table += "\n"; // 일단 기본적으로 최대 9999 번째 행 까지 지원한다고 생각한다. for (int i = 0; i < max_row_size; i++) { total_table += repeat_char(total_wide, '-'); total_table += "\n" + std::to_string(i + 1); total_table += repeat_char(4 - std::to_string(i + 1).length(), ' '); for (int j = 0; j < max_col_size; j++) { if (col_max_wide[j]) { int max_len = std::max(2, col_max_wide[j]); string s = ""; if (data_table[i][j]) { s = data_table[i][j]->stringify(); } total_table += " | " + s; total_table += repeat_char(max_len - s.length(), ' '); } } total_table += "\n"; } return total_table; } string TxtTable::repeat_char(int n, char c) { string s = ""; for (int i = 0; i < n; i++) s.push_back(c); return s; } // 숫자로 된 열 번호를 A, B, .... Z, AA, AB, ... 이런 순으로 매겨준다. string TxtTable::col_num_to_str(int n) { string s = ""; if (n < 26) { s.push_back('A' + n); } else { char first = 'A' + n / 26 - 1; char second = 'A' + n % 26; s.push_back(first); s.push_back(second); } return s; } class HtmlTable : public Table { public: HtmlTable(int row, int col); string print_table(); }; class CSVTable : public Table { public: CSVTable(int row, int col); string print_table(); }; HtmlTable::HtmlTable(int row, int col) : Table(row, col) {} string HtmlTable::print_table() { string s = "<table border='1' cellpadding='10'>"; for (int i = 0; i < max_row_size; i++) { s += "<tr>"; for (int j = 0; j < max_col_size; j++) { s += "<td>"; if (data_table[i][j]) s += data_table[i][j]->stringify(); s += "</td>"; } s += "</tr>"; } s += "</table>"; return s; } CSVTable::CSVTable(int row, int col) : Table(row, col) {} string CSVTable::print_table() { string s = ""; for (int i = 0; i < max_row_size; i++) { for (int j = 0; j < max_col_size; j++) { if (j >= 1) s += ","; // CSV 파일 규칙에 따라 문자열에 큰따옴표가 포함되어 있다면 "" 로 // 치환하다. string temp; if (data_table[i][j]) temp = data_table[i][j]->stringify(); for (int k = 0; k < temp.length(); k++) { if (temp[k] == '"') { // k 의 위치에 " 를 한 개 더 집어넣는다. temp.insert(k, 1, '"'); // 이미 추가된 " 를 다시 확인하는 일이 없게 하기 위해 // k 를 한 칸 더 이동시킨다. k++; } } temp = '"' + temp + '"'; s += temp; } s += '\n'; } return s; } int main() { TxtTable table1(5, 5); std::ofstream out1("test.txt"); table1.reg_cell(new Cell("Hello~", 0, 0, &table1), 0, 0); table1.reg_cell(new Cell("C++", 0, 1, &table1), 0, 1); table1.reg_cell(new Cell("Programming", 1, 1, &table1), 1, 1); std::cout << std::endl << table1; out1 << table1; CSVTable table2(5, 5); std::ofstream out2("test.csv"); table2.reg_cell(new Cell("Hello~", 0, 0, &table2), 0, 0); table2.reg_cell(new Cell("C++", 0, 1, &table2), 0, 1); table2.reg_cell(new Cell("Programming", 1, 1, &table2), 1, 1); out2 << table2; HtmlTable table3(5, 5); std::ofstream out3("test.html"); table3.reg_cell(new Cell("Hello~", 0, 0, &table3), 0, 0); table3.reg_cell(new Cell("C++", 0, 1, &table3), 0, 1); table3.reg_cell(new Cell("Programming", 1, 1, &table3), 1, 1); out3 << table3; }
xxxxxseed 05.07
/* 이번 편은 정말 재밌었습니다! 직접 코드를 짜며 2개 경험한 것이 있습니다. 1. 배열의 길이에 변수를 사용할 수 있습니다. 2. IDE에서, scanf는 deprecated되었고, 대신 scanf_s를 쓰라고 하더군요. 그래서 scanf는 scanf_s로, printf도 혹시 몰라 printf_s로 변경했습니다. 찾아보니 _s가 없는 버전보다 더 안전해졌다고 하네요. 다만 불필요한 것이거나 성능이 떨어질 수도 있을 것 같네요. 제 코드는 첫 번째 줄에 학생 수, 두 번째 줄부터 학생 점수를 입력받고, 그 이후 1등부터 순서대로 점수, 막대그래프로 표현합니다. 정렬 방식을 잘 몰라 끔찍이도 비효율적인 방법으로 한 것 같네요. */ #include <stdio.h> int main() { int size, i, j; printf_s("학생의 수: "); scanf_s("%d", &size); int arr[size]; int result[size] = {}; //미리 다 0으로 해놓음. 안 그러면 뒤에 비교할 때 오류 날 듯. for (i = 0; i < size; i++) { printf_s("%d번째 학생의 점수: ", i + 1); scanf_s("%d", &arr[i]); } // 모든 점수에 대해 for (i = 0; i < size; i++) { // 현재 선택된 점수 int num = arr[i]; // result를 순회하며 for (j = 0; j < size; j++) { // 자기보다 같거나 낮은 점수가 처음으로 나오면 중지 -> 그 부분(j)을 얻음 if (result[j] < num) break; } // 현재 i번째 점수이므로, result에는 (i - 1)개의 요소(지금 점수는 아직 안 넣었으므로 제외)가 들어있을 것입니다. for (int k = i - 1; k >= j; k--) result[k + 1] = result[k]; // 뒤로 shift result[j] = num; } int bars, score; for (i = 0; i < size; i++) { score = result[i]; printf_s("%3d등 학생: %3d점 [", i + 1, score); //최대 100점=20문자로 했습니다. bars = score/5; for (j = 0; j < bars; j++) printf_s("="); for (j = 0; j < 20 - bars; j++) printf_s(" "); printf_s("]\n"); } }
Tomato 05.06