【问题标题】:Convert hexadecimal numbers to decimal numbers将十六进制数转换为十进制数
【发布时间】:2018-07-04 08:18:32
【问题描述】:

我有一个文本文件,其中一行数字用空格分隔,如下例所示:

1 -2 3.1 0xf 0xcc

用C程序解析文件后,结果应该保存在一个向量中,其内部结构应该是:

V[0]=1
V[1]=-2
V[2]=3.1
V[3]=15
V[4]=204

基本上我需要将0x开头的数字转换成十进制数。

我尝试将所有元素存储在一个 char 向量中,然后将它们转换为数字,但没有太多成功。

任何有关 C 代码的帮助将不胜感激。谢谢

【问题讨论】:

  • strtol 以0 为基数将处理除3.1 之外的所有内容。对于3.1,您需要检查endptr 以意识到它不是整数,然后使用strtod 转换为double。
  • 感谢您提供信息。您能根据我的示例发布一个实际的代码示例吗?无论如何,谢谢。
  • 输入有顺序吗?或者不同种类的数字可以按任何顺序出现,你需要找出每个数字是哪种类型?

标签: c file hex decimal converter


【解决方案1】:

你可以有一个look atsscanf。这是一个简单的程序。我相信你可以从这里取货:

#include  <stdio.h>

int main(void)
{
    char *hex = "0xF";
    int i= 0;
    sscanf(hex, "%x", &i);
    printf("%d", i);
}

【讨论】:

    【解决方案2】:

    您需要的是用于整数类型的strtol 函数。您可以使用endptr 来遍历字符串。对于double,您可以使用atof 函数,但您必须首先检查字符串是否包含点。

    编辑:正如user3386109 提到的strtod 是double 的更好解决方案。

    假设你有一个数组中的字符串:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main()
    {
        char numbers_str[] = "1 -2 3.1 0xf 0xcc";
        int ints[10];
        double doubles[10];
        int ints_idx = 0, doubles_idx = 0;
    
        const char delims[] = " ";
        char *it = strtok(numbers_str, delims);
        while(it != NULL)
        {
            char *dot_it = strchr(it, '.');
            // When a dot is found then a double number is found
            if(dot_it)
                doubles[doubles_idx++] = strtod(it, NULL);
            // When a dot is not found then we've got an integer
            else
                ints[ints_idx++] = strtol(it, NULL, 0);
            it = strtok(NULL, delims);
        }
    
        printf("Integers found: \n");
        for(int i = 0; i < ints_idx; ++i)
            printf("%d\n", ints[i]);
    
        printf("Double numbers found: \n");
        for(int i = 0; i < doubles_idx; ++i)
            printf("%f\n", doubles[i]);
    }
    

    【讨论】:

    • 谢谢。您能否根据我的示例发布您建议的算法表示或一段代码,以使我更清楚?提前致谢!
    • 这里有一个简单的解决方案。它不考虑doubles 和ints 数组的溢出,但您可以简单地检查是否可能发生溢出并在动态分配的数组上使用realloc。
    【解决方案3】:

    处理从行中读取值的最简单方法是使用strtod 向下工作。 strtod 将两个指针作为参数。第一个指向搜索数字(或前导+/-)的起点,以便将数字的字符串表示形式转换为数值(跳过所有前导空格)。第二个指针指向指针 (endptr) 将设置为转换中使用的最后一个字符之后的下一个字符。您从那里开始搜索下一个要转换的数字(例如,设置 p = ep; 并重复该过程)。

    您可以查阅手册页以获取更多详细信息,但要验证转换是否成功,请检查指针是否不等于结束指针(意味着数字已转换)并检查以确保 errno 不是放。如果没有转换数字(意味着您有一个无效字符),您只需手动向前扫描该行,直到找到您的下一个 +/- 或 0-9(或者您点击 nul-terminating em> 字符)。

    您希望通过保留一个简单的计数器并在数组已满时退出循环来保护您的数组边界并限制您尝试存储在向量数组中的值的数量。

    这是一个简短的例子(NAN 和 INF 检查省略):

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    #define VECSZ 5   /* if you need a constant, define one (or more) */
    
    int main (int argc, char **argv) {
    
        int i, n = 0;
        double v[VECSZ] = {0.0};
        char buf[BUFSIZ] = "";
        FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    
        if (!fp) {  /* validate file open for reading */
            fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
            return 1;
        }
    
        while (n < VECSZ && fgets (buf, BUFSIZ, fp)) { /* read each line */
            char *p = buf, *ep;     /* pointer, end-pointer for strtod  */
            while (n < VECSZ) {     /* convert vales in buf until VECSZ */
                double tmp = strtod (p, &ep);
                if (p != ep) {                  /* digits converted  */
                    if (!errno)                 /* validate no error */
                        v[n++] = tmp;           /* add to vector  */
                    p = ep;                     /* update pointer */
                }
                else {  /* no digits converted */
                    fprintf (stderr, "error: no digits converted.\n");
                    /* scan forward to next valid '+,-,0-9' */
                    while (*p && *p != '-' && *p != '+' && (*p < '1' || '9' < *p))
                        p++;
                    if (*p)         /* numbers remain in line */
                        continue;
                    break;          /* otherwise get next line */
                }
            }
        }
        if (fp != stdin) fclose (fp);   /* close file if not stdin */
    
        for (i = 0; i < n; i++)
            printf ("v[%d]=% g\n", i, v[i]);
    
        return 0;
    }
    

    输入文件示例

    $ cat dat/strtod_vect.txt
    1 -2 3.1 0xf 0xcc
    

    使用/输出示例

    $ ./bin/strtod_vect dat/strtod_vect.txt
    v[0]= 1
    v[1]=-2
    v[2]= 3.1
    v[3]= 15
    v[4]= 204
    

    查看一下,如果您还有其他问题,请告诉我。您可以查看strtod(3) - Linux man page 了解更多详细信息和可以进行的错误检查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-26
      • 1970-01-01
      • 2013-05-31
      • 2014-04-16
      • 1970-01-01
      • 2010-10-16
      相关资源
      最近更新 更多