我正在尝试使用sscanf从字符串中获取所需的值,但我无法完成它。这是我想要做的:
我有一个具有此模式的字符串
2 7 A BUL
(3个元素的整数空间整数空格字符空格字符串)
我必须用空格分隔每个值并将其存储到变量中。
这是我的代码:
sscanf(string[i],"%d %d %s %s",&e,&m,id,modelo);
我遇到的问题是它只存储第一个整数,忽略了字符。
我该如何解决这个问题?
谢谢。
编辑:
这是函数的完整代码:
void le_lista(lista *l) {
int e,m;
char id[1],modelo[3],frase[20][12];
int linha=0;
while (1) {
fgets(frase[linha],12,stdin);
//
if (feof(stdin)) {
break;
}
//
linha++;
}
int i;
for(i=0;i<=linha;i++) {
sscanf(frase[i],"%d %d %s %s",&e,&m,&id,&modelo);
enfila(e,m,id,modelo,l);
//printf("%s",frase[i]);
}
printf("Linhas: %d",linha+1);
return;
}
答案 0 :(得分:2)
char mystring[] = "2 7 A BUL"
x = strtok(mystring, " "); //separates by spaces
答案 1 :(得分:1)
鉴于您要识别2 7 A BUL
,您无法安全使用:
int e,m;
char id[1], modelo[3];
sscanf(frase[i], "%d %d %s %s", &e, &m, &id, &modelo);
首先,您不应将char (*)[]
值传递到预期为char *
的位置;不要取数组的地址;仅传递id
和modelo
。如果你打开警告,GCC会警告你。如果你正在学习C,你就不能不打开警告(至少使用-Wall
; -Wall -Wextra
,如果可能的话)。
接下来,第一个%s
将读取任意数量的字符并将结果空终止。这将覆盖id
数组的末尾。你也无法安全地将3个字符读入modelo
。因此,您有两个stack overflow问题。
你应该写:
int e, m;
char id[2], modelo[4];
if (sscanf(frase[i], "%d %d %1s %3s", &e, &m, id, modelo) != 4)
...oops...
或者也许:
int e, m;
char id;
char modelo[4];
if (sscanf(frase[i], "%d %d %c %3s", &e, &m, &id, modelo) != 4)
...oops...
或者,您可以使用char id[1];
和%c
,但这很危险;结果不是以空字符结尾的字符串。
您的主要输入循环也是可疑的。您可以在feof()
之后立即使用fgets()
,但测试fgets()
本身的结果要更为常规;它告诉你它是否成功。该代码应该是:
char frase[20][12];
for (int linha = 0; i < sizeof(frase) / sizeof(frase[0]); i++)
{
if (fgets(frase[linha] ,sizeof(frase[linha]), stdin) == 0)
break;
}
这可以避免重复20或12,但可以保护您免受太多线条的伤害。它不能保护您免受过长线路的伤害;你可以补充一下:
size_t len = strlen(frase[linha]);
assert(len != 0);
if (frase[len-1] != '\n')
...input was too long...
循环。
您还可以考虑在主输入循环中执行sscanf()
并调用enfila()
;那么你就不需要frase
数组是多维的。
将所有更改放在一起:
char frase[4096];
while (fgets(frase, sizeof(frase), stdin) != 0)
{
int e;
int m;
char id[2];
char modelo[4];
if (sscanf(frase, "%d %d %1s %3s", &e, &m, id, modelo) == 4)
enfila(e, m, id, modelo, l); // l is the parameter to the function
else
...report error...
}
使用fgets()
和sscanf()
绝对是正确的方法。这意味着错误报告可以显示整个输入行,而不是遗留的任何遗留的scanf()
不可读。
答案 2 :(得分:0)
使用strtok
更简单,恕我直言更加稳固,因为你可以做一个简单的添加错误处理
e.g。
int j = 0;
for (char* token = strtok(frase[i]," "; token != NULL; token = strtok(NULL," ")
{
switch(j++)
{
case 0:
e = atoi(token);
break;
case 1:
m = atoi(token);
break;
case 2:
strncpy(id,token,sizeof(id)); // or strcpy_s
break;
case 3:
strncpy(modelo,token,sizeof(modelo)); // or strcpy_s
break;
default:
printf( "invalid number of arguments in line %d\n", i );
break;
}
}