繁体   English   中英

如何从C中的字符串中提取子字符串?

[英]How to extract a substring from a string in C?

我尝试使用 strncmp 但它只有在我给它指定要提取的特定字节数时才有效。

char line[256] = This "is" an example. //I want to extract "is"
char line[256] = This is "also" an example. // I want to extract "also"
char line[256] = This is the final "example".  // I want to extract "example"
char substring[256]

我将如何提取“”之间的所有元素? 并将其放入变量子字符串中?

注意:在我意识到编写的代码会导致问题后,我编辑了这个答案,因为strtok不喜欢对const char*变量进行操作。 这更像是我如何编写示例的人工制品,而不是基本原则的问题——但显然它应该得到双重否决。 所以我修好了。

以下工作(在 Mac OS 10.7 上使用 gcc 测试):

#include <stdio.h>
#include <string.h>

int main(void) {
const char* lineConst = "This \"is\" an example"; // the "input string"
char line[256];  // where we will put a copy of the input
char *subString; // the "result"

strcpy(line, lineConst);

subString = strtok(line,"\""); // find the first double quote
subString=strtok(NULL,"\"");   // find the second double quote

printf("the thing in between quotes is '%s'\n", subString);
}

这是它的工作原理: strtok查找“分隔符”(第二个参数)——在这种情况下,第一个" 。在内部,它知道“它走了多远”,如果你用NULL作为第一个参数再次调用它(而不是一个char* ),它将从那里重新开始。因此,在第二次调用时,它返回“恰好是第一个和第二个双引号之间的字符串”。这就是你想要的。

警告: strtok通常用'\\0'替换分隔符,因为它“吃掉”了输入。 因此,您必须依靠这种方法修改您的输入字符串。 如果这是不可接受的,您必须先制作本地副本。 本质上,当我将字符串常量复制到变量时,我在上面这样做了。 通过调用line=malloc(strlen(lineConst)+1);来做到这一点会更清晰line=malloc(strlen(lineConst)+1); free(line); 之后 - 但如果你打算将它包装在一个函数中,你必须考虑在函数返回后返回值必须保持有效......因为strtok返回一个指向字符串内正确位置的指针,它不会产生令牌的副本。 传递一个指向您希望结果结束的空间的指针,并在函数内部创建该空间(具有正确的大小),然后将结果复制到其中,将是正确的做法。 这一切都非常微妙。 如果这不清楚,请告诉我!

如果你想在没有库支持的情况下做到这一点......

void extract_between_quotes(char* s, char* dest)
{
   int in_quotes = 0;
   *dest = 0;
   while(*s != 0)
   {
      if(in_quotes)
      {
         if(*s == '"') return;
         dest[0]=*s;
         dest[1]=0;
         dest++;
      }
      else if(*s == '"') in_quotes=1;
      s++;
   }
}

然后调用它

extract_between_quotes(line, substring);

要做到这一点,还有很长的路要走:假设要提取的字符串将用引号引起来(已修复以下注释中 kieth 建议的错误检查)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    char input[100];
    char extract[100];
    int i=0,j=0,k=0,endFlag=0;

    printf("Input string: ");
    fgets(input,sizeof(input),stdin);
    input[strlen(input)-1] = '\0';

    for(i=0;i<strlen(input);i++){
        if(input[i] == '"'){

                j =i+1;
                while(input[j]!='"'){
                     if(input[j] == '\0'){
                         endFlag++;
                         break;
                     }
                     extract[k] = input[j];
                     k++;
                     j++;
                }
        }
    }
    extract[k] = '\0';

    if(endFlag==1){
        printf("1.Your code only had one quotation mark.\n");
        printf("2.So the code extracted everything after that quotation mark\n");
        printf("3.To make sure buffer overflow doesn't happen in this case:\n");
        printf("4.Modify the extract buffer size to be the same as input buffer size\n");

        printf("\nextracted string: %s\n",extract);
    }else{ 
       printf("Extract = %s\n",extract);
    }

    return 0;
}

输出(1):

$ ./test
Input string: extract "this" from this string
Extract = this

输出(2):

$ ./test
Input string: Another example to extract "this gibberish" from this string
Extract = this gibberish

输出(3):(Kieth 建议的错误检查)

$ ./测试

Input string: are you "happy now Kieth ?
1.Your code only had one quotation mark.
2.So the code extracted everything after that quotation mark
3.To make sure buffer overflow doesn't happen in this case:
4.Modify the extract buffer size to be the same as input buffer size

extracted string: happy now Kieth ?

-------------------------------------------------- -------------------------------------------------- -----------------------------

虽然没有被要求 - 以下代码从输入字符串中提取多个单词,只要它们在引号中:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    char input[100];
    char extract[50];
    int i=0,j=0,k=0,endFlag=0;

    printf("Input string: ");
    fgets(input,sizeof(input),stdin);
    input[strlen(input)-1] = '\0';

    for(i=0;i<strlen(input);i++){
        if(input[i] == '"'){
            if(endFlag==0){
                j =i+1;
                while(input[j]!='"'){
                     extract[k] = input[j];
                     k++;
                     j++;
                }
                endFlag = 1;
            }else{
               endFlag =0;
            }

            //break;
        }
    }

    extract[k] = '\0';

    printf("Extract = %s\n",extract);

    return 0;
}

输出:

$ ./test
Input string: extract "multiple" words "from" this "string"
Extract = multiplefromstring

您是否尝试过查看strchr函数? 您应该能够调用该函数两次以获取指向"字符的第一个和第二个实例的指针,并使用memcpy和指针算法的组合来获得所需的内容。

#include <string.h>
...        
substring[0] = '\0';
const char *start = strchr(line, '"') + 1;
strncat(substring, start, strcspn(start, "\""));

省略了边界和错误检查。 避免strtok因为它有副作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM