【问题标题】:learning C - test datatype学习 C - 测试数据类型
【发布时间】:2023-03-04 06:53:02
【问题描述】:

我正在学习 C(困难的方式)并尝试编写一个根据参数数据类型打印一行的函数(简单练习)。

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

 int main( int argc,  char *argv[] )
 {
     int i = 0;
     for(i = 0; i < argc; i++){
         if(isalpha((int)argv[i]) )  //this line produces a warning
         {
             printf("I am alpha.\n");
         }
     }

     return 0;
 }

这会在编译时产生警告(并且在执行时不执行任何操作):

cast to smaller integer type 'int' from 'char *' [-Wpointer-to-int-cast]

cmets 后更新 我正在比较梨和苹果:字符串与 int,它们的字节数不同。所以问题是:我如何编写数据比较 if 语句,就像在 ruby​​ 中一样:

a = "5"
if a.instance_of? String
# do something
end

【问题讨论】:

  • 你想isalpha((int)argv[i]) 是什么意思? argv[i] 是一个字符串,而isalphaone 字符作为参数。
  • 一个指针是 8 个字节,而一个 int 是 4 个字节。所以警告告诉你你丢失了演员表中的信息。
  • 我认为 strings 在 c 中不存在,因为它们是字母数组。
  • @thiebo,在 c 中用字符串来理解,它们是字符数组。
  • @thiebo argv[i] 总是是一个 C 风格的字符串。你不需要检查那个。 C 程序只能并且总是将命令行参数作为字符串获取

标签: c


【解决方案1】:

您似乎已经知道,C 中的“字符串”是\0 终止的字符数组。 argv 是一个指向这些数组开头的指针数组。例如,argv[0] 几乎总是可执行文件的路径。假设您以./a.out 运行该程序。 argv[0] 将如下所示:

+---+---+---+---+---+---+---+---+
| . | / | a | . | o | u | t | \0|
+---+---+---+---+---+---+---+---+
  ^argv[0] points to this character

这就解释了argv 的元素是什么。我想你明白你的程序出了什么问题。您只是想将argv[i] 持有的地址转换为int,但这本身显然也是错误的,因为在您的系统上,指针大于int,因此地址可能会被截断。据我所知,在你的程序中,你要么想要:

  1. 检查argv 的每个元素是否是一个只包含1 个字母的字符串。

  2. 检查argv 的每个元素是否是一个只有字母的字符串(例如"abcde")。


  1. argv[i][0](第一个字符)上使用isalpha,并检查字符串的长度是否只有一个字符(和一个NUL终止符):
for (int i = 0; i < argc; ++i)
{
    if (isalpha(argv[i][0]) && argv[i][1] == '\0') // if length is 1 char, \0 will be right after
        puts("I'm a character.");
}
  1. 在循环中使用isalpha 来检查每个字符是否是字母。
for (int i = 0; i < argc; ++i)
{
    _Bool isalphastr = 1;
    for (const char *j = argv[i]; *j != '\0'; ++j)
    {
        if (!isalpha(*j))
        {
            isalphastr = 0;
            break;
        }
    }
    if (isalphastr)
        puts("I'm a string of letters");
}

或者:

#include <string.h>

for (int i = 0; i < argc; ++i)
{
    if (strspn(argv[i], "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(argv[i]))
        puts("I'm a string of letters");
}

但我认为这个字符串有点太长了......

【讨论】:

    【解决方案2】:

    编写一个根据参数数据类型打印一行的函数

    这里你有一个根本的误解。 C 程序的(命令行)参数始终是 C 风格的字符串。总是...

    无法获取任何其他数据类型。因此,如果您想为程序提供另一种输入类型,例如一个数字,您需要编写将字符串转换为数字的代码。

    例子:

    ./myprogram 123
                ^^^
                Start myprogram using the NUMBER 123
    

    一旦您进入您的main,就没有号码了。相反,您会得到一个字符串,即"123"argv[1] 将指向该字符串。要获取数字,您需要如下代码:

    int number = convert_string_to_number(argv[1]);   // Convert the string "123"
                                                      // to the number 123
    

    (注意:转换功能已经可用 - 例如https://man7.org/linux/man-pages/man3/strtol.3.html

    进一步...您的标题是“测试数据类型”。在 C 中,这并不是你真正要做的事情。有关详细信息,您可能会发现这个https://stackoverflow.com/a/6280095/4386427 很有趣。

    顺便说一句:

    如果您只想打印参数,只需将它们全部打印为字符串:

    for(int i = 0; i < argc; ++i)
    {
        printf("argument %d is %s\n", i, argv[i]);
                                               
    }
    

    顺便说一句:

    对于您的警告...正如在几个 cmets 中已经提到的那样,(int)argv[i] 正在将指针值转换为整数值。语言本身并没有禁止这样做,但这是你永远不会做的事情......所以编译器会给你一个警告。有点像说“这看起来很奇怪。确定这真的是你想做的吗?”在你的情况下,答案是否定的。

    【讨论】:

      【解决方案3】:

      由于接受的答案很好地解释了一切,但您的编译器错误我想尝试提供一个适当的解释。

      argv[i]char *(又名 char 指针,又名 C 字符串),通常指针只是 size_t(具有 16 位或更多位的 无符号 整数)指定某物在 RAM 中的位置。

      int 只是一个具有 16 位或更多位的有符号整数。

      通过此代码,您可以找出您的size_tint 有多少位:

      int main ( int argc,  char *argv[] ) {
      
        printf( "Bits of `char *`: %d", sizeof(char *)*8 );
        printf( "Bits of `int`: %d",    sizeof(int)*8    );
      
        return 0;
      }
      

      假设char * 是32 位,int 是16 位:当从char * 转换为int 时,程序将“剪切”剩余的16 位。

      请注意,保留的 16 位 int 可能从末尾开始,或者构成 size_t 的 32 位的开头,具体取决于您的 CPU 字节序。

      【讨论】:

        【解决方案4】:

        您正在从指针转换为整数。相反,请尝试使用内容运算符((int)(*argv[i]))。

        【讨论】:

          猜你喜欢
          • 2019-08-24
          • 2012-11-08
          • 1970-01-01
          • 2018-06-12
          • 2020-02-21
          • 2020-05-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多