【问题标题】:Using atof() function in C with multiple input values在具有多个输入值的 C 中使用 atof() 函数
【发布时间】:2015-04-09 16:10:41
【问题描述】:

该程序的目标是创建一个函数,该函数读取单个字符串、用户键入的命令(最终用于与机器人一起使用的程序),其中包含一个未知的命令字(存储并打印为命令),以及未知数量的十进制参数(数量存储并打印为 num,参数将存储为数组 params 中的浮点值)。在用户输入中,命令和参数将用空格分隔。当我从字符串中提取十进制值时,我相信我的问题在于 atof 函数。我究竟做错了什么?感谢您的帮助!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func(char *input, char *command, int *num, float *params);

int main()
{
    char input[40]={};
    char command[40]={};
    int num;
    float params[10];

    printf("Please enter your command: ");
    gets(input);

    func(input,command,&num,params);

    printf("\n\nInput: %s",input);
    printf("\nCommand: %s",command);
    printf("\n# of parameters: %d",num);
    printf("\nParameters: %f\n\n",params);

    return 0;
}

void func(char *input, char *command, int *num, float *params)
{
    int i=0, k=0, j=0, l=0;
    int n=0;
    while(input[i]!=32)
    {
        command[i]=input[i];
        i++;
    }
    for (k=0; k<40;k++)
    {
        if ((input[k]==32)&&(input[k-1]!=32))
        {
            n++;
        }
    }
    *num=n;

    while (j<n)
    {
        for (l=0;l<40;l++)
        {
            if((input[l-1]==32)&&(input[l]!=32))
            {
                params[j]=atof(input[l]);
                j++;
            }
        }
    }
}

一个示例输出屏幕:

Please enter your command: Move 10 -10

Input: Move 10 -10
Command: Move
# of parameters: 2
Parameters: 0.000000

理想情况下,参数输出应为输出“10 -10”。谢谢!

【问题讨论】:

  • gets() 很危险,请改用fgets()
  • 您使用的是 C 还是 C++? C++ 解决方案是使用std::istringstream,而不需要所有这些检查空格。
  • 发布一些示例用法会有所帮助。
  • 固定大小的数组不利于用户输入(除非您将读取限制在该大小)
  • C != C++,自然解决方案可能会有所不同。一般来说,您应该只标记您正在学习/编写/编译的语言。

标签: c windows codeblocks


【解决方案1】:

atof(input[l]) 更改为atof(input + l)input[l] 是单个字符,但您想从 l 位置获取子字符串。另见strtod() 函数。

【讨论】:

  • @abligh sscanf 的错误检查与atof 相同,比strtod
【解决方案2】:

其他人已经在你的代码中指出了这个问题,但我可以建议你看看strtod()吗?

atof() strtod() 都会在开头为您丢弃空格(因此您无需手动操作),strtod() 将指向您的末尾编号,以便您知道从哪里继续:

while(j < MAX_PARAMS) // avoid a buffer overflow via this check
{
    params[j] = strtod(ptr, &end); // `end` is where your number ends
    if(ptr == end) // if end == ptr, input wasn't a number (say, if there are none left)
        break;
    // input was a number, so ...
    ptr = end; // continue at end for next iteration
    j++; // increment number of params
}

请注意,上述解决方案没有区分无效参数(例如,foo 而不是 3.5)和缺失参数(因为我们已经找到了最后一个参数)。你可以通过这样做来检查:if(!str[strspn(str, " \t\v\r\n\f")]) --- 这会检查我们是否在字符串的末尾(但允许尾随空格)。请参阅第二个附注了解它的作用。


旁注:

  • 您可以使用' ' 代替32 来检查空间;这有两个优点:

    1. 读者更清楚(很明显,它是一个空格,而不是“一些恰好有意义的幻数”)
    2. 它适用于非 ASCII 编码(该标准允许其他编码,尽管 ASCII 是迄今为止最流行的;一种常见的编码是 EBCDIC)
  • 为了将来参考,这个技巧可以帮助你跳过空格:ptr += strspn(ptr, " \t\v\r\n\f");strspn 返回与集合匹配的字符串开头的字符数(在本例中为" \t\v\r\n" 之一)。查看文档了解更多信息。

strspn 的示例:strspn("abbcbaa", "ab"); 返回 3,因为您在 c(不匹配)之前有 aab(匹配)。

【讨论】:

  • 次要:缺少'\f'。它是 6 个“C”语言环境空白的一部分。
  • @chux:我正要添加它,但当我认为'\f' 是空白时,我总是觉得奇怪,所以我想我不会把他和这个混淆。但我想你是对的 --- 我要添加它。
【解决方案3】:

您正在尝试将char 转换为float

params[j]=atof(input[l]);

你应该得到浮点数的整个单词(子字符串)。

例如,"12.01" 一个包含 5 个字符的以空字符结尾的字符串,并将其传递给 atofatof("12.01"),它将返回 double12.01

所以,您应该首先提取每个浮点参数的字符串并将其传递给atof

避免将字符与 ascii 值进行比较,而是可以直接使用 ' '(空格)。

您可以使用strlen()strnlen()来查找输入字符串的长度,而不是使用固定大小的for循环。

【讨论】:

  • 当我不知道子字符串的开始和结束位置(取决于第一个命令的长度)时,我将如何提取子字符串?
  • 您可以使用 strtok() 将输入拆分为令牌并保存。 pch = strtok (input," "); while (pch != NULL) { printf ("%s\n",pch); pch = strtok (NULL, " "); }
  • 并将第一个令牌存储为命令,然后将其余令牌转换并存储为浮点参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2012-07-30
  • 2018-12-30
  • 1970-01-01
  • 2022-01-10
  • 2011-05-26
  • 1970-01-01
相关资源
最近更新 更多