如何确保字符串argv[1]中的每个字符都是C中的数字

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

我在 CS50 中进行加密练习,我被卡住了 有这样的部分:“添加到 caesar.c 的 main 下面,一个名为 only_digits 的函数,它接受一个字符串作为参数,如果该字符串仅包含数字(0 到 9),则返回 true,否则返回 false。确保将函数的原型也添加到 main 之上”。

这是我的代码:

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

bool only_digits(string s);

int main(int argc, string argv[])
{
    // Make sure program was run with just one command-line argument

    argc = only_digits(argv[1]);
    if(argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    return 0;

}

// make sure that the character in argv[1] is a digit

bool only_digits(string s)
{
    // int n = strlen(s);
    for (int i = 0, n = strlen(s); i < n; i++)
    {
        if(isdigit(s[i]))
        {
            return 0;
        }
    }
    printf("Usage: ./caesar key\n");
    return 1;
}

我决定创建一个 for 循环,在其中我可以检查字符是否是数字,但我只需要检查第二个字符,而不是“凯撒”,因此,我认为我的代码失败并带有“用法” : ./凯撒钥匙 ”一直,如果我只写“./caesar” - 它会出现“分段错误(核心转储)”。显然我的代码有缺陷,但我找不到解决方案。

c cs50
2个回答
0
投票

让我们注意一些错误/误用。

  • 您可以这样做,但我不鼓励您这样做..将

    argc
    放在一边。我的意思是,不要将其重复用于其他用途。相反,创建一个专用变量..

  • 在处理输入参数之前始终检查它们的有效性。在您的情况下,当用户没有输入时,您仍然检查号码。这会使您访问无效的内存区域并可能触发分段错误。

  • 在您提供的示例代码中,

    only_digits
    返回
    0
    1
    。因此,检查
    if(argc != 2)
    总是令人满意的。

  • 你的函数

    only_digits
    应该返回一个布尔值=>要么
    true
    (或
    1
    )或
    false
    (或
    0
    )。按照惯例,在你的学习过程中,我建议你坚持
    true
    false

  • 你的函数

    only_digits
    有一个否定的逻辑。如果只有非数字,则返回 true。

生成的代码如下所示:

#include <stdio.h>
#include <ctype.h>
#include <string.h>

bool only_digits(string s);

int main(int argc, string argv[])
{
    /* Make sure there are enough arguments passed to your program. */
    if (argc < 2) {
        goto usage;
    }

    // Make sure program was run with just one command-line argument
    bool isvalid = only_digits(argv[1]);
    if(isvalid == 0) {
        goto usage;
    }

    // everything is good.
    return 0;

usage:
    printf("Usage: ./caesar key\n");
    return 1;
}

// make sure that the character in argv[1] is a digit

bool only_digits(string s)
{
    for (int i = 0; i < strlen(s); i++) {
        /* Here, we want to break the loop upon the first non-digit
         * character. Thus the negation `!` */
        if(!isdigit(s[i])) {
            return false;
        }
    }

    return true;
}

0
投票

OP 代码试图做太多事情,并且顺序混乱。例如,函数

only_digits()
的任务是测试字符串是否仅由 ASCII 数字组成,而不报告如何执行程序。

下面使用较少的代码。检查传递参数的字符(如果有)。如果有一个参数,并且有 1+ 个字符要检查,并且检查到字符串末尾,则返回值是

true
表示一切正常。

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

bool only_digits(string s);

int main(int argc, string argv[])
{
    if( only_digits( argv[1] ) == 0 )
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    /* more code here */

    return 0;
}

bool only_digits(string s)
{
    int i = 0;
    while( s && isdigit( s[i] ) )
        i++; // loop until end of string (if there is one)
    return s && i && s[i] == '\0';
}

人们想要编写简洁的代码,不给错误留下隐藏的空间。
这会“消耗”一些额外的(极其便宜的)机器周期。谁在乎?

编辑
一个鲜为人知的事实是,C 保证 argv[] 的“后最终”值为 NULL。 (即:“a.out foobar”将 argv[0] 设置为指向“a.out”,将 argv[1] 设置为指向“foobar”,并将 argv[2] 设置为 NULL。人们可以将此信息用于自己的优势。

© www.soinside.com 2019 - 2024. All rights reserved.