c - 将数字拆分为 C 中的位置值
问题描述
我想打印一个整数的细分,只输出非零数字。例如:./printint 23401 将打印:20000 + 3000 + 400 + 1 注意:0 的十位值被省略。
到目前为止,这是我的代码:
#include <stdio.h>
int main(int argc, const char * argv[]) {
int n = 23401;
int g,s,b,q,w;
g=n%10;
s=(n/10)%10*10;
b=(n/100)%10*100;
q= (n/1000)%10*1000;
w= n/10000*10000;
printf("%d" ,"+","%d","+","%d","+","%d","+","%d\n",w,q,b,s,g);
return 0;
}
我是编码新手,也是 C 新手。我也在尝试获得输入,但很难彻底思考,所以我只是使用问题中的示例。另外,我对 printf() 中的连接样式有疑问。
解决方案
与任何问题一样,您只需将复杂问题分解为可以解决的较小问题,为每个部分编写一个解决方案,然后将所有单独的编码解决方案合并到您的最终代码中。在这种情况下,可以认为是:
- 提示用户输入,
- 读取并验证用户输入,
0
处理没有附加组件的用户输入的极端情况,- 确定输入的数字是否为负数,使其为正数并保存标志,指示原始数字为负数,
- 确定用户输入的数字中的位数,
- 为这么多数字生成 10 的幂,
- 循环除以 10 的幂的数字,输出由
digit * power of 10
(如果非零)形成的 10 的结果幂,然后将数字减少该数量并将 10 的幂除以 10 并重复直到 10 的幂为零.
现在只需编写代码。让我们在编写每个步骤之前确定一些我们需要的变量名称(在我们完成这些步骤时作为指南提供服务器)。在具有 8-byte 的 64 位计算机上long
,选择long
保存用户输入的数字的类型对于处理负值是有意义的。我们将添加更多以帮助其余代码。五个变量应该做到这一点,例如
#include <stdio.h>
int main (void) {
int ndigits, sign = 0; /* number of digits, sign (1 if negative) */
long num /* the number to get from user */
unsigned long limit = 1, n; /* divisor limit, working var for num */
让我们从第 1 步开始。 - 提示输入。不需要转换,如果我们希望输入位于行尾而不是行尾,这fputs
是提示的不错选择(puts
如果要输出换行符强制用户输入到下一行,请使用) ,例如
fputs ("enter number in range of long int: ", stdout);
第 2 步 - 读取并验证用户输入(每个用户输入)并在提供无效输入时处理错误(如果输入无效整数,我们只需退出)return 1;
:main()
if (scanf ("%ld", &num) != 1) { /* validate input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
第 3 步 - 如果用户输入0
没有任何内容可添加的地方来获取您的最终号码,则处理这种情况:
if (!num) { /* handle 0 corner-case */
printf ("%ld : ()\n", num);
return 0;
}
(我们还将输出用户此时输入的数字,并在循环中和循环之后输出余数。调用此步骤 3a。)
printf ("%ld : ", num); /* output orignal number */
步骤 4. 确定该数字是否为负数,如果是,则使其为正数并保存一个标志,表明原始输入为负数。(在这种情况下,您可以只输出'-'
并取消该标志,但您不会总是有这样的机会——因此,如果需要,请习惯于使用简单的标志来保存状态)
if (num < 0) { /* if negative set sign=1, make positive */
sign = 1;
num = -num;
}
n = num; /* set working variable for num */
(注意:此时我们还设置了我们的工作变量n = num;
。如果您不想保留原始变量,则可以不使用工作变量,只需根据需要修改原始变量——就像我们在这里一样,因为我们已经输出了原本的)
步骤 5. - 确定用户输入的数字中的位数:
ndigits = snprintf (NULL, 0, "%ld", num); /* get number of digits in num */
(是的:snprintf
目的地NULL
和长度0
提供了一种非常方便的方法来计算将数字转换为字符串所需的字符数)
第 6 步 - 为输入的位数生成 10 的幂:
for (int i = 1; i < ndigits; i++) /* set power of 10 limit */
limit *= 10;
(在进入我们的循环之前,我们检查原始数字是否为负,此时输出'-'
- 步骤 6a。):
if (sign) /* if negative, output '-' */
putchar ('-');
步骤 7. 循环除以limit
10 的幂的数字,并输出 10 的结果分量幂(如果非零),您将添加它以得出最终数字。然后,我们将工作变量减少该数量并将 10 的幂(除以 10)并重复直到 10 的幂为零,您可以执行以下操作:
while (limit) { /* loop over each power of 10 */
int digit = n / limit; /* is there a digit at that power of 10? */
if (digit) { /* if so, output digit * power of 10 */
printf (n != (unsigned long)num ? " + %lu" : "(%lu", digit * limit);
}
n -= digit * limit; /* subtract digit * power of 10 */
limit /= 10; /* reduce limit by power of 10 */
}
剩下的就是以您喜欢的任何方式整理输出。我们将添加一个右括号,以使其看起来不错。这也是你想知道在程序期间你想把剩下的输出放在哪里(是什么导致了所有 3a. 和 6a. 步骤等)
puts (")"); /* output closing paren */
}
如果您收集所有碎片并将它们放在一起,您将拥有:
#include <stdio.h>
int main (void) {
int ndigits, sign = 0; /* number of digits, sign (1 if negative) */
long num /* the number to get from user */
unsigned long limit = 1, n; /* divisor limit, working var for num */
fputs ("enter number in range of long int: ", stdout);
if (scanf ("%ld", &num) != 1) { /* validate input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
if (!num) { /* handle 0 corner-case */
printf ("%ld : ()\n", num);
return 0;
}
printf ("%ld : ", num); /* output orignal number */
if (num < 0) { /* if negative set sign=1, make positive */
sign = 1;
num = -num;
}
n = num; /* set working variable for num */
ndigits = snprintf (NULL, 0, "%ld", num); /* get number of digits in num */
for (int i = 1; i < ndigits; i++) /* set power of 10 limit */
limit *= 10;
if (sign) /* if negative, output '-' */
putchar ('-');
while (limit) { /* loop over each power of 10 */
int digit = n / limit; /* is there a digit at that power of 10? */
if (digit) { /* if so, output digit * power of 10 */
printf (n != (unsigned long)num ? " + %lu" : "(%lu", digit * limit);
}
n -= digit * limit; /* subtract digit * power of 10 */
limit /= 10; /* reduce limit by power of 10 */
}
puts (")"); /* output closing paren */
}
示例使用/输出
现在运行它并确保它符合您的预期,如果没有 - 去修复它。
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 23401
23401 : (20000 + 3000 + 400 + 1)
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 20431
20431 : (20000 + 400 + 30 + 1)
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 1
1 : (1)
处理零:
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: 0
0 : ()
处理负值:
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: -1
-1 : -(1)
$ ./bin/pwrsof10sum_scanf
enter number in range of long int: -29031
-29031 : -(20000 + 9000 + 30 + 1)
笔记。无需使用 提示用户输入scanf
,您只需num
在代码中设置一个默认值,然后提供您想要测试的任何数字作为程序的第一个参数。这避免了测试阶段的所有提示和输入。如果您想尝试一下,只需将您的scanf
条目替换为检查是否在命令行上提供了参数,如果是,则转换并分配给num
using sscanf
,例如
#include <stdio.h>
int main (int argc, char **argv) {
int ndigits, sign = 0; /* number of digits, sign (1 if negative) */
long num = 23401; /* the number */
unsigned long limit = 1, n; /* divisor limit, working var for num */
/* check if new mumber provided on command line, convert to long */
if (argc > 1 && sscanf (argv[1], "%ld", &num) != 1) {
fputs ("error: invalid non-integer argument.\n", stderr);
return 1;
}
(唯一的变化是默认值num
,然后检查argc
和转换以及 VALIDATION with sscanf
。
如果您还有其他问题,请仔细查看并告诉我。
推荐阅读
- powershell - PowerShell 文件监控和文本转语音
- mysql - 如果存在 mysql 小时功能,如何获得半小时
- pdf - 支持在背面 V2 生成的 pdf 中搜索
- javascript - 在 Winwheel.js 中旋转之前设置要赢得的奖品
- javascript - 为什么 DOM 方法的行为在 React 中呈现元素的函数中是不确定的?
- machine-learning - 心电图信号上的 Keras Conv1D
- couchbase - 在单节点集群上启用 fts/n1ql 而无需添加额外的节点
- ios - IOS 上的 Firebase TestLab - 上传无效
- android - 如何在Sqlite android中使用算术表达式更新一行
- php - Migration from mcrypt_encrypt() to openssl_encrypt()