假设我有一个字符串"file1.h: file2.c,file3.cpp"
,我希望将其拆分为"file1.h"
和"file2.c,file3.cpp"
- 即使用:
(:
和空格)作为分隔符。我该怎么办?
我在没有帮助的情况下尝试了这段代码:
int main(int argc, char *argv[]) {
char str[] = "file1.h: file2.c,file3.cpp";
char name[100];
char depends[100];
sscanf(str, "%s: %s", name, depends);
printf("Name: %s\n", name);
printf("Deps: %s\n", depends);
}
我得到的输出是:
姓名:file1.h:
的DEP:
答案 0 :(得分:2)
您似乎需要的是strtok()
。在man page中了解相关信息。来自C11
的相关引用,章节§7.24.5.8
对
strtok
函数的一系列调用将s1
指向的字符串分成一个 标记序列,每个标记由指向的字符串中的字符分隔 按s2
。 [...]
在您的情况下,您可以使用像
这样的分隔符 char * delim = ": "; //combination of : and a space
去完成工作。
另外值得一提的是,
strtok()
答案 1 :(得分:1)
正如Sourav所说,你真的需要使用strtok
来标记字符串。但是,这并不能解释为什么您的现有代码无效。
答案在于sscanf
的规范以及它如何处理格式字符串中的'%s'
。
来自man
页面:
s匹配一系列非空白字符;
因此,格式字符串中冒号空格的存在与计算第一个'%s'
无关。当sscanf
看到第一个%s
时,它只会消耗输入字符串,直到遇到空白字符,为您提供name
"file1.h:"
的值(请注意包含冒号) )。
接下来,它会尝试处理格式字符串中的冒号空间序列。
再次,从man
页面
格式字符串由一系列指令组成,这些指令描述了如何处理输入字符序列。
冒号空间序列与任何已知指令都不匹配(即"%"后跟某些内容),因此会出现匹配失败。
如果您的格式字符串只是"%s%s"
,那么sscanf
几乎可以让您获得所需内容。
int main(int argc, char *argv[]) {
char str[] = "file1.h: file2.c,file3.cpp";
char name[100];
char depends[100];
sscanf(str, "%s%s", name, depends);
printf("str: '%s'\n", str);
printf("Name: %s\n", name);
printf("Deps: %s\n", depends);
return 0;
}
这给出了这个输出:
str: 'file1.h: file2.c,file3.cpp'
Name: file1.h:
Deps: file2.c,file3.cpp
此时,您可以简单地检查sscanf
返回值是否为2(即找到两个值),name
的最后一个字符是冒号。然后截断name
即可得到答案。
当然,按照这种逻辑,您无法使用sscanf
将depends
变量解析为多个字符串......这就是为什么其他人建议使用{ {1}},strtok
等,因为您正在解析和标记您的输入。
答案 2 :(得分:1)
这是另一种方法,它使用strchr()
,但这假设输入字符串始终具有格式
name: item1,item2,item3,...,itemN
这是程序
#include <string.h>
#include <stdio.h>
int
main(void)
{
const char *const string = "file1.h: file2.c,file3.cpp ";
const char *head;
const char *tail;
const char *next;
// This basically makes a pointer to the `:'
head = string;
// If there is no `:' this string does not follow
// the assumption that the format is
//
// name: item1,item2,item3,...,itemN
//
if ((tail = strchr(head, ':')) == NULL)
return -1;
// Save a pointer to the next character after the `:'
next = tail + 1;
// Strip leading spaces
while (isspace((unsigned char) *head) != 0)
++head;
// Strip trailing spaces
while (isspace((unsigned char) *(tail - 1)) != 0)
--tail;
fputc('*', stdout);
// Simply print the characters between `head' and `tail'
// you could as well copy them, or whatever
fwrite(head, 1, tail - head, stdout);
fputc('*', stdout);
fputc('\n', stdout);
head = next;
while (head != NULL) {
tail = strchr(head, ',');
if (tail == NULL) {
// This means there are no more `,'
// so we now try to point to the end
// of the string
tail = strchr(head, '\0');
}
// This is basically the same algorithm
// just with a different delimiter which
// will presumably be the same from
// here
next = tail + 1;
// Strip leading spaces
while (isspace((unsigned char) *head) != 0)
++head;
// Strip trailing spaces
while (isspace((unsigned char) *(tail - 1)) != 0)
--tail;
// Here is where you can extract the string
// I print it surrounded by `*' to show that
// it's stripping white spaces
fputc('*', stdout);
fwrite(head, 1, tail - head, stdout);
fputc('*', stdout);
fputc('\n', stdout);
// Try to point to the next one
// or make head `NULL' if this is
// the end of the string
//
// Note that the original `tail' pointer
// that was pointing to the next `,' or
// the end of the string, has changed but
// we have saved it's original value
// plus one, we now inspect what was
// there
if (*(next - 1) == '\0') {
head = NULL;
} else {
head = next;
}
}
fputc('\n', stderr);
return 0;
}
它过分评论指导读者。
答案 3 :(得分:0)
好吧,我已经很晚了。我对C中的内置函数知之甚少。所以我开始为你编写一个解决方案。我认为你现在不需要这个。但是,无论如何here it is并根据您的需要进行修改。如果您发现任何错误,请随时告诉。