0

我正在尝试使用 sscanf 从字符串中获取所需的值,但无法完成。这是我正在尝试做的事情:

我有一个具有这种模式的字符串

2 7 公牛

(整数空间整数空间字符空间字符串的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;

}

4

3 回答 3

2
char mystring[] = "2 7 A BUL"
x = strtok(mystring, " ");  //separates by spaces

更多在这里使用 C 中的分隔符拆分字符串

于 2013-07-28T19:44:41.327 回答
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 (*)[]a 的地方传递值;char *不要取数组的地址;通过id并且modelo只有。如果您打开警告,GCC 会警告您。如果你正在学习 C,你不能不打开警告(-Wall至少使用;-Wall -Wextra如果可能的话)。

接下来,第一个%s将读取任意数量的字符并将结果以空值结尾。这将覆盖id数组的末尾。而且你不能安全地读入 3 个字符modelo。因此,您有两个堆栈溢出问题。

你应该写:

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];and %c,但这很危险;结果不是以 null 结尾的字符串。

您的主要输入循环也值得怀疑。您可以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()andsscanf()绝对是正确的方法。这意味着错误报告可以显示整个输入行,而不是任何被破坏的仍然scanf()留在后面的不可读的内容。

于 2013-07-28T20:46:30.003 回答
0

改用strtok它更简单,恕我直言,更可靠,因为您可以进行简单的添加错误处理

例如

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;
  }
}
于 2013-07-28T20:18:21.780 回答