找到你要的答案

Q:Extract integers from a string in C

Q:提取字符串中的整数

I'm trying to extract all numbers from a string add 56 89 29. There is something wrong with my code which I'm not able to figure out. The output looks like this:

Current no: 56
Current no: 89
Current no: 9
Current no: 29
Current no: 9
Current no: 9
Current no: 0
Current no: 0

where as, I would expect this:

Current no: 56
Current no: 89
Current no: 29
Current no: 29
Current no: 29
Current no: 29

There are better ways to do it but I want to know what is wrong with this implementation.

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

int main(int argc, char * argv[]){
    char temp[100];
    char op[3];
    char *buf = "add 56 89 29";
    int offset = 0;
    int rcount = 0;
    int lastno = -999;
    int currno;
    bzero(&temp, sizeof(temp));
    sscanf(buf, "%s", op);  // Get the operator (add)
    if(!strcmp(op, "add")){
        while(1){
            sscanf(buf + offset + 4, "%s", temp);  // strlen("add ") == 4
            currno = atoi(temp);
            offset += strlen(temp);
            if(currno == lastno){
                rcount++;
                // Repeating numbers means string finished
                if(rcount == 3){
                    break;
                }
            }
            printf("Current no: %d\tOffset: %d\n", currno, offset + 4);
            lastno = currno;
        }
    }
    return 0;
}

Thanks in advance!

I'm trying to extract all numbers from a string add 56 89 29. There is something wrong with my code which I'm not able to figure out. The output looks like this:

Current no: 56
Current no: 89
Current no: 9
Current no: 29
Current no: 9
Current no: 9
Current no: 0
Current no: 0

在哪里,我希望这:

Current no: 56
Current no: 89
Current no: 29
Current no: 29
Current no: 29
Current no: 29

There are better ways to do it but I want to know what is wrong with this implementation.

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

int main(int argc, char * argv[]){
    char temp[100];
    char op[3];
    char *buf = "add 56 89 29";
    int offset = 0;
    int rcount = 0;
    int lastno = -999;
    int currno;
    bzero(&temp, sizeof(temp));
    sscanf(buf, "%s", op);  // Get the operator (add)
    if(!strcmp(op, "add")){
        while(1){
            sscanf(buf + offset + 4, "%s", temp);  // strlen("add ") == 4
            currno = atoi(temp);
            offset += strlen(temp);
            if(currno == lastno){
                rcount++;
                // Repeating numbers means string finished
                if(rcount == 3){
                    break;
                }
            }
            printf("Current no: %d\tOffset: %d\n", currno, offset + 4);
            lastno = currno;
        }
    }
    return 0;
}

先谢谢了。

answer1: 回答1:

The "%n" specifier will record the number of characters used by a scan. The result can be added to the offset to advance through the string.

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

int main(int argc, char * argv[]){
    char temp[100];
    char op[4];
    char *buf = "add 56 89 29";
    int offset = 0;
    int used = 0;
    int rcount = 0;
    int lastno = -999;
    int currno;
    bzero(&temp, sizeof(temp));
    sscanf(buf, "%3s%n", op, &used);  // Get the operator (add)
    offset += used;
    if(!strcmp(op, "add")){
        while( ( sscanf(buf + offset, "%99s%n", temp, &used)) == 1) {
            currno = atoi(temp);
            offset += used;
            printf("Current no: %d\tOffset: %d\n", currno, offset);
            lastno = currno;
        }
    }
    return 0;
}

“%”说明符将记录数量的字符由一个扫描。结果可以通过字符串添加到偏移量。

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

int main(int argc, char * argv[]){
    char temp[100];
    char op[4];
    char *buf = "add 56 89 29";
    int offset = 0;
    int used = 0;
    int rcount = 0;
    int lastno = -999;
    int currno;
    bzero(&temp, sizeof(temp));
    sscanf(buf, "%3s%n", op, &used);  // Get the operator (add)
    offset += used;
    if(!strcmp(op, "add")){
        while( ( sscanf(buf + offset, "%99s%n", temp, &used)) == 1) {
            currno = atoi(temp);
            offset += used;
            printf("Current no: %d\tOffset: %d\n", currno, offset);
            lastno = currno;
        }
    }
    return 0;
}
answer2: 回答2:

There are a few things I can see that would cause your program to fail

  1. It's unecessary to write a loop like while (1) and then check for the variable inside the loop to break, because there is do {} while ();, this makes the code hard to understand.

  2. This initialization bzero(&temp, sizeof(temp)); is wrong, unecessary, and inefficient. And also, bzero() is deprecated use memset().

  3. You have a very important mistake in scanf("%s", op); you allocate space for 3 characters and type add which requires 3 + 1 for the nul terminator. The correct way to do it would be

    char op[4];
    if (sscanf(buf, "%3s", op) != 1)
     {
        fprintf("unexpected problem while reading the operator.\n");
        return -1;
     }
    
  4. sscanf(buf + offset + 4, "%s", temp) is very dangerous too, because you could easily overflow buf or temp, and besides it's much more readable like this

    sscanf(&buf[offset + 4], "%s", temp)
    

This implementation would work better

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

int main(int argc, char * argv[])
{
    char        op[4];
    const char *buffer;
    int         count;
    int         last;
    int         length;
    int         offset;
    const char *pointer;

    buffer = "add 56 89 29";
    if (sscanf(buffer, "%3s%n", op, &length) != 1)
     {
        fprintf(stderr, "unexpected problem while reading the operator.\n");
        return -1;
     }
    pointer = &buffer[length];
    if (strcmp(op, "add") != 0)
     {
        fprintf(stderr, "sorry, I can't understand this operator `%s'.\n", op);
        return -1;
     }

    count  = 0;
    last   = -999;
    offset = length;
    do {
        int number;
        int length;

        if (sscanf(pointer, "%d%n", &number, &length) != 1)
         {
            fprintf(stderr, "input format error, exiting.\n");
            return -1;
         }
        pointer += length;
        if (number == last)
            ++count;
        printf("Current no: %d\tOffset: %d\n", number, offset);

        last    = number;
        offset += length;
    } while ((count < 3) && (*pointer != '\0'));

    return 0;
}

read about the scanf() "%n" specifier.

You can also use strtol() like this

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

int main(int argc, char * argv[])
{
    char  op[4];
    char  buffer[] = "add 56 89 29";
    int   count;
    int   last;
    int   length;
    int   offset;
    char *pointer;

    if (sscanf(buffer, "%3s%n", op, &length) != 1)
     {
        fprintf(stderr, "unexpected problem while reading the operator.\n");
        return -1;
     }
    pointer = &buffer[length];
    if (strcmp(op, "add") != 0)
     {
        fprintf(stderr, "sorry, I can't understand this operator `%s'.\n", op);
        return -1;
     }

    count  = 0;
    last   = -999;
    offset = length;
    do {
        int   number;
        char *previous;

        previous = pointer;
        number   = strtol(pointer, &pointer, 10);
        if (number == last)
            ++count;
        printf("Current no: %d\tOffset: %d\n", number, offset);
        last    = number;
        offset += pointer - previous;
    } while ((count < 3) && (*pointer != '\0'));

    return 0;
}

有一些事情我可以看到,会导致您的程序失败

  1. 写一个循环而这是不必要的(1),然后检查该变量在循环打破,因为没有做而(){ };,这使代码难以理解。

  2. 这个初始化bzero(&;温度,sizeof(临时));是错误的,不必要的,效率低下。同时,bzero()是不推荐使用memset()。

  3. 你有一个很重要的错误scanf(“%s”,OP);你分配空间3字符类型添加需要3 + 1的空结束符。正确的方法是

    char op[4];
    if (sscanf(buf, "%3s", op) != 1)
     {
        fprintf("unexpected problem while reading the operator.\n");
        return -1;
     }
    
  4. sscanf(BUF +偏移量+ 4,“%s”,温度)是非常危险的,因为你可以很容易地溢出缓冲区或温度,而且它更可读的这样

    sscanf(&buf[offset + 4], "%s", temp)
    

这个实现会更好

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

int main(int argc, char * argv[])
{
    char        op[4];
    const char *buffer;
    int         count;
    int         last;
    int         length;
    int         offset;
    const char *pointer;

    buffer = "add 56 89 29";
    if (sscanf(buffer, "%3s%n", op, &length) != 1)
     {
        fprintf(stderr, "unexpected problem while reading the operator.\n");
        return -1;
     }
    pointer = &buffer[length];
    if (strcmp(op, "add") != 0)
     {
        fprintf(stderr, "sorry, I can't understand this operator `%s'.\n", op);
        return -1;
     }

    count  = 0;
    last   = -999;
    offset = length;
    do {
        int number;
        int length;

        if (sscanf(pointer, "%d%n", &number, &length) != 1)
         {
            fprintf(stderr, "input format error, exiting.\n");
            return -1;
         }
        pointer += length;
        if (number == last)
            ++count;
        printf("Current no: %d\tOffset: %d\n", number, offset);

        last    = number;
        offset += length;
    } while ((count < 3) && (*pointer != '\0'));

    return 0;
}

阅读关于scanf()“%n”说明符。

你也可以用这样的strtol()

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

int main(int argc, char * argv[])
{
    char  op[4];
    char  buffer[] = "add 56 89 29";
    int   count;
    int   last;
    int   length;
    int   offset;
    char *pointer;

    if (sscanf(buffer, "%3s%n", op, &length) != 1)
     {
        fprintf(stderr, "unexpected problem while reading the operator.\n");
        return -1;
     }
    pointer = &buffer[length];
    if (strcmp(op, "add") != 0)
     {
        fprintf(stderr, "sorry, I can't understand this operator `%s'.\n", op);
        return -1;
     }

    count  = 0;
    last   = -999;
    offset = length;
    do {
        int   number;
        char *previous;

        previous = pointer;
        number   = strtol(pointer, &pointer, 10);
        if (number == last)
            ++count;
        printf("Current no: %d\tOffset: %d\n", number, offset);
        last    = number;
        offset += pointer - previous;
    } while ((count < 3) && (*pointer != '\0'));

    return 0;
}
answer3: 回答3:

Hi I tried your code and the following worked for me. I am not a hardcore C programmer so please forgive me if I am used any non standard C functions here and but I love to work in C.

int main(int argc, const char * argv[])
{
  char *buf = "add 56 89 29";
  int sum = 0;

  if(!strncmp(buf, "add", 3))
  {
    buf += 3;

    while(*buf != '\0')
    {
        if(isdigit(*buf) == 0)
        {
            ++buf;
            continue;
        }

        int digit;
        int num = 0;

        while(isdigit(*buf))
        {
            digit = (int)*buf - 48;
            num = (num * 10) + digit;
            ++buf;
        }

        sum += num;
        printf("Current no: %d\t Sum: %d\n", num, sum);
      }
   }

   return 0;
 }

嗨,我尝试了你的代码和以下为我工作。我不是一个铁杆C程序员,所以请原谅我,如果我使用任何非标准C功能在这里,但我喜欢在C.工作

int main(int argc, const char * argv[])
{
  char *buf = "add 56 89 29";
  int sum = 0;

  if(!strncmp(buf, "add", 3))
  {
    buf += 3;

    while(*buf != '\0')
    {
        if(isdigit(*buf) == 0)
        {
            ++buf;
            continue;
        }

        int digit;
        int num = 0;

        while(isdigit(*buf))
        {
            digit = (int)*buf - 48;
            num = (num * 10) + digit;
            ++buf;
        }

        sum += num;
        printf("Current no: %d\t Sum: %d\n", num, sum);
      }
   }

   return 0;
 }
answer4: 回答4:

A much better and convenient way of doing this is with strtok which you can use to get tokens one after the other.

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

int main(int argc, char * argv[]){
    char *buf = "add 56 89 29";
    char *token;
    int count = 0;

    token = strtok(buf, " ");
    while(token != NULL){
        count++;
        if(count == 1)
            continue;
        printf("%s\n", token)
        token = strtok(NULL, " ");
    }
}

一个更加方便的方式做这是strtok时你可以用它获得令牌一前一后。

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

int main(int argc, char * argv[]){
    char *buf = "add 56 89 29";
    char *token;
    int count = 0;

    token = strtok(buf, " ");
    while(token != NULL){
        count++;
        if(count == 1)
            continue;
        printf("%s\n", token)
        token = strtok(NULL, " ");
    }
}
c  string