将文本存储在数组中的两个字符之间
Store text between two characters in a array
我有这个字符数组 char txt[80] = "Some text before /01/2017$";
并且需要将两个 $
之间的内容复制到一个字符串 11/01/2017
中。我如何使用 <string.h>
函数执行此操作?
假设您确定字符串中有 2 个 $
...您可以执行以下操作:
char *first_dollar = strchr(txt, '$'); //get position of first dollar from the start of string
char *second_dollar = strchr(first_dollar + 1, '$'); //get position of first dollar starting
// from one position after the first dollar
char tocopy[20];
*second_dollar = '[=10=]'; //change the value of last dollar to '[=10=]'
strcpy(tocopy, first_dollar + 1); //copy into the place you want
*second_dollar = '$'; // put back the second dollar
如果您不确定字符串中是否包含 2 $
,您应该检查 strchr
的 return,即 NULL
.
是否必须使用字符串?有一个聪明的方法使用 sscanf
:
char txt[80] = "Some text before /01/2017$";
char t[20];
sscanf(txt, "%*[^$]$%[^$]", t);
printf("ORIGINAL TEXT: %s\nEXTRACTED TEXT: %s\n", txt, t);
scanf中的格式含义如下:
- 忽略所有不是
$
; 的字符
- 忽略 1
$
。
- 读取所有字符,直到找到下一个
$
并将其存储在 t
中。
我不知道你为什么要用string.h。
供您参考,这没有 string.h 方法。
更新
#include <stdio.h>
#include <string.h>
int main(){
char txt[80] = "Some text before /01/2017$ and /01/2017$ and $$ end $abc$";
char get[80] = { '[=10=]' };
int i = 0, k = -1, j = 0;
int len = strlen( txt ); // Get length
for ( i = 0 ; i < len ; i++ ){
bool find = false;
for ( i ; txt[i] != '$' && txt[i] != '[=10=]' ; i++ ); // Find '$' location
if ( txt[i] == txt[i+1] && txt[i] == '$' ) { // Check $$ case
find = true;
get[++k] = ' ';
} // if
for ( j = i + 1 ; txt[j] != '$' && txt[j] != '[=10=]' ; j++ ){
find = true;
get[++k] = txt[j];
} // for
if ( find == true ) get[++k] = ' '; // add space
i = j ;
} // for
get[k] = '[=10=]'; // remove last space
printf( "%s", get );
return 0;
} // main()
输出:
21/01/2017 32/01/2017 abc
提取 $
之间的文本
这可以通过简单的 for
循环、读取和复制字符来完成。
在下面的代码中,参数 inside
表示我们当前是否在两个 $
之间
函数returns 1 if two $ were effective found
#include <stdio.h>
#include <string.h>
// return 1 if two $ have been found, 0 elsewhere
int extract (char *in, char *out, char c) {
if (in == NULL) return 0;
int size = strlen(in);
int inside = 0;
int n = 0; // size new string
for (int i = 0; i < size; ++i) {
if(in[i] == c) {
if (inside) {
inside = 2;
break; // 2nd $
}
inside = 1; // 1st $
} else {
if (inside) { // copy
out[n++] = in[i];
}
}
}
out[n++] = '[=10=]';
return inside == 2;
}
int main() {
char txt[80] = "Some text before /01/2017$";
char txt_extracted[80];
int check = extract (txt, txt_extracted, '$');
if (check) printf ("%s\n", txt_extracted);
else printf ("two $ were not found\n");
return 0;
}
有一个函数叫做 strtok。 (https://www.cplusplus.com/reference/cstring%20/strtok/)
这是一个关于它的视频:https://www.youtube.com/watch?v=34DnZ2ewyZo.
我试过这段代码:
#include <stdio.h>
#include <string.h>
int main()
{
char txt[] = "Some text before /01/2017$, some text, /04/2018$ another text more and more text /02/2019$";
int skip = 0;
char* piece = strtok(txt, "$");
while(piece != NULL)
{
piece = strtok(NULL, "$");
if(piece == NULL)
break;
if(skip != 1)
{
skip = 1;
printf("%s \n", piece);
}
else
skip = 0;
}
return 0;
}
输出:
11/01/2017
11/04/2018
01/02/2019
这是一个函数。无把手井边角案例。使用 string.h
函数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *texBetween(const char *str, char ch)
{
char *result = NULL;
const char *start, *end;
if(str)
{
start = strchr(str, ch);
if(start)
{
end = strchr(start + 1, ch);
if(end)
{
result = malloc(end - start);
if(result)
{
memcpy(result, start + 1, end - start - 1);
result[end - start] = 0;
}
}
}
}
return result;
}
int main()
{
char *result;
printf("\"%s\"\n", (result = texBetween("$$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("$ $", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("$test$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("test$$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("test$test1$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("test34$test$dfd", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween(NULL, '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("$", '$')) ? result : "ERROR"); free(result);
}
获得不修改原始字符串的单个标记的简单方法是使用两次调用 strcspn()
建立指向第一个分隔符的起始指针(在本例中为 '$'
)和指向标记中最后一个字符的结束指针(第二个 '$'
之前的字符或字符串结尾,如果没有第二个 '$'
存在)。然后验证起始指针和结束指针之间是否存在字符,并使用 memcpy()
复制令牌。
一个简短的例子是:
#include <stdio.h>
#include <string.h>
int main (void) {
char txt[80] = "Some text before /01/2017$",
*sp = txt + strcspn (txt, "$"), /* start ptr to 1st '$' */
*ep = sp + strcspn (*sp ? sp + 1 : sp, "$\n"), /* end ptr to last c in token */
result[sizeof txt] = ""; /* storage for result */
if (ep > sp) { /* if chars in token */
memcpy (result, sp + 1, ep - sp); /* copy token to result */
result[ep - sp] = 0; /* nul-termiante result */
printf ("%s\n", result); /* output result */
}
else
fputs ("no characters in token\n", stderr);
}
(注意: 三进制 只是处理 txt
是空字符串的情况。 '\n'
作为第二个定界符的一部分添加,以处理从 fgets()
或 POSIX getline()
过去的字符串,其中没有第二个 '$'
并且 '\n'
是最后一个字符在字符串中。)
也适用于空字符串、零、一或两个 '$'
的任意组合,并且不会修改原始字符串,因此可以安全地与 String-Literals 一起使用。
例子Use/Output
$ ./bin/single_token
11/01/2017
如果您还有其他问题,请告诉我。
允许有效空字符串作为结果的变体
@chqrlie 提供的巧妙改进提供 (*sp == '$')
而不是 (ep > sp)
的测试将允许空字符串(令牌中没有字符)成为有效结果 --我同意)。更改为:
if (*sp == '$') { /* if chars in token */
memcpy (result, sp + 1, ep - sp); /* copy token to result */
result[ep - sp] = 0; /* nul-termiante result */
printf ("%s\n", result); /* output result */
}
因此,如果您想将空标记(如 .csv 中的空字段,例如 "one,,three,four"
)视为有效标记,请使用此替代方法。
我有这个字符数组 char txt[80] = "Some text before /01/2017$";
并且需要将两个 $
之间的内容复制到一个字符串 11/01/2017
中。我如何使用 <string.h>
函数执行此操作?
假设您确定字符串中有 2 个 $
...您可以执行以下操作:
char *first_dollar = strchr(txt, '$'); //get position of first dollar from the start of string
char *second_dollar = strchr(first_dollar + 1, '$'); //get position of first dollar starting
// from one position after the first dollar
char tocopy[20];
*second_dollar = '[=10=]'; //change the value of last dollar to '[=10=]'
strcpy(tocopy, first_dollar + 1); //copy into the place you want
*second_dollar = '$'; // put back the second dollar
如果您不确定字符串中是否包含 2 $
,您应该检查 strchr
的 return,即 NULL
.
是否必须使用字符串?有一个聪明的方法使用 sscanf
:
char txt[80] = "Some text before /01/2017$";
char t[20];
sscanf(txt, "%*[^$]$%[^$]", t);
printf("ORIGINAL TEXT: %s\nEXTRACTED TEXT: %s\n", txt, t);
scanf中的格式含义如下:
- 忽略所有不是
$
; 的字符
- 忽略 1
$
。 - 读取所有字符,直到找到下一个
$
并将其存储在t
中。
我不知道你为什么要用string.h。
供您参考,这没有 string.h 方法。
更新
#include <stdio.h>
#include <string.h>
int main(){
char txt[80] = "Some text before /01/2017$ and /01/2017$ and $$ end $abc$";
char get[80] = { '[=10=]' };
int i = 0, k = -1, j = 0;
int len = strlen( txt ); // Get length
for ( i = 0 ; i < len ; i++ ){
bool find = false;
for ( i ; txt[i] != '$' && txt[i] != '[=10=]' ; i++ ); // Find '$' location
if ( txt[i] == txt[i+1] && txt[i] == '$' ) { // Check $$ case
find = true;
get[++k] = ' ';
} // if
for ( j = i + 1 ; txt[j] != '$' && txt[j] != '[=10=]' ; j++ ){
find = true;
get[++k] = txt[j];
} // for
if ( find == true ) get[++k] = ' '; // add space
i = j ;
} // for
get[k] = '[=10=]'; // remove last space
printf( "%s", get );
return 0;
} // main()
输出:
21/01/2017 32/01/2017 abc
提取 $
这可以通过简单的 for
循环、读取和复制字符来完成。
在下面的代码中,参数 inside
表示我们当前是否在两个 $
函数returns 1 if two $ were effective found
#include <stdio.h>
#include <string.h>
// return 1 if two $ have been found, 0 elsewhere
int extract (char *in, char *out, char c) {
if (in == NULL) return 0;
int size = strlen(in);
int inside = 0;
int n = 0; // size new string
for (int i = 0; i < size; ++i) {
if(in[i] == c) {
if (inside) {
inside = 2;
break; // 2nd $
}
inside = 1; // 1st $
} else {
if (inside) { // copy
out[n++] = in[i];
}
}
}
out[n++] = '[=10=]';
return inside == 2;
}
int main() {
char txt[80] = "Some text before /01/2017$";
char txt_extracted[80];
int check = extract (txt, txt_extracted, '$');
if (check) printf ("%s\n", txt_extracted);
else printf ("two $ were not found\n");
return 0;
}
有一个函数叫做 strtok。 (https://www.cplusplus.com/reference/cstring%20/strtok/) 这是一个关于它的视频:https://www.youtube.com/watch?v=34DnZ2ewyZo.
我试过这段代码:
#include <stdio.h>
#include <string.h>
int main()
{
char txt[] = "Some text before /01/2017$, some text, /04/2018$ another text more and more text /02/2019$";
int skip = 0;
char* piece = strtok(txt, "$");
while(piece != NULL)
{
piece = strtok(NULL, "$");
if(piece == NULL)
break;
if(skip != 1)
{
skip = 1;
printf("%s \n", piece);
}
else
skip = 0;
}
return 0;
}
输出:
11/01/2017
11/04/2018
01/02/2019
这是一个函数。无把手井边角案例。使用 string.h
函数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *texBetween(const char *str, char ch)
{
char *result = NULL;
const char *start, *end;
if(str)
{
start = strchr(str, ch);
if(start)
{
end = strchr(start + 1, ch);
if(end)
{
result = malloc(end - start);
if(result)
{
memcpy(result, start + 1, end - start - 1);
result[end - start] = 0;
}
}
}
}
return result;
}
int main()
{
char *result;
printf("\"%s\"\n", (result = texBetween("$$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("$ $", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("$test$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("test$$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("test$test1$", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("test34$test$dfd", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween(NULL, '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("", '$')) ? result : "ERROR"); free(result);
printf("\"%s\"\n", (result = texBetween("$", '$')) ? result : "ERROR"); free(result);
}
获得不修改原始字符串的单个标记的简单方法是使用两次调用 strcspn()
建立指向第一个分隔符的起始指针(在本例中为 '$'
)和指向标记中最后一个字符的结束指针(第二个 '$'
之前的字符或字符串结尾,如果没有第二个 '$'
存在)。然后验证起始指针和结束指针之间是否存在字符,并使用 memcpy()
复制令牌。
一个简短的例子是:
#include <stdio.h>
#include <string.h>
int main (void) {
char txt[80] = "Some text before /01/2017$",
*sp = txt + strcspn (txt, "$"), /* start ptr to 1st '$' */
*ep = sp + strcspn (*sp ? sp + 1 : sp, "$\n"), /* end ptr to last c in token */
result[sizeof txt] = ""; /* storage for result */
if (ep > sp) { /* if chars in token */
memcpy (result, sp + 1, ep - sp); /* copy token to result */
result[ep - sp] = 0; /* nul-termiante result */
printf ("%s\n", result); /* output result */
}
else
fputs ("no characters in token\n", stderr);
}
(注意: 三进制 只是处理 txt
是空字符串的情况。 '\n'
作为第二个定界符的一部分添加,以处理从 fgets()
或 POSIX getline()
过去的字符串,其中没有第二个 '$'
并且 '\n'
是最后一个字符在字符串中。)
也适用于空字符串、零、一或两个 '$'
的任意组合,并且不会修改原始字符串,因此可以安全地与 String-Literals 一起使用。
例子Use/Output
$ ./bin/single_token
11/01/2017
如果您还有其他问题,请告诉我。
允许有效空字符串作为结果的变体
@chqrlie 提供的巧妙改进提供 (*sp == '$')
而不是 (ep > sp)
的测试将允许空字符串(令牌中没有字符)成为有效结果 --我同意)。更改为:
if (*sp == '$') { /* if chars in token */
memcpy (result, sp + 1, ep - sp); /* copy token to result */
result[ep - sp] = 0; /* nul-termiante result */
printf ("%s\n", result); /* output result */
}
因此,如果您想将空标记(如 .csv 中的空字段,例如 "one,,three,four"
)视为有效标记,请使用此替代方法。