でint snprintf(char *str, size_t size, const char *format, ...);
特定の文字数をに書き込むことができますstr
。
c文字列から特定の文字数を読み取るにはどうすればよいですか?
よろしく
format引数で数値を渡すことができます。
char buf[21];
sscanf(str, "%20s", buf);
これにより、最大20文字がに読み込まれますbuf
。
コンパイル時に読み取るデータの量がわからない場合は、実行時にフォーマット文字列を準備できます。
char format[20];
sprintf(format, "%%%ds", howMuchToRead);
sscanf(str, format, buf);
sscanf
とソリューションの両方の代わりに、高精度strncpy
の指定子を使用することもできます(20文字だけを印刷するなど)。このSO投稿では、 C文字列の高精度指定子について説明しています。手順は基本的にソリューションと同じです。フォーマット文字列を作成し、それを使用して必要な文字をキャプチャします。上記のフォーマット指定子などを使用している
場合、文字列に空白が含まれていると20文字になるとは限りません。空白が検出された場合は、空白までしか文字を取得できません(空白は関数ファミリーの区切り文字であるため)。代わりに、次のようなものを利用する必要があります"%.20s"
sscanf
sscanf
"%20s"
scanf
%20[^\n]
。[^\n]
改行までの読み取りを示し、20はスキャンする文字数を指定します。これらはすべて、次のサンプルで確認できます。
#include <stdio.h>
#include <string.h>
int main(void) {
char format[20] = {0};
char buf[50] = {0};
char str[] = "Hello World! How are you?";
size_t howMuchToRead = 8;
/* Using sscanf - till whitespace or size specified */
snprintf(format, sizeof format, "%%%zus", howMuchToRead);
sscanf(str, format, buf);
printf("Using sscanf with %%8s format :%s\n", buf);
/* Using sscanf - read everything upto newline */
snprintf(format, sizeof format, "%%%zu[^\n]", howMuchToRead);
sscanf(str, format, buf);
printf("Using sscanf with %%8[^\\n] format :%s\n", buf);
/* Using precision specifier */
snprintf(format, sizeof format, "%%.%zus", howMuchToRead);
snprintf(buf, sizeof buf, format, str);
printf("Using precision specifier :%s\n", buf);
return 0;
}
/*
Output:
Using sscanf with %8s format :Hello
Using sscanf with %8[^\n] format :Hello Wo
Using precision specifier :Hello Wo
*/
そして、sinelawの答えは、あなたが注意しなければならない非常に重要な点を示しています。
お役に立てれば!
strncpy
またはを使用できますmemcpy
。ただし、場合によっては終了文字strncpy
が追加されない場合があり、追加されない場合があることに注意してください。また、文字列の終わりをまったくチェックせず、要求したバイト数をコピーするだけです。'\0'
memcpy
memcpy
あなたが使用することができますsscanf
:
int sscanf(const char *str, const char *format, ...);
例えば:
char out[4];
sscanf("foo", "%3s", &out);
もちろん、もっと面白いこともできます。
int value;
sscanf("value=10", "value=%d", &value);
sscanf
、scanf
関数のように、問題があります。GNUのマンページにあるように:
指定されたフォーマット指定子には十分なアドレス引数が必要です。そうでない場合、結果は予測不可能であり、恐らく悲惨です。
したがって、回避する必要のある問題が1つあります(一部のコンパイラには、これらの関数について具体的に警告するハックがありますが、コンパイラは、正しい量またはタイプの引数を渡していることを確認できません)。この問題の一部は、フォーマット文字列に最大バッファサイズをハードコーディングする必要があることでもあります(これにより、バッファオーバーフローを防ぐために整数定数を使用することが難しくなります)。
あなたのユースケースは単に文字列から特定の数の文字をコピーすることなので、Joachim Pileborgの答えが示唆するように、私はただ使用しますstrncpy
(そして必ず終了を設定します)。'\0'
長さパラメーターには、入力バッファーと出力バッファーの両方の最小長から、終了を収容するために1を引いたものを使用する必要がありますnul
。
言い換えれば(テストされていない):
strncpy(dest, src,
MIN(NUM_OF_CHARS_TO_COPY,
MIN(DEST_BUFFER_SIZE, SRC_BUFFER_SIZE)) - 1);
ここで、は整数MIN(a,b)
と同等です。a < b ? a : b