如何从字符串中提取数字?

3

我希望从一个字符串中提取出数字,并将它们放入一个数组中。

例如,字符串是"fds34 21k34 k25j 6 10j340ii0i5"

我想创建一个数组,其元素如下:

arr[0]=34, arr[1]=21, arr[2]=34, arr[3]=25, arr[4]=6, arr[5]=10, arr[6]=340, arr[7]=0, arr[8]=5;

我的试用代码:

#include <stdio.h>
int main()
{
    char ch;
    int i, j;
    int pr[100];
    i=0;
    while ( (ch = getchar()) != '\n' ){
        if( ch>='0' && ch<='9' ){
            pr[i] = ch-'0';
            i++;
    }
    for(j=0; j<i; j++)
        printf("pr[%d]: %d\n", j, pr[j]);
    return 0;
}

我的代码无法识别连续数。只有 'pr' 数组包含 {3, 4, 2, 1, 3, 4, 2, 5, 6, 1, 0, 3, 4, 0, 0, 5}。有没有方法来实现我的目标?


你能展示一下你的代码吗? - Cherubim
实际上,我没有我的代码。我只是想知道如何在字符串中仅查找数字。然后,我试图编写一些代码来提取字符串中的数字。但是我没能成功。但是我会编辑代码的那部分,请稍等。 - Danny_Kim
你应该将问题分为两个部分:(1)在字符串中找到一系列数字的起始和结束位置(或长度);(2)将给定范围内的字符数字转换为一个单独的数字。 - grek40
一个字符串是运行时输入。 - Danny_Kim
2
你想如何处理 '-''+'?这些字符应该作为_数字_的一部分允许吗?还是你只对十个数字感兴趣? - chux - Reinstate Monica
显示剩余2条评论
4个回答

2

这是一个算法:

  • 使用一个字符串来存储当前的数字。一开始,将其初始化为空字符串。
  • 当ch是数字('0'..'9')时,将其放入该字符串中。
  • 当ch不是数字时,如果字符串不为空,则通过atoi函数将当前字符串转换为数字,并将该数字存储在数组中。之后,再次将当前字符串初始化为空。

例如:我有字符串"ab34 56d1"

  • 使用字符串str来存储当前数字,一开始str=""(空)
  • ch='a',不进行任何操作(因为当前字符串为空)
  • ch='b',不进行任何操作
  • ch='3',将其放入字符串中,所以str="3"
  • ch='4',将其放入字符串中,现在str="34"
  • ch=' ',将"34"转换为34,保存到数组中,再次初始化str=""
  • .....

为什么我想不出这个算法呢?当我阅读一些编写代码的方法时,认为它并不难。但是当我尝试编写一个算法时,它变得非常困难...非常感谢您。我将尝试使用此算法编写代码。 - Danny_Kim
我已经更新了我的答案。我认为它很容易理解和开发。尝试编写代码,如果遇到问题,请问我。 - Viet
谢谢您的友善回答。 - Danny_Kim

2
创建一个状态机。
记录前一个字符 - 它是数字吗?
当检测到数字时...
... 如果继续数字序列,*10 并相加
... 否则开始新的序列
不要过度填充 pr[] 使用 int ch 来正确检测 EOF
//char ch;
int ch;
bool previous_digit = false;
int pr[100];
int i = 0 - 1;
while (i < 100 && (ch = getchar()) != '\n' && ch != EOF) {
  if (ch>='0' && ch<='9') {
    if (previous_digit) {
      pr[i] = pr[i] * 10 + ch - '0';
    } else {
      i++;
      pr[i] = ch - '0';
    }
    previous_digit = true;
  } else {
    previous_digit = false;
  }
}
i++;

1

这里有一段可用的代码。我尝试了3-4次,它可以正常工作。 chPrevious将保存ch的先前状态。没有必要将数字存储到数字字符串中。我们可以简单地使用一个整数来实现这个目的。

#include<stdio.h>
#define NONDIGIT 'a'

int main() {
    char ch, chPrevious; //chPrevious hold the previous state of ch.
    chPrevious = NONDIGIT;
    int temp = 0;
    int pr[100];
    int i = 0;
    while ( (ch = getchar()) != '\n' ){
    if( (ch>='0' && ch<='9') && (chPrevious>='0' && chPrevious<= '9')){
        temp = temp * 10 + (ch - '0');
    } else if (ch>= '0' && ch<= '9' && temp != 0) {
        pr[i++] = temp;
        temp = 0;
        temp = ch - '0';
    } else if (ch >= '0' && ch <= '9') {
        temp = ch-'0';
    }
    chPrevious = ch;
    }
    pr[i++] = temp;
     for(int j=0; j<i; j++)
        printf("pr[%d]: %d\n", j, pr[j]);
    return 0;
}

可能有其他更有效的方法来完成这个任务。请忽略不良的样式。您也应该改进这段代码。


使用<ctypes.h>中的isdigit()函数是有优点的。 - Jonathan Leffler
1
输入 "0 1 2\n" --> pr[0]: 1 pr[1]: 2。缺少第一个数字。 - chux - Reinstate Monica
@chux 是的,你说得对。我发现你的更有效率,所以给了赞。我还在学习阶段。 - Hemant Parihar
顺便说一句,在发布之前没有看到你的内容。这里的特殊情况是使用 temp == 0 来表示一个新的 int,而 0 是一个有效的 int。也许可以使用 -1 作为“未使用”的值。 - chux - Reinstate Monica

1
使用scanf。当您使用标准函数而不是编写自己的算法时,生活变得更简单。
此代码使用扫描读取用户输入的一行,然后解析它。检测到的数字被放入数组中,并且搜索索引向前移动了数字的数量。
char line[100];
int p[100];
int readNums = 0;
int readDigits = 0;
int len;
int index = 0;

//get line
scanf("%99[^\n]%n",line,&len);

while( index < len ){
    if(line[index] <= '9' && line[index] >= '0'){
        if(sscanf(line + index, "%d%n", p + readNums, &readDigits) != 1)
            fprintf(stderr, "failed match!!!! D:\n");
        index += readDigits;
        readNums++;
    }
    index++;
}

//print results
printf("read %d ints\n", readNums);

for(int i = 0; i < readNums; i++)
    printf("p[%d] = %d\n", i, p[i]);

请注意,如果输入为“\n”,则 scanf("%99[^\n]%n",line,&len); 不会将任何内容读入 line,并且会使 linelen 未初始化。 - chux - Reinstate Monica
@chux 你是什么意思?scanf("%99[^\n]%n",line,&len);读取的是不包括换行符的最多99个字符。你认为它是做什么用的?你可以尝试运行一下这段代码吗? - peteey
"scanf("%99[^\n]%n",line,&len); 读取的是不包含换行符的最多99个字符。但如果第一个字符是 '\n',则该语句并不正确。如之前所述,它会执行 注释 中的操作。如果第一个字符是 '\n',那么你期望会发生什么?你试过了吗?当第一个字符是 '\n' 时,代码将产生未定义的行为。 - chux - Reinstate Monica
哪种方法更好?我不熟悉如何使用fgets()和stdin,因此选择了一种简单的解决方案,因为我认为这是一个作业问题。 - peteey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接