如何在 char 数组的特定索引处获取实际值

Posted

技术标签:

【中文标题】如何在 char 数组的特定索引处获取实际值【英文标题】:How to get the actual Value at a specific index of a char array 【发布时间】:2014-06-15 21:23:14 【问题描述】:

我正在制作一个用于日期验证的程序。我以 MM/DD/YYYY 的形式接收来自用户的输入并将其存储为字符数组。

首先,我尝试通过强制转换将其分解为月日和年的 int 变量

 char UserDate[10];
 int month = 00, day = 00, year = 0000;
 cout << "Enter a date in the format of MM/DD/YYYY" << endl;
 cin >> UserDate;
 month = (int)UserDate[0] + (int)UserDate[1];
 day = (int)UserDate[3] + (int)UserDate[4];
 year = (int)UserDate[6] + (int)UserDate[7] + (int)UserDate[8] + (int)UserDate[9];

然后我尝试了没有强制转换

 char UserDate[10];
 int month = 00, day = 00, year = 0000;
 cout << "Enter a date in the format of MM/DD/YYYY" << endl;
 cin >> UserDate;
 month = UserDate[0] + UserDate[1];
 day = UserDate[3] + UserDate[4];
 year = UserDate[6] + UserDate[7] + UserDate[8] + UserDate[9];

问题是我无法从数组的索引中获取实际值。 我输入的日期01/01/2014得到的结果如下:

month = 48'0' + 49'1'; //months value is 97
day = 48'0' + 49'1'; //days value is 97
year = 50'2' + 48'0' + 49'1' + 52'4'; //years value is 199

无论我是否将 char 转换为 int,上述两种方法都会发生这种情况。由于没有UserDate[1].Value,如何获取存储在我想要的索引中的值??

【问题讨论】:

使用scanf 读取整数值。 @JoelCornett 他为什么要这么做? 【参考方案1】:

强制转换不会将 char 转换为 int。减去 '0' 得到 int 值。

month = 10 * (UserDate[0] - '0') + UserDate[1] - '0';

【讨论】:

b-e-a-u-tiful.. 但为什么是 10 *?你能解释一下为什么会这样吗? @AndyLink 因为数字的小数位老兄!对超过 99 的数字使用额外的 100 * (UserDate[0] - '0') + ... 大声笑我在任何地方都看不到任何小数位。我在调试器中看到为什么 - 0 所以我明白了,但我仍然不明白 10 * 部分..【参考方案2】:

您的UserDate 数组实际上是一个字符数组,每个字符都由一个标准的 ASCII 代码表示(请参阅完整的 ASCII 表 here)。像您一样使用显式转换会导致将字符(无论是字母还是数字)转换为整数 ASCII 码。例如 - 字符 '0' 的 ASCII 值为 48,因此写入 (int)'0' 等于 48。

由于数字 0-9 在 ASCII 表中顺序出现,您可以通过以下方式评估每个字符:

int digit = (int)UserDate[...] - '0'

这里的数学很简单,所以我相信你明白为什么这是真的。

请注意,如果您的字符不是数字,则此转换将导致负整数或大于 9 的数字,因此您应检查收到的值是否有效。

【讨论】:

【参考方案3】:

您在这里遇到的问题是 C 不会以这种方式将字符转换为数字。 char 是一个 1 字节的数字。 char 是有符号还是无符号取决于您的编译器,除非您在代码中特别指定。如果我这样做:

char x = '1';
int y = (int)x;

实际上,我的编译器和平台上都有 y = 49。这是字符 1 的 ASCII 值,出于本次讨论的目的,对于其他人来说可能会有所不同(特别是,如果我将 x 设为无符号字符,我可能没问题,并且 1 的 ASCII 值足够低,以至于无论如何可能是这样)。除非您知道自己在做什么,否则不要假设 chars 会保留特定的值。有些人将它们用作微小的整数,如果您了解 ASCII,则可以使用一些技巧。在我看来,最好把它们藏在图书馆里,或者只在非常特殊的情况下使用。

其次,您不能只添加转换后的值:即使假设转换有效,您也要添加数字 - 对于 1999 年,您的方法会给出 28。因为它没有,所以您得到了什么是该部分字符串的 ASCII 值的总和。如果要 + 连接字符串,则必须使用 std::string 来处理所有内容。否则,字符基本上是 1 字节整数。

如果您绝对、绝对肯定字符串是有效的,您可以执行以下操作。如果它无效,则会中断,因此您需要验证字符串。这是一个演示该技术的程序。这不是最佳编码实践:您可能应该使用 std::string,使 parseDate 成为构造函数,并做一些其他事情。我故意以牺牲一些良好的设计实践为代价保持这一点。实际上,我建议寻找一个日期处理库:boost.date_time 不是我用过的东西,但根据我对 boost 其他部分的经验,它会成为我的首选。除非这是一个非常小的项目,否则您最终将需要更多功能,为什么要重新发明***?总之:

#include <stdio.h>

class date 
    public:
    int day, month, year;
;

date parseDate(const char* str) 
    date d;
    sscanf(str, "%i/%i/%i", &d.month, &d.day, &d.year);
    return d;


void main() 
    char test[255];
    scanf("%s", &test);
    date d = parseDate(test);
    printf("%i %i %i", d.day, d.month, d.year);

请注意,至少在我看来,sscanfscanf 实际上在很多方面都比cincout 更强大——专门针对这种解析,并且没有引入外部库,他们几乎总是我的第一选择。由于您已经在使用 char 数组(这是不安全的,您可能应该使用 std::string),因此您不需要额外的转换。如果您需要将 std::string 传递给它,请使用 std::string::c_str(),如:

string dateString;
cin>>dateString;
date d = parseDate(dateString.c_str());

希望这会有所帮助。

【讨论】:

以上是关于如何在 char 数组的特定索引处获取实际值的主要内容,如果未能解决你的问题,请参考以下文章

如何根据数组值获取索引

在 NSMutableArray 的特定索引处添加对象

如何在 numpy / scipy 中获取特定百分位数的索引?

从特定索引处的列表中检索值

如果某个值存在于某个数组索引处,我如何检查 JavaScript?

如何使用javascript对属性上的数组进行分组以在特定键处获得每个组的聚合值?