【问题标题】:Variable input read from stdin从标准输入读取的变量输入
【发布时间】:2014-03-17 23:25:42
【问题描述】:

我有一个疑问,例如,如果我有这样的输入:

5 4
1 2 3 4 5
2 3 4
2 3
1 2 3

第一个数字表示不同的“玩具”,每个孩子对应于第二个数字,即四,因此代表每个孩子的行数和他们想要的玩具......

如何在 ansi C 中读取这样的输入? 用strtok?或者还有其他更简单的方法吗?

我可以这样做

char line [250];
char * tok;
char *ptr = line;


while((scanf("%s",line)!= EOF){

    while ((tok = strtok(ptr, " ")) != NULL)
    {
        pseudo part
        //convert to int
        //add to array

    }

}

但是有没有更简单的方法可以在不使用 tok 的情况下进行此输入? 谢谢...

【问题讨论】:

  • ptr的来源应该是个谜吗?
  • 您阅读过strtok 的手册页吗?连续调用使用 NULL 而不是原始值。
  • 我举了一个例子,就像我说的那样,我不想再像上面所说的那样使用 strtok 的替代方法,我想要另一种方法来做到这一点......
  • scanf("%s", line) 不会读取一行,它会读取一个空格分隔的字符串,所以你不需要strtok
  • 如果您至少阅读过输入的工作原理,您就会明白为什么要使用 strtok...。

标签: c input stdin


【解决方案1】:

推荐一个经典的fgets()/sscanf()组合。

一次读一行。提供良好的错误检查。使用"%n" 知道从哪里开始扫描下一个玩具。

char buffer[250];
if (fgets(buffer, sizeof buffer, stdin) == NULL)
  HandleEOF();
int toys, kids;
int cnt = sscanf(buffer, "%d%d", &toys, &kids);
if (cnt != 2 || toys <= 0 || kids <= 0)
  Handle_BadToysKids(cnt);
int kid_wants[kids][toys] = { 0 };

for (int k = 0; k < kids; k++) {
  if (fgets(buffer, sizeof buffer, stdin) == NULL)
    HandleEOF();
  char *p = buffer;
  int want;
  int n;
  while ((cnt = sscanf(p, "%d %n", &want, &n)) == 1) {
    if (want <= 0 || want > toys)
      Handle_BadWant(want);
    kid_wants[k][want - 1] = 1;
    p += n;
  }
}

改进:
使用size_t toys, kids"%zu"
使用 sentinel 检查线路上的多余垃圾:
int ch; int cnt = sscanf(buffer, "%d%d %c", &amp;toys, &amp;kids, &amp;ch);
while 循环的末尾检查*p - 它应该是'\0'

【讨论】:

    【解决方案2】:

    您可以使用fgets 读取一行,而不是scanf。 scanf 只会读取到第一个空格。 (最好使用fgets,因为它比gets更安全)

    像这样:

    ptr = fgets(line,sizeof(line),stdin);
    

    如果您在第一次调用后将 ptr 设置为 NULL,您的 strtok 将起作用。 无论如何,最好添加更多空格,例如:" \r\n\t"

    //assume ptr = line had been set by fgets...
    char* tok;
    do{
       const char* whitespaces = " \r\n\t";
       tok = strtok(ptr, whitespaces);
       ptr = NULL;//till next fgets
       if(tok){
          //got more number  
       }
    }while(tok);
    

    【讨论】:

      最近更新 更多