Cで文字列の一部を切り取る方法を理解しようとしています。たとえば、「道路を横断中に車が彼にぶつかったため、犬が死んだ」という文字列があるとします。関数はどのように文を作成しますか。車が道路を横断中に彼を襲った」または「車が彼を襲った」
Cのライブラリ(または/および)カスタム関数を使用してこれをどのように行いますか?
はい、メインコードはありませんが、これがこの実験の構造になります
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include "display_usage.c"/*If the user enters wrong arguments it will tell them how it should be */
void cut( const char *file, int option, int first, int last );
int main(int argc, char *argv[] ) {
FILE *fp;
char ch;
fp = fopen("test.txt", "r"); // Open file in Read mode
while (ch!=EOF) {
ch = fgetc(fp); // Read a Character
printf("%c", ch);
}
fclose(fp); // Close File after Reading
return 0;
}
void cut( const char *file, int reverse, int first, int last ) {
return;
}
次の関数は、charバッファーから指定された範囲を切り取ります。範囲は、開始インデックスと長さによって識別されます。負の長さを指定して、開始インデックスから文字列の終わりまでの範囲を示すことができます。
/*
* Remove given section from string. Negative len means remove
* everything up to the end.
*/
int str_cut(char *str, int begin, int len)
{
int l = strlen(str);
if (len < 0) len = l - begin;
if (begin + len > l) len = l - begin;
memmove(str + begin, str + begin + len, l - len + 1);
return len;
}
Charの範囲は、末尾の'\0'
を含む範囲の後のすべてをmemmove
で開始インデックスに移動し、それによって範囲を上書きすることによって切り取られます。範囲内のテキストは失われます。
内容を変更できるcharバッファを渡す必要があることに注意してください。読み取り専用メモリに格納されている文字列リテラルを渡さないでください。
strncpy
はn
文字までコピーします。必要に応じて、文字列内でポインタを移動できます。また、書き込み可能なメモリがある場合は、配列に\0
を挿入して、配列を早期に終了できます。
このような問題については、独自の関数を記述する方が良いですが、時間がかかりますが、見返りはあります。関数のコードstr_sliceを以下に示します。これは、JavaScriptの関数string.slice( https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice )および文字列または配列でスライスを作成するためのPythonの機能( https: //docs.python.org/3.5/library/functions.html#slice )。
また、C標準ライブラリのみに基づいているため、クロスプラットフォームであり、任意のコンパイラで動作する必要があります。疑わしい場合は、テストを調べます。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/**
* Extracts a selection of string and return a new string or NULL.
* It supports both negative and positive indexes.
*/
char *
str_slice(char str[], int slice_from, int slice_to)
{
// if a string is empty, returns nothing
if (str[0] == '\0')
return NULL;
char *buffer;
size_t str_len, buffer_len;
// for negative indexes "slice_from" must be less "slice_to"
if (slice_to < 0 && slice_from < slice_to) {
str_len = strlen(str);
// if "slice_to" goes beyond permissible limits
if (abs(slice_to) > str_len - 1)
return NULL;
// if "slice_from" goes beyond permissible limits
if (abs(slice_from) > str_len)
slice_from = (-1) * str_len;
buffer_len = slice_to - slice_from;
str += (str_len + slice_from);
// for positive indexes "slice_from" must be more "slice_to"
} else if (slice_from >= 0 && slice_to > slice_from) {
str_len = strlen(str);
// if "slice_from" goes beyond permissible limits
if (slice_from > str_len - 1)
return NULL;
buffer_len = slice_to - slice_from;
str += slice_from;
// otherwise, returns NULL
} else
return NULL;
buffer = calloc(buffer_len, sizeof(char));
strncpy(buffer, str, buffer_len);
return buffer;
}
テスト
#include <assert.h>
void
test_str_slice()
{
char str[] = "abcdefghijkl";
assert(NULL == str_slice(str, -3, -10));
assert(NULL == str_slice(str, -1, -2));
assert(NULL == str_slice(str, -1, 0));
assert(NULL == str_slice(str, 1, 0));
assert(NULL == str_slice(str, 5, 4));
assert(NULL == str_slice(str, 0, 0));
assert(NULL == str_slice(str, 10, 10));
assert(NULL == str_slice(str, -2, -2));
assert(NULL == str_slice(str, -20, -12));
assert(NULL == str_slice(str, -20, -13));
assert(NULL == str_slice(str, 12, 13));
assert(NULL == str_slice(str, 12, 20));
assert(NULL == str_slice("", 1, 2));
assert(NULL == str_slice("", -2, -1));
assert(strcmp(str_slice(str, -3, -1), "jk") == 0);
assert(strcmp(str_slice(str, -8, -3), "efghi") == 0);
assert(strcmp(str_slice(str, -10, -9), "c") == 0);
assert(strcmp(str_slice(str, -2, -1), "k") == 0);
assert(strcmp(str_slice(str, -15, -1), "abcdefghijk") == 0);
assert(strcmp(str_slice(str, -12, -2), "abcdefghij") == 0);
assert(strcmp(str_slice(str, -15, -8), "abcd") == 0);
assert(strcmp(str_slice(str, -15, -11), "a") == 0);
assert(strcmp(str_slice(str, 1, 3), "bc") == 0);
assert(strcmp(str_slice(str, 11, 100), "l") == 0);
assert(strcmp(str_slice(str, 2, 4), "cd") == 0);
assert(strcmp(str_slice(str, 3, 6), "def") == 0);
assert(strcmp(str_slice(str, 0, 1), "a") == 0);
assert(strcmp(str_slice(str, 4, 6), "ef") == 0);
assert(strcmp(str_slice(str, 1, 2), "b") == 0);
assert(strcmp(str_slice(str, 0, 3), "abc") == 0);
assert(strcmp(str_slice(str, 0, 11), "abcdefghijk") == 0);
assert(strcmp(str_slice(str, 2, 10), "cdefghij") == 0);
assert(strcmp(str_slice(str, 0, 50), "abcdefghijkl") == 0);
}
テストでわかるように、文字列またはNULLを返す関数です。また、負のインデックスと正のインデックスの両方をサポートしています。このアイデアは、JavaScriptおよびPythonの前述の初期の機能から得られました。したがって、この回答の大量のテキストを汚染しないでください。JavaScriptとPythonのドキュメントを読むことをお勧めします。
文字列の内容がわかっている場合は、strstr
が最適です。
例:
char *str = "A dog died because a car hit him while he was crossing the road.";
char *pCh = strstr(str, "dog");
pCh
には、'd'
内の"dog"
のアドレスが含まれます。
http://www.cplusplus.com/reference/cstring/
Strstr(部分文字列を取得する)、strtok(トークンを使用して分割する)、