如何在 C 中重复此操作?

问题描述 投票:0回答:4

刚刚开始并完成 cs50。我想要:

  1. 提示用户输入数字
  2. 计算该数字的位数
  3. 如果位数不等于 13、15 或 16: 打印“无效”
  4. 如果“无效”,请重复步骤 1
#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 发挥作用。非常感谢任何帮助。

c cs50
4个回答
5
投票

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" );

留给初学者的练习:

  • CS50
    get_long()
    是否返回 数字?如果是这样,程序应该检测并拒绝它们吗?
  • 某些数据输入功能接受以
    octal
    hexadecimal
    表示法输入的数字。 CS50
    get_long()
    只接受
    decimal
    数字吗?
  • 了解可以存储在 C 的不同“整数”数据类型中的(近似)最大
    decimal
    值(例如:
    char
    short
    int
    ...都作为
    signed
    unsigned
    值.) 提示:某些编译器仅将
    long
    视为 32 位。它们的
    unsigned long
    的最大值刚刚超过 40 亿(即不足以存储 13、15 或 16 位十进制数字。)

3
投票

更简单,连续循环并使用

snprintf (NULL, 0, ...)
技巧来确定位数。仅当位数正确时才中断。

来自

man 3 snprintf

函数

snprintf()
vsnprintf()
写的不超过 size 字节(包括终止空字节 (
'\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

等等...


2
投票

最简单的方法是给出一个标志来检查输入是否无效。例如,

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;
    }

}

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;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.