The final destination of programming
- K&R C Style Function Declaration (2023.08.20)
- Conditional Compile with
#ifdef
(2022.08.30) - File I/O (2022.08.27)
- GCC Optimization Option Practice (2022.08.16)
printf()
format test (2022.04.25)- Binary Search 1 (2022.04.19)
- Binary Search 0 (2022.02.11)
- Increment and Decrement Operators (2022.02.01)
- Prevent Garbage Value (2022.01.21)
- Containers : Deque, Stack and Queue (2021.10.14)
- Template (2021.07.23)
- Stack Overflow (2021.05.18)
- Hello World (2021.05.12)
※ All codes include the following top lines. :
// C
#include <stdio.h>
// CPP
#include <iostream>
using namespace std;
-
A comparison between the K&R style and ANSI C style function declaration methods
-
What is K&R C? → [Wikipedia] C (programming language) > History > K&R C
According to ChatGPT
-
Pros:
- Conciseness: The K&R style reduces the length of the function declaration, making it more concise.
-
Cons:
- Readability: Without parameter names, it can be difficult to understand the purpose of each parameter.
- Lack of Type Safety: Since only data types are mentioned, there's no type checking for function arguments.
- Maintenance: If parameter order or types change, you need to update both the declaration and definition.
-
Conclusion:
- While the K&R style was used in early C development due to limitations of the time, the ANSI C style has become the recommended practice. It improves code readability, provides better type safety, and enhances maintainability. The ANSI C style also aligns with modern coding standards and best practices, making it the preferred choice for most developers today.
-
-
Example
Codes : KnrFunctionSyntax.c
int add(a, b) // K&R 스타일 함수 선언: 매개변수 이름을 생략하고 데이터 타입만 표시 int a, b; // 실제 매개변수 이름과 데이터 타입은 별도로 기술 { return a + b; }
int add2(int a, int b) // ANSI C 스타일 함수 선언: 매개변수와 데이터 타입을 함께 명시 { return a + b; }
int main() { int result = add(5, 3); // K&R 스타일 함수 호출 int result2 = add2(5, 3); // ANSI C 스타일 함수 호출 printf("Result (K&R) : %d\n", result); printf("Result2 (ANSI): %d\n", result2); return 0; }
Output
Surprisingly, the K&R style code has been compiled successfully even in recent compilation environments. The above code was compiled using MinGW.org GCC-6.3.0-1 and executed without any issues.
Result (K&R) : 8 Result2 (ANSI): 8
-
Can determine where to compile or not with the preprocessors
#ifdef
~#endif
-
It seems very useful! I love it!
-
References :
- 조건부 컴파일 (TCP School) http://www.tcpschool.com/c/c_compile_condCompile
- 조건부 컴파일 (C언어 / Wikidocs) https://wikidocs.net/13348
- (C/C++) 조건부 컴파일로 디버깅용 출력 한방에 없애기 (BOJ) https://www.acmicpc.net/blog/view/110
-
※ When the macro
fileio
is on, Ahnlab V3 Lite recognizesa.exe
as a malware!Codes : ConditionalCompile.c
int main() { char txt[] = "I am your father.\n"; #ifdef fileio char fileName[] = "ConditionalCompile.txt"; FILE* pf = fopen(fileName, "w"); // w : make a new empty file fprintf(pf, txt); fclose(pf); printf("%s has been generated.\n", fileName); #else printf("%s", txt); #endif return 0; }
Codes : ConditionalCompile.cpp
#include <iostream> #include <fstream> #define endl '\n' using namespace std;
int main() { string txt = "I am your father."; #ifdef fileio ofstream ofs; string fileName = "ConditionalCompile.txt"; ofs.open(fileName, ios::out); // ios::out : make a new empty file ofs << txt << endl; ofs.close(); cout << fileName << " has been generated." << endl; #else cout << txt << endl; #endif return 0; }
Commands : ConditionalCompile_c.bat
The couple of files have the same results.
:: #ifdef fileio gcc -Dfileio conditionalcompile.c a :: #else gcc conditionalcompile.c a
ConditionalCompile.txt has been generated.
I am your father.Commands : ConditionalCompile_cpp.bat
:: #ifdef fileio g++ -Dfileio conditionalcompile.cpp a :: #else g++ conditionalcompile.cpp a
ConditionalCompile.txt has been generated.
I am your father.Results : ConditionalCompile.txt
I am your father.
-
A practice of file input/ouput in C/C++
-
Further discussion : how to read Korean string from external file
Codes : FileIO.c
int main() { // Write file FILE* pf1 = fopen("FileIO.txt", "w"); // w : make a new empty file fprintf(pf1, "My wife is crazy.\n"); fprintf(pf1, "Really crazy.\n"); fclose(pf1); // Read file FILE* pf2 = fopen("FileIO.txt", "r"); // r : read-only char txt[__INT16_MAX__]; fread(txt, 1, __INT16_MAX__, pf2); printf("%s", txt); fclose(pf2); return 0; }
Codes : FileIO.cpp
#include <iostream> #include <fstream> #define endl '\n' using namespace std;
int main() { // Write file ofstream ofs; ofs.open("FileIO.txt", ios::out); // ios::out : make a new empty file ofs << "My wife is crazy." << endl; ofs << "Really crazy." << endl; ofs.close(); // Read file ifstream ifs; string line; ifs.open("FileIO.txt", ios::in); // ios::in : read-only while(getline(ifs, line)) cout << line << endl; ifs.close(); return 0; }
Results : FileIO.txt
My wife is crazy. Really crazy.
-
Generate many assembly(
.s
) files with various optimization options inGCC
-
But I've just realized that I'm not ready yet to read their assembly codes ……
-
However, I've found at least that the generally known properties of the optimization options are not fixed absolutely.
(For example,Os
is known as smaller code size but it sometimes returns rather larger one.) -
References :
· https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
· https://wiki.kldp.org/wiki.php/GccOptimizationOptions
· https://www.rapidtables.com/code/linux/gcc/gcc-o.htmlCodes : OptimizePractice.c
void operate(int i, int* p) { if (i % 2 != 0) (*p)++; }
int main() { int num = 0; int* p = # for (int i = 0; i < 10; i++) operate(i, p); printf("%d\n", num); return 0; }
5
Codes : OptimizePractice.bat (Old)
gcc -O0 -S OptimizePractice.c -o OptimizePractice_O0.s gcc -O1 -S OptimizePractice.c -o OptimizePractice_O1.s gcc -O2 -S OptimizePractice.c -o OptimizePractice_O2.s gcc -O3 -S OptimizePractice.c -o OptimizePractice_O3.s gcc -Os -S OptimizePractice.c -o OptimizePractice_Os.s gcc -Ofast -S OptimizePractice.c -o OptimizePractice_Ofast.s
Codes : OptimizePractice.bat (New)
@echo off set name=OptimizePractice set options=O0 O1 O2 O3 Os Ofast @REM There should be no space on the both side of "=" for %%i in (%options%) do ( @REM echo %%i gcc -%%i -S %name%.c -o %name%_%%i.s )
-
I wrote the below codes in GCJ 2022 Round 1B - Controlled Inflation, but there's some struggle with
printf()
's format%d
%ld
%lld
.
(All the variables are declared as long long type.)// test // printf("min : %lld, max : %lld, dist : %lld, sum1 : %lld, sum2 : %lld\n", min, max, dist, sum1, sum2);
-
I will never miss the criminal!
Codes : printf.c & printf.cpp
The codes except each of the headers are the same.
int main() { char text[] = "%d %ld %lld\n"; printf(text, __SCHAR_MAX__, __SCHAR_MAX__, __SCHAR_MAX__); printf(text, __INT8_MAX__, __INT8_MAX__, __INT8_MAX__); printf(text, __SHRT_MAX__, __SHRT_MAX__, __SHRT_MAX__); printf(text, __INT16_MAX__, __INT16_MAX__, __INT16_MAX__); printf(text, __INT_MAX__, __INT_MAX__, __INT_MAX__); printf(text, __LONG_MAX__, __LONG_MAX__, __LONG_MAX__); printf(text, __INT32_MAX__, __INT32_MAX__, __INT32_MAX__); printf(text, __LONG_LONG_MAX__, __LONG_LONG_MAX__, __LONG_LONG_MAX__); printf(text, __INT64_MAX__, __INT64_MAX__, __INT64_MAX__); return 0; }
Results
127 127 8458399796925825151 127 127 8458399796925825151 32767 32767 8458399796925857791 32767 32767 8458399796925857791 2147483647 2147483647 8458399799073308671 2147483647 2147483647 8458399799073308671 2147483647 2147483647 8458399799073308671 -1 2147483647 9223372036854775807 -1 2147483647 9223372036854775807
-
Implications
%d
and%ld
don't make trouble with readingchar
orshort
, but%lld
is something special.- Make sure
int
==long
==int32
in the current standard environment - -1 seems interesting.
__LONG_LONG_MAX__
(==__INT64_MAX__
) is0 111 …… 1111
, but%d
reads only partial digits from it.
And the partial number1 111 …… 1111
indicates -1 as 2's complement.
-
I tried this code with Binary Search 0 (2022.02.11) about the same time,
but couldn't find why the traversal results are wrong. -
There was a crazy mistake …… It stole my two months!
Codes : BinarySearch.c
#include <stdio.h> #include <stdlib.h> // malloc()
typedef struct _tNode // It makes using struct easier to declare it with typedef { int value; struct _tNode* left; // Node* left : why does it not work? struct _tNode* right; // should be declared as a pointer } Node;
Node* insert(Node* root, int value) // The location of '*' doesn't matter { if (root == NULL) { Node* root = malloc(sizeof(Node)); // malloc : instead of `new` in C++ root->value = value; root->left = NULL; root->right = NULL; return root; } else { if (root->value > value) root->left = insert(root->left, value); else root->right = insert(root->right, value); } return root; } Node* delete(Node* root, int value) { if (root == NULL) return root; if (root->value > value) root->left = delete(root->left, value); else if (root->value < value) root->right = delete(root->right, value); else { // ing~~~ } return root; }
delete()
is still imcomplete.void preOrder(Node* root) { if (root == NULL) return; printf("%d ", root->value); preOrder(root->left); preOrder(root->right); } void inOrder(Node* root) { if (root == NULL) return; inOrder(root->left); printf("%d ", root->value); inOrder(root->right); } void postOrder(Node* root) { if (root == NULL) return; postOrder(root->left); postOrder(root->right); printf("%d ", root->value); }
I wrote all the inside function names as
preOrder()
…… crazy~~~int main() { Node* root = NULL; int arr[6] = {6, 3, 4, 7, 13, 10}; int len = sizeof(arr) / sizeof(int); for (int i = 0; i < len; i++) root = insert(root, arr[i]); printf("Preorder traversal : "); preOrder(root); putchar('\n'); printf("Inorder traversal : "); inOrder(root); putchar('\n'); printf("Postorder traversal : "); postOrder(root); putchar('\n'); return 0; }
Results
Preorder traversal : 6 3 4 7 13 10 Inorder traversal : 3 4 6 7 10 13 Postorder traversal : 4 3 10 13 7 6
-
hope
binary_search()
in C++ would be a free lunch ……
but it just returns onlytrue
orfalse
depending on the element's presence. -
Of course, this function seems very powerful for sorted data.
Codes : BinarySearch.cpp
#include <iostream> #include <vector> #include <algorithm>
int main() { vector<int> vec = {2, 4, 6, 8, 10, 12}; // should be sorted vector<int> vec2 = {3, 6, 9, 12}; for (auto v : vec2) { // binary_search() : a function to just return true or false if the value exists bool ans = binary_search(vec.begin(), vec.end(), v); cout << v << ' ' << ans << endl; } return 0; }
Results
3 0 6 1 9 0 12 1
-
Some extreme(?) experiments about
++
and--
operatorsCodes : IncDecOperator.c
int main() { int a = 1, b = 1, c = 1, d = 1, e = 1, f = 1; a++; --b; // no problem c = ++c; d = d++; // gcc - no problem // clang - warning: multiple unsequenced modifications to 'c' [-Wunsequenced] // e = ++e--; // ++e--; // f++--++; // f++++++; // gcc - error: lvalue required as increment operand // clang - error: expression is not assignable printf("Good-bye %d %d %d %d\n", a, b, c, d); return 0; }
Results
Good-bye 2 0 2 1
-
The way to prevent variable declaration from garbage value
Codes : PreventGarbageValue.cpp
int main() { int garbage; int noGarbage{}; cout << garbage << endl; cout << noGarbage << endl; return 0; }
Results
2686816 0
-
STL
Practice : ContainerDeque
and its adaptorsStack
andQueue
- Especially
Deque
is something greater thanvector
andlist
Prior Queue
that is also one of the container adaptor from Deque and consists ofheap
will be continued ……
- Especially
-
Reference ☞ 코딩 테스트를 위한 자료 구조와 알고리즘 with C++ (길벗, 2020)
Codes : Containers_Deque.cpp
#include <deque>
void print(deque<int> deq) { for (auto it = deq.begin(); it != deq.end(); it++) cout << *it << ' '; cout << endl; }
int main() { deque<int> deq {1, 2, 3, 4, 5}; print(deq); deq.push_front(0); print(deq); deq.push_back(6); print(deq); deq.insert(deq.begin() + 2, 10); print(deq); deq.pop_back(); print(deq); deq.pop_front(); print(deq); deq.erase(deq.begin() + 1); print(deq); deq.erase(deq.begin() + 3, deq.end()); print(deq); // emplace()? // emplace_front()? // emplace_back()? return 0; }
1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 10 2 3 4 5 6
0 1 10 2 3 4 5
1 10 2 3 4 5
1 2 3 4 5
1 2 3Codes : Containers_Stack.cpp
#include <stack>
void print(stack<int> stk) { if (stk.empty()) cout << "The stack is empty." << endl; else { while (!stk.empty()) { cout << stk.top() << ' '; stk.pop(); } cout << endl; } }
int main() { stack<int> stk ({1, 2, 3}); // check the different way to declare with initial elements from deque and so on print(stk); stk.push(4); print(stk); stk.push(5); print(stk); stk.pop(); stk.pop(); print(stk); stk.pop(); stk.pop(); stk.pop(); print(stk); // Any other methods? return 0; }
3 2 1
4 3 2 1
5 4 3 2 1
3 2 1
The stack is empty.Codes : Containers_Queue.cpp
#include <queue>
void print(queue<int> q) { if (q.empty()) cout << "The que is empty." << endl; else { while (!q.empty()) { cout << q.front() << ' '; q.pop(); } cout << endl; } }
int main() { queue<int> q ({1, 2, 3}); // don't forget ()! print(q); q.push(4); print(q); q.push(5); print(q); q.pop(); q.pop(); print(q); q.pop(); q.pop(); q.pop(); print(q); return 0; }
1 2 3
1 2 3 4
1 2 3 4 5
3 4 5
The que is empty.
-
Significantly advanced code using template from the previous
StackOverflow.cpp
-
I am so proud!
Codes : Template.cpp
template <class T> // void next (T a) cout << a++ << endl; // can't write in a line without {} void next (T a) { if (typeid(a) == typeid((char) 'a') || typeid(a) == typeid((unsigned char) 'a')) { cout << typeid(a).name() << " : " << (int) a << " + 1 = " << (int) ++a << " (converted to ASCII value)" << endl; } else { cout << typeid(a).name() << " : " << a << " + 1 = " << ++a << endl; } // there will be more alternatives like type_info and so on …… }
int main() { next((char) CHAR_MAX); next((unsigned char) UCHAR_MAX); next((short) SHRT_MAX); next((unsigned short) USHRT_MAX); next((int) INT_MAX); next((unsigned int) UINT_MAX); next((bool) 1); // warning: use of an operand of type 'bool' in 'operator++' is deprecated return 0; }
Results
c : 127 + 1 = -128 (converted to ASCII value)
h : 255 + 1 = 0 (converted to ASCII value)
s : 32767 + 1 = -32768
t : 65535 + 1 = 0
i : 2147483647 + 1 = -2147483648
j : 4294967295 + 1 = 0
b : 1 + 1 = 1
-
"Let's conquer the stack overflow problem!"
-
…… a stupid conquerer who didn't know template and generic function said.
-
Can he learn them or still stay in beginner's swamps? To be continued ……
Codes : StackOverflow.cpp
#include <iostream> using namespace std; int main() { // char : -128 to 127 (-2^7 to 2^7 - 1) char chr1 = 126; char chr2 = chr1 + 1; char chr3 = chr2 + 1; cout << "char (" << sizeof(char) << ") : " << (short)chr1 << " + 1 = " << (short)chr2 << endl; // 127 cout << "char (" << sizeof(char) << ") : " << (short)chr2 << " + 1 = " << (short)chr3 << endl << endl; // -128 // unsigned char : 0 to 255 (0 to 2^8 - 1) unsigned char uChr1 = 254; unsigned char uChr2 = uChr1 + 1; unsigned char uChr3 = uChr2 + 1; cout << "unsigned char (" << sizeof(unsigned char) << ") : " << (short)uChr1 << " + 1 = " << (short)uChr2 << endl; // 255 cout << "unsigned char (" << sizeof(unsigned char) << ") : " << (short)uChr2 << " + 1 = " << (short)uChr3 << endl << endl; // 0 // short : -32768 to 32767 (-2^15 to 2^15 - 1) short shrt1 = 32766; short shrt2 = shrt1 + 1; short shrt3 = shrt2 + 1; cout << "short (" << sizeof(short) << ") : " << shrt1 << " + 1 = " << shrt2 << endl; // 32767 cout << "short (" << sizeof(short) << ") : " << shrt2 << " + 1 = " << shrt3 << endl << endl; // -32768 // unsigned short : 0 to 65535 (0 to 2^16-1) unsigned short uShrt1 = 65534; unsigned short uShrt2 = uShrt1 + 1; unsigned short uShrt3 = uShrt2 + 1; cout << "unsigned short (" << sizeof(unsigned short) << ") : " << uShrt1 << " + 1 = " << uShrt2 << endl; // 65535 cout << "unsigned short (" << sizeof(unsigned short) << ") : " << uShrt2 << " + 1 = " << uShrt3 << endl << endl; // 0 // int : -214748368 to 214748367 (-2^31 to 2^31 - 1) int int1 = 2147483646; int int2 = int1 + 1; int int3 = int2 + 1; cout << "int (" << sizeof(int) << ") : " << int1 << " + 1 = " << int2 << endl; // 2147483647 cout << "int (" << sizeof(int) << ") : " << int2 << " + 1 = " << int3 << endl << endl; // -2147483648 // unsigned int : 0 to 4294967295 (0 to 2^32 -1) unsigned int uIint1 = 4294967294; unsigned int uIint2 = uIint1 + 1; unsigned int uIint3 = uIint2 + 1; cout << "unsigned int (" << sizeof(unsigned int) << ") : " << uIint1 << " + 1 = " << uIint2 << endl; // 4294967295 cout << "unsigned int (" << sizeof(unsigned int) << ") : " << uIint2 << " + 1 = " << uIint3 << endl << endl; // 0 // bool : 0 to 1 bool bl1 = false; bool bl2 = bl1 + 1; bool bl3 = bl2 + 1; cout << "bool (" << sizeof(bool) << ") : " << bl1 << " + 1 = " << bl2 << endl; // 1 cout << "bool (" << sizeof(bool) << ") : " << bl2 << " + 1 = " << (bool)(bl3) << endl; // 1 return 0; }
Results
char (1) : 126 + 1 = 127
char (1) : 127 + 1 = -128unsigned char (1) : 254 + 1 = 255
unsigned char (1) : 255 + 1 = 0short (2) : 32766 + 1 = 32767
short (2) : 32767 + 1 = -32768unsigned short (2) : 65534 + 1 = 65535
unsigned short (2) : 65535 + 1 = 0int (4) : 2147483646 + 1 = 2147483647
int (4) : 2147483647 + 1 = -2147483648unsigned int (4) : 4294967294 + 1 = 4294967295
unsigned int (4) : 4294967295 + 1 = 0bool (1) : 0 + 1 = 1
bool (1) : 1 + 1 = 1
-
My first run of
C
/C++
code in Visual Studio Code- Environmental setting was harder than coding
- Find how to complie and run in cosole (rather easier than VS Code menu)
gcc
(forC
) andg++
(forC++
) seem not so different to each other
Codes : IamYourFather_c.c
#include <stdio.h> #include <windows.h> // for using system() int main() { printf("I am your father.\n"); // system("pause"); return 0; }
Command Lines to Run IamYourFather_c.c
gcc --help gcc -S IamYourFather_c.c gcc IamYourFather_c.c -o IamYourFather_c.exe
.\IamYourFather_c
I am your father.
Codes : IamYourFather_cpp.cpp
#include <iostream> using namespace std; int main() { cout << "I am your father." << endl; // system("pause"); return 0; }
Command Lines to Run IamYourFather_cpp.cpp
g++ --help g++ -S IamYourFather_cpp.cpp g++ IamYourFather_cpp.cpp -o IamYourFather_cpp.exe
.\IamYourFather_cpp
I am your father.