【问题标题】:Extract numbers from string doesnt work! c从字符串中提取数字不起作用! C
【发布时间】:2014-01-20 08:59:33
【问题描述】:

我会从 ISBN 字符串中删除“-”。 但是我的代码不会打印出我的价值。错在哪里?

char *ISBN[20];  //example: 3-423-62167-2
*p = ISBN;

strcpy(ISBN, ptr); //Copy from a Buffer
printf("\nISBN Array: %s", ISBN); //This works!

while(*p)
{
    if (isdigit(*p))
    {
        long val = strtol(p, &p, 10);
        printf("%ld\n", val);         //Do not show anything!
    }
    else
    {
        p++;
    }
}

【问题讨论】:

  • p的声明是什么?
  • char *ISBN[20]?当然?数组数组?
  • 只需char ISBN[20] 就足够了。那里有一个 C 字符串数组
  • @Adriano 不,这是一个指针数组。
  • 另外,@OP: strtol() 不会做你认为的那样。 阅读其文档。

标签: c string strtol


【解决方案1】:

怎么样:

for (char* p = ISBN; *p != '\0'; p++)
{
    if (isdigit(*p))
    {
        printf("%c", *p);
    }
}

如果您想要long:将字符保存在char[](而不是printf())中,然后在完成后将其转换为long。您甚至可以使用 ISBN 数组进行就地转换:

int i = 0;
for (char* p = ISBN; *p != '\0'; p++)
{
    if (isdigit(*p))
    {
        ISBN[i++] = *p;
    }
}

ISBN[i] = '\0';

long isbn = strtol(ISBN, NULL, 10);

顺便说一句,当is digit() 为真时,您忘记了p++

【讨论】:

    【解决方案2】:

    以下代码适用于我:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    
    char *ptr = "3-423-62167-2";
    char ISBN[20];  // should be either ISBN[] or char *ISBN for a string
    char *p = ISBN; // declared this one here.. else should be p = ISBN
    
    strcpy(ISBN, ptr);
    printf("\nISBN Array: %s\n", ISBN);
    
    while(*p)
    {
        if (isdigit(*p))
        {
            long val = strtol(p, &p, 10);
            printf("%ld\n", val);
        }
        else
        {
            p++;
        }
    }
    
    }
    

    已在 cmets 中标记更正!

    【讨论】:

    • 谢谢大家!答案都很有用!但是我如何才能长期保护新价值并使用它呢?
    • @legends2k:为什么会这样? "3-423-62167-2" 是一个以 null 结尾的字符串,因此 (*p) 是一个足够好的退出条件..
    • 这段代码会单独提取数字;如果您只想摆脱连字符并将组合数字转换为 long,那么@meaning-matters 的答案就是您想要的答案。
    • 好的,我对无限循环的看法是错误的,但是您还需要包含 ctype.hstdlib.h 。我投了你一票。
    • @legends2k:同意这一点。不过 gcc 并没有警告我。
    【解决方案3】:

    没有必要错误地使用strtol;第二个参数不是输入,而是输出,即将它设置为最后一个解释的字符。最重要的是,当您只需要一个要打印的字符时,为什么要将字符转换为 long 然后再将其转换回字符?

    char ISBN[] = "3-423-62167-2";
    char *p = ISBN;
    while (*p)
    {
        if (isdigit(*p))
            printf("%c", *p);
        ++p;
    }
    

    编辑:

    将整个字符串变成一个长字符串:

    unsigned long long num = 0;
    while (*p)
    {
        if (isdigit(*p))
        {
            const char digit = *p - '0';
            num = (num * 10) + digit;
        }
        ++p;
    }
    

    【讨论】:

    • 我需要将 ISBN 字符串转换为不带“-”的长字符串,以便在模运算中使用它。但是在你的例子中,我只打印出字符串。我该怎么做?
    • 您的意思是每个数字为long 或整个3423621672long
    • 全长:3423621672
    • 首先,使用(签名的)long 4 个字节,您最多只能表示 2147483647;使用 4 个字节的 unsigned long,您最多可以表示 4294967295。当 ISBN 号为 8-423-62167-2 时,你会怎么做?
    • @user3214376:我想说你应该使用unsigned long long,它保证至少是64位,最多可以表示18446744073709551615。使用解决方案更新了答案,但请确保您没有遇到the XY problem
    【解决方案4】:

    假设 pchar * 指针,您应该将代码更新为

    //-----v no *
      char ISBN[20];  //example: 3-423-62167-2
      p = ISBN;
    //^-- no *
    

    保持其余代码不变。

    【讨论】:

    • 另外,strtol() 并没有像 OP 认为的那样做。
    【解决方案5】:

    我认为 OP 想要的是将带有连字符的字符串转换为长整数。此函数将字符串的十进制数字转换为长整数。连字符(在任何地方)都会被忽略,其他字符,包括空格,会导致阅读错误:

    /*
     *      Return ISBN as long or -1L on format error
     */
    long isbn(const char *str)
    {
        long n = 0L;
    
        if (*str == '\0') return -1L;
    
        while (*str) {
            if (isdigit(*str)) {
                n = n * 10 + *str - '0';
            } else {
                if (*str != '-') return -1L;
            }
            str++;
        }
    
        return n;
    }
    

    请注意,long 在某些机器上与int 的大小相同,并且可能不够宽以存储数字 ISBN。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多