C 中的手动拆分函数

发布于 2024-11-07 16:49:24 字数 2136 浏览 0 评论 0原文

这段代码快把我逼疯了。目标是根据逗号拆分为 char[]。它在java中工作。但在 C 中打印出奇怪的输出。我怀疑错误出现在循环的第二次迭代中的 28 处,我试图添加 5 ,数组变成了奇怪的字符。

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

main()
{
    char asshat[] = {'4','5','5',',','7','4','7','\0'};

    int firstSize = 0;//
    int secondSize = 0;//

    //new = 4 \0 \0
    char first[] = {'0', '\0'};//
    //new = 
    char second[] = {'0', '\0'};//
    char *first_ptr = first;
    char *second_ptr = second;

    int takingFirst = 1;
    int takingSecond = 0;

    int i;
    for (i = 0; i < strlen(asshat); i++)
    {
        if (asshat[i] != ',')
        {
            if (takingFirst == 1)
            {
                first_ptr[firstSize] = asshat[i];//ERROR here when you add 5 you s**t bricks
                firstSize++;
                if (asshat[i+1] != ',')
                {
                    char new[firstSize+2];
                    int k;
                    for (k = 0; k < strlen(first_ptr); k++)
                    {
                        new[k] = first_ptr[k];
                    }
                    new[firstSize] = '0';
                    new[firstSize+1] = '\0';
                    first_ptr = new;
                }
            }
            if (takingSecond == 1)
            {
                second_ptr[secondSize] = asshat[i];
                secondSize++;
                if (asshat[i+1] != '\0')
                {
                    char new[secondSize+2];
                    int k;
                    for (k = 0; k < strlen(second_ptr); k++)
                    {
                        new[k] = second_ptr[k];
                    }
                    new[secondSize+1] = '\0';
                    second_ptr = new;
                }
            }
        }
        else
        {
            takingFirst = 0;
            takingSecond = 1;
        }
    }
    printf("%d\n",strlen(first_ptr));
    printf("%c%c%c\n",first_ptr[0],first_ptr[1],first_ptr[2]);
    printf("%s\n",first_ptr);

    printf("%d\n",strlen(second_ptr));
    printf("%c%c%c\n",second_ptr[0],second_ptr[1],second_ptr[2]);
    printf("%s\n",second_ptr);
}

This code is driving me up the wall. The goal is to split to char[] based on a comma. It works in java. But prints weird output in C. The error I suspect is at 28 on the second iteration of the loop where I tried to add 5 the array turns into weird characters.

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

main()
{
    char asshat[] = {'4','5','5',',','7','4','7','\0'};

    int firstSize = 0;//
    int secondSize = 0;//

    //new = 4 \0 \0
    char first[] = {'0', '\0'};//
    //new = 
    char second[] = {'0', '\0'};//
    char *first_ptr = first;
    char *second_ptr = second;

    int takingFirst = 1;
    int takingSecond = 0;

    int i;
    for (i = 0; i < strlen(asshat); i++)
    {
        if (asshat[i] != ',')
        {
            if (takingFirst == 1)
            {
                first_ptr[firstSize] = asshat[i];//ERROR here when you add 5 you s**t bricks
                firstSize++;
                if (asshat[i+1] != ',')
                {
                    char new[firstSize+2];
                    int k;
                    for (k = 0; k < strlen(first_ptr); k++)
                    {
                        new[k] = first_ptr[k];
                    }
                    new[firstSize] = '0';
                    new[firstSize+1] = '\0';
                    first_ptr = new;
                }
            }
            if (takingSecond == 1)
            {
                second_ptr[secondSize] = asshat[i];
                secondSize++;
                if (asshat[i+1] != '\0')
                {
                    char new[secondSize+2];
                    int k;
                    for (k = 0; k < strlen(second_ptr); k++)
                    {
                        new[k] = second_ptr[k];
                    }
                    new[secondSize+1] = '\0';
                    second_ptr = new;
                }
            }
        }
        else
        {
            takingFirst = 0;
            takingSecond = 1;
        }
    }
    printf("%d\n",strlen(first_ptr));
    printf("%c%c%c\n",first_ptr[0],first_ptr[1],first_ptr[2]);
    printf("%s\n",first_ptr);

    printf("%d\n",strlen(second_ptr));
    printf("%c%c%c\n",second_ptr[0],second_ptr[1],second_ptr[2]);
    printf("%s\n",second_ptr);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我一向站在原地 2024-11-14 16:49:24

new 声明为局部变量,并让 first_ptr 指向该局部变量的内存位置:

{
    char new[firstSize+2];
    ...  
    first_ptr = new;
}

然后局部变量超出范围,其内存将被其他变量重用变量/...在未来创建。 first_ptr 仍然指向该内存位置,但那里的数组不再存在。当尝试通过first_ptr访问数组时,任何事情都可能发生,并且您很可能会发现意外的值。

You declare new as a local variable and let first_ptr point to the memory location of that local variable:

{
    char new[firstSize+2];
    ...  
    first_ptr = new;
}

Then the local variable goes out of scope and its memory will be reused by other variables/... created in the future. first_ptr still points to that memory location, but the array that was there doesn't exist anymore. When try to access the array through first_ptr anything could happen and you most likely will find unexpected values.

许一世地老天荒 2024-11-14 16:49:24

很难阅读您的解决方案正在做什么。我尝试重新实现它以使其更简单,同时保持指针播放:

#include <stdio.h>

int 
main(int argc, char *argv[])
{   
  /* Keeping variable names consistent :) */
  char asshat[] = "456,747";
  char *first = asshat, *second = asshat, *c = asshat;

  while (*c) {
    if (*c == ',') {
      *c = '\0'; second = ++c;
    } else c++;
  }   
  printf("first: %s\nsecond: %s\n", first, second);
  return 0;
}   

这会产生:

first: 456
second: 747

It's very hard to read what your solution is doing. I tried reimplementing it to be simpler while maintaining your pointer play:

#include <stdio.h>

int 
main(int argc, char *argv[])
{   
  /* Keeping variable names consistent :) */
  char asshat[] = "456,747";
  char *first = asshat, *second = asshat, *c = asshat;

  while (*c) {
    if (*c == ',') {
      *c = '\0'; second = ++c;
    } else c++;
  }   
  printf("first: %s\nsecond: %s\n", first, second);
  return 0;
}   

This produces:

first: 456
second: 747
春庭雪 2024-11-14 16:49:24

您可以通过大约一行切片来完成:)

假设至少有一个 , ...

char asshat[] = "hello,world";
char* second = asshat;
while (*second++ != ',');
*(second - 1) = 0;

printf("first: %s; second: %s\n",asshat,second);

您可以在此基础上检查是否有逗号(如果有,它将严重崩溃)不是)。

You can do it with slicing in roughly one line :)

Assuming there is at least one , ...

char asshat[] = "hello,world";
char* second = asshat;
while (*second++ != ',');
*(second - 1) = 0;

printf("first: %s; second: %s\n",asshat,second);

You can build on that to check if there is a comma at all (it will crash horribly if there isn't).

回忆躺在深渊里 2024-11-14 16:49:24

要在 C 中拆分字符串,我建议您将艰苦的工作留给 strtok()。如果没有必要,不要重新发明轮子。

To split a string in C, I suggest you leave the hard work for strtok(). Dont re-invent the wheel if you don't have to.

月隐月明月朦胧 2024-11-14 16:49:24

我假设您正在尝试将“455”复制到第一个,并将“747”复制到第二个?如果是这样,则说明您没有为此分配足够的空间。 char first[] = {'0', '\0'} 仅分配大小为 2 的数组;您将需要 4。第二个 与此相同。

您试图通过弄清楚您在原始字符串中的位置以及是否尝试复制到first来解决同一级别的太多问题>第二 跟踪每个子字符串的长度;这会加剧你的困惑,并使问题变得比实际需要的更加困难。

首先分离关注点:您需要一个函数来查找输入中的下一个子字符串,另一个函数将该子字符串复制到其目标中。

坦率地说,分割字符串的最佳方法是使用标准库函数 strtokstrchrstrcspn 中的任何一个,并使用strcpystrncpy 将子字符串复制到目标数组。有很多很好的理由使用strtok,但它是实现您正在寻找的最简单方法之一。

以下是使用 strtok 的一般过程:

char *token = strtok(asshat, ",");  // return a pointer to the substring
                                    // before the first comma
while (token)
{
  strcpy(destination[i++], token);   // assumes destination exists and is
                                     // large enough to hold the token contents
  token = strtok(NULL, ",");         // find the next substring in the sequence;
                                     // pass NULL to indicate you're continuing
                                     // in the same string
}

正如我上面提到的,您有不想想要使用 strtok 的原因。它修改输入字符串(用 0 替换分隔符),因此您不能在字符串文字上使用它。您可能还想保留原始字符串。此外,strtok 不是可重入的,也不是线程安全的。

将其应用于您的具体情况,您可以执行以下操作:

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

int main(void)
{
  char asshat[] = "455,747";
  char first[4] = "";
  char second[4] = "";
  char *destination[] = {first, second, NULL};
  size_t i = 0;

  char *token = strtok(asshat, ",");
  while (token && destination[i])  // continue while we get a token AND
  {                                // there's a place to save it
    strcpy(destination[i++], token);
    token = strtok(NULL, ",");
  }

  printf("first = %s\n", first);
  printf("second = %s\n", second);

  return 0;
}

I assume you're trying to copy the "455" to first and the "747" to second? If so, you haven't allocated enough space for that. char first[] = {'0', '\0'} only allocates an array of size 2; you'll need 4. Same for second.

You're trying to solve too many problems at the same level by figuring out where you are in the original string and whether you're trying to copy to first or second and tracking how long each substring is; this is contributing to your confusion and making the problem harder than it needs to be.

Start by separating the concerns: you need one function to find the next substring in your input, and another to copy that substring into its destination.

Frankly, the best way to split up the string is to use any one of the standard library functions strtok, strchr, or strcspn, and use either strcpy or strncpy to copy the substring to the destination arrays. There are a lot of very good reasons not to use strtok, but it is one of the easiest methods to do what you're looking for.

Here's the general procedure for using strtok:

char *token = strtok(asshat, ",");  // return a pointer to the substring
                                    // before the first comma
while (token)
{
  strcpy(destination[i++], token);   // assumes destination exists and is
                                     // large enough to hold the token contents
  token = strtok(NULL, ",");         // find the next substring in the sequence;
                                     // pass NULL to indicate you're continuing
                                     // in the same string
}

As I mentioned above, there are reasons you don't want to use strtok. It modifies the input string (replaces the delimiter with a 0), so you can't use it on a string literal. You may also want to preserve your original string. In addition, strtok is not reentrant nor thread-safe.

Applying it to your specific case, you could do something like:

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

int main(void)
{
  char asshat[] = "455,747";
  char first[4] = "";
  char second[4] = "";
  char *destination[] = {first, second, NULL};
  size_t i = 0;

  char *token = strtok(asshat, ",");
  while (token && destination[i])  // continue while we get a token AND
  {                                // there's a place to save it
    strcpy(destination[i++], token);
    token = strtok(NULL, ",");
  }

  printf("first = %s\n", first);
  printf("second = %s\n", second);

  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文