C言語で文字列の複製と自作関数を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
strdup/strndup関数で文字列の複製
1 2 |
char *strdup(const char *s); char *strndup(const char *s, size_t n); |
strdup/strndup関数は文字列を複製します.
strdup関数は,文字列sの複製である新しい文字列へのポインタを返します.
新しい文字列のためのメモリはmalloc関数で確保し,free関数で解放します.
strndup関数も同様ですが,最大でnバイトを複製します.
sがnよりも長い場合,nバイトだけが複製され,終端に'\0'が追加されます.
strdup/strndup関数の利用例
strdup/strndup関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define STR "string" int main(void) { char *s, *t; s = strdup(STR); printf("s = %s\n", s); t = strndup(STR, 3); printf("t = %s\n", t); free(t); free(s); return 0; } |
実行結果は以下になります.
1 2 3 4 |
$ gcc strdup.c $ a.out s = string t = str |
strdup/strndup関数の自作関数
strdup/strndup関数の自作関数は以下のコードになります.
自作関数のmystrdup/mystrndup関数では,malloc関数を利用していることに注意して下さい.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define STR "string" char *mystrdup(const char *s) { char *t; size_t len = strlen(s); if ((t = malloc(sizeof(char) * (len + 1))) == NULL) { fprintf(stderr, "Error: cannot allocate memory %zu bytes\n", sizeof(char) * (len + 1)); exit(1); } strcpy(t, s); return t; } char *mystrndup(const char *s, size_t n) { char *t; size_t len = strlen(s); if (len > n) { len = n; } if ((t = malloc(sizeof(char) * (len + 1))) == NULL) { fprintf(stderr, "Error: cannot allocate memory %zu bytes\n", sizeof(char) * (len + 1)); exit(2); } strncpy(t, s, len); t[len] = '\0'; return t; } int main(void) { char *s, *t; s = mystrdup(STR); printf("s = %s\n", s); t = mystrndup(STR, 3); printf("t = %s\n", t); free(t); free(s); return 0; } |
実行結果は以下になります.同じです.
1 2 3 4 |
$ gcc mystrdup.c $ a.out s = string t = str |
strdupa/strndupa関数で文字列の複製
1 2 |
char *strdupa(const char *s); char *strndupa(const char *s, size_t n); |
strdupa/strndupa関数で文字列を複製します.
strdupa/strndupa関数も,strdup/strdupa関数とそれぞれ同様の文字列を複製しますが,メモリ確保にalloca関数を利用する点が異なります.
また,strdupa/strndupa関数はGCC拡張なので,Visual Studioでは利用できないことに注意して下さい.
strdupa/strndupa関数の利用例
strdupa/strndupa関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #define _GNU_SOURCE #include <stdio.h> #include <string.h> #define STR "string" int main(void) { char *s, *t; s = strdupa(STR); printf("s = %s\n", s); t = strndupa(STR, 3); printf("t = %s\n", t); return 0; } |
実行結果は以下になります.
1 2 3 4 |
$ gcc strdupa.c $ a.out s = string t = str |
strdupa/strndupa関数の自作関数
strdupa/strndupa関数の自作関数を作成するためには,alloca関数を呼び出す必要があります.
alloca関数はスタックに自動的に解放されるメモリを割り当てます.
strdupa/strndupa関数内でalloca関数を呼び出すと,解放済みのメモリのアドレスが返り値に入ってしまい,正常に動作しません.
そこで,strdupa/strndupa関数の自作関数では,強制的にインライン化する属性「__attribute__((always_inline))」を付けることで,正常に動作することができます.
strdupa/strndupa関数の自作関数は以下のコードになります.
自作関数のmystrdupa/mystrndupa関数では,alloca関数を利用していることに注意して下さい.
また,mystrdupa/mystrndupa関数を定義する時に「__attribute__((always_inline))」を付けています(60,72行目).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #define _GNU_SOURCE #include <stdio.h> #include <string.h> #include <alloca.h> #define STR "string" static inline __attribute__((always_inline)) char *mystrdupa(const char *s) { char *t; size_t len = strlen(s); t = alloca(len + 1); strcpy(t, s); return t; } static inline __attribute__((always_inline)) char *mystrndupa(const char *s, size_t n) { char *t; size_t len = strlen(s); if (len > n) { len = n; } t = alloca(len + 1); strncpy(t, s, len); t[len] = '\0'; return t; } int main(void) { char *s, *t; s = mystrdupa(STR); printf("s = %s\n", s); t = mystrndupa(STR, 3); printf("t = %s\n", t); return 0; } |
実行結果は以下になります.同様です.
1 2 3 4 |
$ gcc mystrdupa.c $ a.out s = string t = str |
まとめ
C言語のstrdup/strndup関数で文字列の複製と自作関数,GCC拡張のstrdupa/strndupa関数と自作関数を紹介しました.
これらの関数の違いは下表になります.
項目 | strdup関数 | strndup関数 | strdupa関数 | strndupa関数 |
---|---|---|---|---|
概要 | 文字列を複製 | 文字列をn文字複製 | 文字列を複製 | 文字列をn文字複製 |
実行可能な開発環境 | GCC/Clang/Visual Studio | GCC/Clang/Visual Studio | GCC/Clang | GCC/Clang |
メモリ確保 | malloc関数 | malloc関数 | alloca関数 | alloca関数 |
メモリ解放 | free関数 | free関数 | 不要 | 不要 |
malloc/alloca関数や関連関数を知りたいあなたは,malloc/calloc/realloc/alloca関数と可変長配列で動的にメモリ確保を読みましょう.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!