如何从包含字符和整数的行中解析出整数

How to parse out integers from a line with characters and integers

本文关键字:整数 包含 字符      更新时间:2023-10-16

对于C/C++赋值,我需要取一个输入行,从字符"s"开始,后跟最多3个独立的整数。我的问题是,如果没有向量,我不知道如何计算未知数量的整数(1-20)。

例如,测试输入看起来像:

s 1 12 20

有人建议我使用cin.getline,并将整行作为一个字符串,但我怎么知道每个整数在字符数组中的位置,因为可能是单位数或双位数,更不用说所述字符串中的整数数量了?

根据行的内容构造一个std::istringstream,然后继续将operator>>使用到int中,直到fail()s,将每个整数填充到std::vector中(在最初使用operator>>一次以处理前导字符之后)。

您可以使用动态内存分配来模拟向量。最初使用int *a = new int[2]; 创建一个大小为2的数组

当此数组填满时,制作一个大小为原来两倍的新数组,将旧数组复制到新数组中,并将a重新分配给新数组。继续这样做,直到达到要求为止。

编辑因此,通过字符串流获取数字,如果数组填满,可以执行以下操作:

int changeArr(int *a, int size){
    int *b = new int[size*2];
    for(int i=0;i<size;i++){
        b[i] = a[i];
    }
    a = b;
    return size*2;
}
int getNos(istringstream ss){
    int *a = new int[2];
    int cap = 2, i=0, number;
    while(ss){
        if(i>=cap){
            cap = changeArr(a, cap);
        }
        ss >> a[i];
        i++;
    }
}

我跳过了关于第一个角色的部分,但我想你可以应付。

如果没有向量,您有几种方法。(1) 一次读取整行,并strtokstrsep标记该行,或者(2)使用strtol中内置的标准功能沿字符串向下遍历,该字符串使用指向函数的指针和结束指针参数分隔值。

既然你知道格式,你可以很容易地使用任何一种。两者都是1&2做同样的事情,您只是使用strtol中的工具在一个步骤中同时将标记化转换为数字。下面是一个处理每行后面跟着未知数字的字符串的简短示例:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
enum { BASE = 10, MAXC = 512 };
long xstrtol (char *p, char **ep, int base);
int main (void) {
    char buf[MAXC] = "";
    while (fgets (buf, MAXC, stdin)) {   /* for each line of input */
        char *p, *ep;   /* declare pointers */
        p = buf;        /* reset values */
        errno = 0;
        printf ("n%sn", p); /* print the original full buffer */
        /* locate 1st digit in string */
        for (; *p && (*p < '0' || '9' < *p); p++) {}
        if (!*p) {  /* validate digit found */
            fprintf (stderr, "warning: no digits in '%s'n", buf);
            continue;
        }
        /* separate integer values */
        while (errno == 0)
        {   int idx = 0;
            long val;
            /* parse/convert each number in line into long value */
            val = xstrtol (p, &ep, BASE);
            if (val < INT_MIN || INT_MAX < val) {   /* validate int value */
                fprintf (stderr, "warning: value exceeds range of integer.n");
                continue;
            }
            printf ("  int[%2d]: %dn", idx++, (int) val);  /* output int */
            /* skip delimiters/move pointer to next digit   */
            while (*ep && *ep != '-' && (*ep < '0' || *ep > '9')) ep++;
            if (*ep)
                p = ep;
            else
                break;
        }
    }
    return 0;
}
/** a simple strtol implementation with error checking.
 *  any failed conversion will cause program exit. Adjust
 *  response to failed conversion as required.
 */
long xstrtol (char *p, char **ep, int base)
{
    errno = 0;
    long val = strtol (p, ep, base);
    /* Check for various possible errors */
    if ((errno == ERANGE && (val == LONG_MIN || val == LONG_MAX)) ||
        (errno != 0 && val == 0)) {
        perror ("strtol");
        exit (EXIT_FAILURE);
    }
    if (*ep == p) {
        fprintf (stderr, "No digits were foundn");
        exit (EXIT_FAILURE);
    }
    return val;
}

xstrtol函数只是将正常的错误检查移动到一个函数,以清理代码的主体)

示例输入

$ cat dat/varyint.txt
some string 1, 2, 3
another 4 5
one more string 6 7 8 9
finally 10

示例使用/输出

$ ./bin/strtolex <dat/varyint.txt
some string 1, 2, 3
  int[ 0]: 1
  int[ 1]: 2
  int[ 2]: 3
another 4 5
  int[ 0]: 4
  int[ 1]: 5
one more string 6 7 8 9
  int[ 0]: 6
  int[ 1]: 7
  int[ 2]: 8
  int[ 3]: 9
finally 10
  int[ 0]: 10

您可以提供一些整理,但此方法可以用于可靠地解析未知数量的值。仔细看一下,如果你有任何问题,请告诉我。

由于不允许使用向量,因此您需要先找出行中有多少数字,然后才能创建一个数组来容纳它们。

我不会只给你完整的代码,因为这是家庭作业,但我会告诉你我会做什么来解决你的问题。

如果你的台词总是这样:;s数";或";s数";或";s数";,然后你可以通过计算空格很容易地找到行中的数字!

在任何有一个数字的字符串中(在s和那个数字之间)都会有一个空格,第一个数字后面的每个数字都会多留一个空格。

所以让我们数一下空格!

int countSpaces(string s) {
    int count = 0;
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == ' ') {
            count++;
        }
    }
    return count;
}

传递这些字符串:

string test1 = "s 123 4 99999";
string test2 = "s 1";
string test3 = "s 555 1337";

countSpaces函数将给我们:

3
1
2

有了这些信息,我们可以制作一个大小正确的数组来容纳每个值!


编辑

现在我意识到你很难从字符串中提取数字。

我要做的是,使用上面的方法来找到行中的数字数量。然后,我将使用std::string.find()函数来确定字符串中的位置以及是否有空格。

假设我们有一条线路:s 123 45 678

countSpaces会告诉我们我们有3个数字。

然后我们做一个数组来容纳我们的三个数字。我也会剪掉s 的部分,这样你就不用再担心了。请注意,您可以使用std::stoi将字符串转换为数字!

现在我们可以在find(' ')不返回-1时循环。

在我们的循环中,我会将子字符串从0带到第一个空间,如下所示:

num = std::stoi( myLine.substr(0, myLine.find(' ') )

然后你可以切掉你刚刚使用的部分:

myLine = myLine.substr( myLine.find(' ') );

这将从字符串前面取下一个数字,然后从字符串中砍下该数字,并在字符串中仍有空格时重复该过程。

编辑:

如果不能保证每个数字之间有一个空格,那么可以在执行此方法之前删除多余的空格,也可以在countSpaces循环中删除。在这一点上,调用函数countNums或类似的函数会更有意义。

一个示例函数可以删除一段空间并将其替换为一个空间:

void removeExtraSpaces(string s) {
    bool inSpaces = (s[0] == ' ');
    for (int i = 1; i < s.size(); i++) {
        if (s[i] == ' ') {
            if(inSpaces) {
                s.erase(i); 
            } else { 
                inSpaces = true;
            }
        } else if(inSpaces) {
            inSpaces = false;
        }
    }
}