简体   繁体   English

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

[英]Increment numbers in char array separated by different delimiters

I have string like this 1-2,4^,14-56 我有这样的字符串1-2,4 ^,14-56
I am expecting output 2-3,5^,15-57 我期望输出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, "-,^");
}

After running through this if I print input it prints only 2 which is first character of the updated string. 在运行此命令后,如果我打印输入,它将仅打印2,这是更新字符串的第一个字符。 It does not print all characters in the string. 它不会打印字符串中的所有字符。 What is the problem with my code? 我的代码有什么问题?

There are two major problems with this code: First of all, 此代码有两个主要问题:首先,

pch = strtok(input, ",");

When applied to the string 1-2,4^,14-56 will return the token 1-2 . 当应用于字符串1-2,4^,14-56将返回令牌1-2

When you call atoi("1-2") you'll get 1 , which gets converted to 2 . 当您调用atoi("1-2")您将获得1 ,它将转换为2

You can fix this by changing the first strtok to pch = strtok(NULL, "-,^"); 您可以通过将第一个strtok更改为pch = strtok(NULL, "-,^");来解决此问题pch = strtok(NULL, "-,^");

Second of all, strtok modifies the string, which means that you lose the original delimiter found. 其次,strtok修改字符串,这意味着您丢失了找到的原始定界符。 As this looks like a homework exercise, I'll leave you to figure out how to get around this. 因为这看起来像是一项家庭作业,所以我将让您了解如何解决此问题。

For plain C, use the library function strtod . 对于纯C语言,请使用库函数strtod Other than atoi , this can update a pointer to the next unparsed character: 除了atoi ,这可以将指针更新为下一个未解析的字符:

long strtol (const char *restrict str , char **restrict endptr , int base ); strtol (const char * restrict str ,char ** restrict endptr ,int base );
... ...
The strtol() function converts the string in str to a long value. strtol()函数将str中的字符串转换为长值。 [...] If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr . [...]如果endptr不为NULL,则strtol()将第一个无效字符的地址存储在* endptr中

Since there may be more than one 'not-a-digit' character between the numbers, skip them with the library function isdigit . 由于数字之间可能有多个“非数字”字符,请使用库函数isdigit跳过它们。 I placed this at the start of the loop so it would not accidentally convert a string such as -2,3 to -1,4 -- the initial -2 would be picked up first! 我将其放置在循环的开头,这样它就不会意外地将诸如-2,3的字符串转换为-1,4 -最初的-2将首先被拾取! (And if that is a problem elsewhere, there is also a strtoul .) (如果这在其他地方是一个问题,那么也有一个strtoul 。)

Since it appears you want the result in a char string, I use sprintf to copy the output into a buffer, which must be large enough for your possible input plus extra characters caused by a decimal overflow. 由于似乎需要将结果保存在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 ("%s\n", 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 ("%s\n", dest);

    return EXIT_SUCCESS;
}

Sample run: 样品运行:

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

strtok modifies the string you pass to it. strtok修改传递给它的字符串。 Either use strchr or something like that to find the delimiters or make a copy of the string to work on. 使用strchr或类似的东西来查找定界符或复制要处理的字符串。

I think this could by easier using regular expressions(and C++ instead of C of course): 我认为可以通过使用正则表达式(和C ++而不是C)更轻松地实现:

Complete exmaple: 完整示例:

#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;
}

Output: 输出:

2-3,5^,15-57

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM