从混合字符串中获取值

时间:2013-07-28 19:37:43

标签: c scanf

我正在尝试使用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;

}

3 个答案:

答案 0 :(得分:2)

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

更多Split string with delimiters in C

答案 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 *的位置;不要取数组的地址;仅传递idmodelo。如果你打开警告,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;
  }
}