刚刚开始并完成 cs50。我想要:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long n = 0;
n = get_long("Number: ");
int i = 0;
long cn = n;
while (cn > 0)
{
cn = cn / 10;
i++;
}
if (i != 13 && i != 15 && i != 16)
{
printf("INVALID\n");
}
}
这让我完成了步骤 1-3,但我不知道如何让步骤 4 发挥作用。非常感谢任何帮助。
OP:“我不知道如何让步骤 4 [重复] 工作”
A:只需将要重复的代码包裹在
for()
、while()
或do/while()
循环中即可。也许您错过了课程材料的一部分,因为循环是几乎每个 C 程序中使用的语言的一部分。
做出假设时必须小心。前导数字可能为 0,并且数字值可能无法反映输入的内容。
#include <stdio.h>
#include <ctype.h> // for C library function 'isdigit()'
#include "cs50.h"
int main( void ) {
for( ;; ) { // infinite loop to avoid tedium
char *ps = get_string( "Enter a number: " );
int cnt = 0;
while( isdigit( (unsigned char)*ps ) ) {
ps++;
cnt++;
}
// positive logic may be easier for some readers
// MUST also test that user's string entry has been exhausted
if( *ps == '\0' && ( cnt == 13 || cnt == 15 || cnt == 16 ) )
; // all good
else
printf( "INVALID\n" );
}
return 0;
}
输出:
Enter a number: 1234567890123
Enter a number: 123456789012345
Enter a number: 1234567890123456
Enter a number: 12345678901234567
INVALID
Enter a number: 0000000000000
Enter a number: 0001112223334
Enter a number:
使用“辅助功能”
指示如何继续处理有效数字字符串的替代版本。
#include <stdio.h>
#include <ctype.h> // for library function 'isdigit()'
#include "cs50.h"
int isValidLen( char *ps ) { // return 0 for bad, 1 for good
// THIS 'ps' is a local copy.
// Same value, but not the same variable as in main().
int cnt = 0;
while( isdigit( (unsigned char)*ps ) ) {
ps++;
cnt++;
}
return *ps == '\0' && ( cnt == 13 || cnt == 15 || cnt == 16 );
}
int main( void ) {
for( ;; ) {// infinite loop to avoid tedium
char *ps = get_string( "Enter a number: " );
if( !isValidLen( ps ) ) {
printf( "INVALID\n" );
continue; // or something else???
}
// main()'s copy of 'ps' still points to start of the string
/*
* perhaps more processing with validated string
*/
}
return 0;
}
探索 C 的(可靠)标准库函数
或者,可以使用标准 C 库函数......
#include <stdio.h>
#include <string.h> // for library function 'strspn()'
#include "cs50.h"
int main( void ) {
for( ;; ) { // infinite loop to avoid tedium
char *ps = get_string( "Enter a number: " );
int cnt = strspn( ps, "0123456789" );
if( ps[ cnt ] == '\0' && ( cnt == 13 || cnt == 15 || cnt == 16 ) )
; // all good
else
printf( "INVALID\n" );
}
return 0;
}
知道(现在)此 CS50 作业仅涉及 3 个品牌的信用卡,并且这些品牌的 numbers 都不以
'0'
开头,使用提供的库的 get_long()
是合理的,但前提是数据是存储在 long long
变量中:
long long ccn = get_long( "Enter a number: " );
// Use a copy to "erase" digits from right-to-left until nothing remains
int cnt = 0;
for( long long cpy = ccn; cpy; cpy /= 10 )
cnt++;
if( cnt == 13 || cnt == 15 || cnt == 16 )
; // all good
else
printf( "INVALID\n" );
留给初学者的练习:
get_long()
是否返回负 数字?如果是这样,程序应该检测并拒绝它们吗?octal
或 hexadecimal
表示法输入的数字。 CS50 get_long()
只接受 decimal
数字吗?decimal
值(例如:char
、short
、int
...都作为 signed
和 unsigned
值.) 提示:某些编译器仅将 long
视为 32 位。它们的 unsigned long
的最大值刚刚超过 40 亿(即不足以存储 13、15 或 16 位十进制数字。)更简单,连续循环并使用
snprintf (NULL, 0, ...)
技巧来确定位数。仅当位数正确时才中断。
来自
man 3 snprintf
函数
和snprintf()
写的不超过 size 字节(包括终止空字节 (vsnprintf()
))。如果 由于此限制,输出被截断,则返回值为 字符数(不包括终止空字节) 如果有足够的空间,就会被写入最终的字符串 可用。'\0'
#include <cs50.h>
#include <stdio.h>
int main(void) {
long n = 0;
for (;;) { /* loop continually */
int ndigits = 0;
n = get_long("Number: ");
ndigits = snprintf (NULL, 0, "%ld", n);
if (n < 0) { /* subtract 1 for '-' sign */
ndigits -= 1;
}
if (ndigits == 13 || ndigits == 15 || ndigits == 16) {
break; /* break loop only if ndigits correct */
}
puts ("INVALID");
}
}
(注意:从技术上讲,
'-'
不是数字,因此您需要考虑负值)
示例使用/输出
./bin/ndigitstest
Number: 1
INVALID
Number: 123456789012
INVALID
Number: 1234567890123
或者,具有负值,
$ ./bin/ndigitstest
Number: -123456789012
INVALID
Number: -1234567890123
等等...
最简单的方法是给出一个标志来检查输入是否无效。例如,
int invalid = 1;
long n = 0;
while (invalid) {
n = get_long("Number: ");
int i = 0;
long cn = n;
while (cn > 0)
{
cn = cn / 10;
i++;
}
if (i != 13 && i != 15 && i != 16)
{
printf("INVALID\n");
} else {
invalid = 0;
}
}
将特定部分放入 while(1) 循环中。所以这是解决方案:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long n = 0;
int i = 0;
long cn;
while(1)
{
i=0;
n = get_long("Number: ");
cn = n;
while (cn > 0)
{
cn = cn / 10;
i++;
}
if (i != 13 && i != 15 && i != 16)
{
printf("INVALID\n");
}
else{
break;
}
}
}