递增由不同分隔符分隔的字符数组中的数字

Increment numbers in char array separated by different delimiters

本文关键字:字符 数组 数字 分隔 分隔符      更新时间:2023-10-16

我有这样的字符串 1-2,4^,14-56
我期待输出 2-3,5^,15-57

char input[48];
int temp;
char *pch;
pch = strtok(input, "-,^");
while(pch != NULL)
{
    char tempch[10];
    temp = atoi(pch);
    temp++;
    itoa(temp, tempch, 10);
    memcpy(pch, tempch, strlen(tempch));
    pch = strtok(NULL, "-,^");
}

运行完此操作后,如果我打印输入,它只打印 2,这是更新字符串的第一个字符。它不会打印字符串中的所有字符。我的代码有什么问题?

对于普通 C,请使用库函数 strtod 。除了 atoi 之外,这可以更新指向下一个未解析字符的指针:

Long strtol (const char *restrict str, char **restrict endptr, int base);
...
strtol() 函数将 str 中的字符串转换为长整型值。[...]如果 endptr 不是 NULL,strtol() 将第一个无效字符的地址存储在 *endptr 中。

由于数字之间可能有多个"非数字"字符,因此请使用库函数 isdigit 跳过它们。我把它放在循环的开头,这样它就不会意外地将 -2,3 等字符串转换为 -1,4 - 初始-2将首先被拾取!(如果这是其他地方的问题,那也有一个strtoul

由于您似乎希望结果以 char 字符串形式出现,因此我使用 sprintf 将输出复制到缓冲区中,缓冲区必须足够大,以便您可能输入以及由十进制溢出引起的额外字符。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
int main (void)
{
    char *inputString = "1-2,4^,14-56";
    char *next_code_at = inputString;
    long result;
    char dest[100], *dest_ptr;
    printf ("%sn", inputString);
    dest[0] = 0;
    dest_ptr = dest;
    while (next_code_at && *next_code_at)
    {
        while (*next_code_at && !(isdigit(*next_code_at)))
        {
            dest_ptr += sprintf (dest_ptr, "%c", *next_code_at);
            next_code_at++;
        }
        if (*next_code_at)
        {
            result = strtol (next_code_at, &next_code_at, 10);
            if (errno)
            {
                perror ("strtol failed");
                return EXIT_FAILURE;
            } else
            {
                if (result < LONG_MAX)
                    dest_ptr += sprintf (dest_ptr, "%ld", result+1);
                else
                {
                    fprintf (stderr, "number too large!n");
                    return EXIT_FAILURE;
                }
            }
        }
    }
    printf ("%sn", dest);
    return EXIT_SUCCESS;
}

示例运行:

Input:  1-2,4^,14-56
Output: 2-3,5^,15-57

此代码有两个主要问题:首先

pch = strtok(input, ",");

当应用于字符串时,1-2,4^,14-56将返回令牌1-2

当您调用atoi("1-2")时,您将获得1,这将转换为2

您可以通过将第一个 strtok 更改为 pch = strtok(NULL, "-,^"); 来解决此问题

其次,strtok 修改字符串,这意味着您将丢失找到的原始分隔符。 由于这看起来像一个家庭作业练习,我将让您弄清楚如何解决这个问题。

我认为这可以通过更容易地使用正则表达式(当然还有C++而不是 C):

完整示例:

#include <iostream>
#include <iterator>
#include <regex>
#include <string>
int main()
{
    // Your test string.
    std::string input("1-2,4^,14-56");
    // Regex representing a number.
    std::regex number("\d+");
    // Iterators for traversing the test string using the number regex.
    auto ri_begin = std::sregex_iterator(input.begin(), input.end(), number);
    auto ri_end = std::sregex_iterator();

    for (auto i = ri_begin; i != ri_end; ++i)
    {
        std::smatch match = *i;                             // Match a number.
        int value = std::stoi(match.str());                 // Convert that number to integer.
        std::string replacement = std::to_string(++value);  // Increment 1 and convert to string again.
        input.replace(match.position(), match.length(), replacement); // Finally replace.
    }
    std::cout << input << std::endl;
    return 0;
}

输出:

2-3,5^,15-57

strtok修改传递给它的字符串。使用 strchr 或类似的东西来查找分隔符或制作要处理的字符串的副本。