【问题标题】:Read input consisting a command option and arguments, separated by white spaces, in C读取由 C 语言中的命令选项和参数组成的输入,以空格分隔
【发布时间】:2017-08-24 11:07:49
【问题描述】:

我的用户输入包含 3 个或更少的参数,由空格分隔,例如

A Name 20

第一个参数“A”(在本例中为 Add)表示一个命令选项,它决定如何处理其余输入。本例中的第二个参数是要添加到结构元素链表的名称,最后一个参数是要存储在同一结构元素上的 int 类型值。

其他命令选项包括例如'P' 用于打印列表中的所有元素,'D Name' 用于从列表中删除具有给定名称的元素。

到目前为止,我有以下代码,但它似乎不能很好地工作。我只包括了 addElem 函数,因为整个事情似乎有问题。我不知道我的代码到底出了什么问题。当我尝试通过例如添加元素时'A Name 20',我得到多行'Invalid command',并且在列表中似乎没有找到该元素。开关循环不是完全处理这个问题的好方法,还是我在这里做了其他非常错误的事情?

typedef struct element {
   char *name;
   int val;
   struct element *next;
} Elem;

/* Read name dynamically */
char *readName()
{
   int ch, i = 0;
   char *name = malloc(1);

   name[0] = '\0';
   do {
      ch = getchar();
      name = realloc(name, (i + 2));
      name[i] = (char) ch;
      name[i+1] = '\0';
      i++;
   } while (ch != ' ' && ch != '\n');

   return name;
}

/* Add element "name" into linked list */
Elem *addElem(Elem *first)
{
   /* Create new element */
   Elem *new_elem = malloc(sizeof(Elem));

   new_elem->name = readName();
   scanf(" %d", &new_elem->val);
   new_elem->next = NULL;

   /* Add new element to linked list */
   if (first == NULL)
      first = new_elem;
   else {
      Elem *ptr = first;
      while (ptr->next != NULL)
         ptr = ptr->next;
      ptr->next = new_elem;
   }

   return first;
}

int main()
{
   char cmd;
   Elem *first = malloc(sizeof(Elem));

   while (1) {
      scanf("%c", &cmd);
      switch (cmd) {
         case 'A':
            first = addElem(first);
            break;
         case 'D':
            first = delElement(first);
            break;
         case 'P':
            printElems(first);
            break;
         default:
            printf("Invalid command\n");
            break;
      }
   }

   return 0;
}

【问题讨论】:

  • 如果您希望每行有一个“命令”,那么最好逐行读取输入,然后解析每一行。
  • malloc() / realloc() 通常会带来相关的运行时成本。使用更大的块来避免过多的调用!
  • 感谢您的建议!我开始认为解析整行会容易得多。

标签: c input dynamic switch-statement scanf


【解决方案1】:

您的代码读入的第一件事是“A”。然后它读取名称直到下一个空格...由于 A 后面有一个空格,这意味着它在读取一个字符后停止。然后它尝试读入一个数字,因为此时我们仍处于第二个字段的开头。

到目前为止,您只阅读了“A”,现在您又回到了代码的开头,这就是您收到大量“无效命令”消息的原因。

如果您将整行读入一个字符串并将其作为一个命令处理而不是零碎地读取,您会好得多。下面是一个简单的示例,说明您可以如何做到这一点。

char cmdline[1024],*pos;
int num;
char name[50], *namepos;

if(fgets(cmdline,1024,stdin))
  {
  switch(*cmdline)
    {
  case 'A':
    pos=cmdline+1;
    while(isspace(*pos)) pos++;
    namepos=name;
    while((*pos)&&(!isspace(*pos)))
      {
      *namepos=*pos;
      namepos++;
      pos++;
      }
    *namepos='\0';
    if(sscanf(pos," %d",&num)==1)
      {
      // Do stuff now that you've processed the line
      }
  break;
    }
  }

【讨论】:

  • 谢谢!这似乎确实是一种更好的方法。
猜你喜欢
  • 1970-01-01
  • 2012-10-17
  • 2015-03-08
  • 1970-01-01
  • 2021-02-17
  • 2017-03-18
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多