我希望 name 保留行中剩余的所有字符,直到'\0'.
#include <stdio.h>
int main(){
char line[] = "1999-08-01,14.547,0.191,United Kingdom";
unsigned int year, month, day;
float temp, uncertainty;
char name[100];
sscanf(line, "%u - %u - %u, %f , %f , %s", &year, &month,
&day, &temp, &uncertainty, name);
printf("%u-%u-%u,%lf,%lf,%s\n", year, month, day, temp, uncertainty, name);
}
Run Code Online (Sandbox Code Playgroud)
我可以让这个工作像这样:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char line[] = "1999-08-01,14.547,0.191,United Kingdom";
char* newline = malloc(strlen(line) + 2);
strcpy(newline, line);
newline[strlen(newline)] = '\n';
newline[strlen(newline)] = '\0';
unsigned int year, month, day;
float temp, uncertainty;
char name[100];
sscanf(line, "%u - %u - %u, %f , %f , %[^\n]", &year, &month,
&day, &temp, &uncertainty, name);
printf("%u-%u-%u,%lf,%lf,%s\n", year, month, day, temp, uncertainty, name);
}
Run Code Online (Sandbox Code Playgroud)
但我觉得这非常不优雅。
这应该有效:
char line[] = "1999-08-01,14.547,0.191,United Kingdom";
unsigned int year, month, day;
float temp, uncertainty;
char name[100];
sscanf(line, "%u - %u - %u, %f , %f , %99[^\n]", &year, &month,
&day, &temp, &uncertainty, name);
printf("%u-%u-%u,%lf,%lf,%s\n", year, month, day, temp, uncertainty, name);
Run Code Online (Sandbox Code Playgroud)
'\n'将找不到,但由于不会达到 99 的限制,因此sscanf将继续读取直到字符串结尾标记。
sscanf不是最优雅的界面,但它有很多功能。其中之一是能够找出您在输入字符串中的位置,这使您可以提取(或仅指向)“输入的其余部分”。
例如,之后;
int nchar = -1;
int nfield = sscanf(line, "%u - %u - %u, %f , %f , %n", &year, &month,
&day, &temp, &uncertainty, &nchar);
Run Code Online (Sandbox Code Playgroud)
ncharline将包含名称字段的偏移量(除非它仍然是-1,表示sscanf无法匹配格式字符串)。如果该字段延伸到 的末尾line,则可以直接使用它 ( line + nchar) 或在检查它是否太长后将其复制到另一个字符串中。
如果line与它的名称相反,包含多行,并且您想要提取字符串直至换行符,则可以使用两种%n格式,%*[^\n]中间带有一个(星号抑制复制,从而避免溢出问题):
char name[NAME_MAX + 1];
int nstart = -1, nend = -1;
int nfield = sscanf(line, "%u - %u - %u, %f , %f , %n%*[^\n]%n", &year, &month,
&day, &temp, &uncertainty, &nstart, &nend);
if (nend > 0) {
if (nend - nstart <= NAME_MAX) {
memcpy(name, line + nstart, nend - nstart);
name[nend - nstart] = 0;
}
else {
/* name is too long */
}
}
else if (nstart > 0) {
/* Name was 0 bytes long. Sscanf requires that %[ match at least
* one character; if not, it fails the scan.
*/
name[0] = 0; /* Perhaps you wanted to signal an error
}
else {
/* Line didn't match format */
}
Run Code Online (Sandbox Code Playgroud)
显然,当我知道缓冲区有多大时,我可以避免使用固定长度缓冲区以及通过动态分配缓冲区来检查溢出的需要:
char* name = NULL;
// ...
if (nend > 0)
name = strndup(line + nstart, nend - nstart);
// or, if you don't like strndup
// name = malloc(nend - nstart + 1);
// memcpy(name, line + nstart);
// name[nend - nstart] = 0;
Run Code Online (Sandbox Code Playgroud)
如果您真正想要的是动态分配的字符串并且您有一个符合 Posix 的字符串sscanf,则可以通过使用m长度修饰符来避免这种麻烦,这是最全面的最简单的解决方案。
char* name = NULL;
int nfield = sscanf(line, "%u - %u - %u, %f , %f , %m[^\n]", &year, &month,
&day, &temp, &uncertainty, &name);
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅您的sscanf联机帮助页。在所有动态分配的情况下name,不要忘记在使用完毕后释放它。
| 归档时间: |
|
| 查看次数: |
6716 次 |
| 最近记录: |