如何在 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);
请注意,至少在我看来,sscanf
和scanf
实际上在很多方面都比cin
和cout
更强大——专门针对这种解析,并且没有引入外部库,他们几乎总是我的第一选择。由于您已经在使用 char 数组(这是不安全的,您可能应该使用 std::string),因此您不需要额外的转换。如果您需要将 std::string 传递给它,请使用 std::string::c_str(),如:
string dateString;
cin>>dateString;
date d = parseDate(dateString.c_str());
希望这会有所帮助。
【讨论】:
以上是关于如何在 char 数组的特定索引处获取实际值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 numpy / scipy 中获取特定百分位数的索引?