2

我有一个 C++ 函数,它在遇到分隔符时将 char 数组拆分为多个 char 数组。出于某种原因,当保存第三个拆分数组时,程序会崩溃,有时会返回 std::bad_alloc 异常。

char ** explode(const char * arr, const char delim) {
int start, end, curr=0, count=1;
char ** strings;
//Iegūst explodēto stringu skaitu
for (int i = 0; arr[i] != 0; i++) {
    if (arr[i] == delim && i != 0 && arr[i+1] != 0 && arr[i+1] != delim ) { //Nav pirmais, nav pēdējais, nav pa labi vēlviens delimiters
        count++;
    }
}
strings = new char*[count];
start = 0;
for (int i = 0; arr[i] != 0; i++) {
    if (arr[i] == delim || arr[i+1] == 0) {
        if (arr[i] == delim) {
            end = i;
        } else {
            end = i+1;
        }
        if (end-start < 1) {
            start++;
        } else {
            copystring(arr,strings[curr++],start,end-start);
            start = i+1;
        }
    }
}
for (int i = 0; i < count; i++) {
    cout << strings[i] << endl;
}

return strings;
}

//Pārkopē daļu no pirmā char masīva uz otru, no START pozīcijas, līdz GARUMS garumā
void copystring(const char * from, char *& to, const int start, const int garums) {
    int curr=0;
    if (garums < 1 || start > charlen(from)) {
        return;
    }
    to = new char[garums];
    for (int i = start; i < start+garums && from[i] != 0; i++) {
        to[curr++] = from[i];
    }
    to[curr] = 0;
}

很难说,因为它并没有真正告诉我在哪一行出了问题,但我认为它发生在

to = new char[garums];

我已经尝试在 CodeBlocks 中调试这一行,但由于某种原因,在使用断点和跟踪变量时,应用程序可以正常工作并正确执行。它只在正常运行时崩溃,无需调试...

另请注意,除了 fstream 和 iostream,我不能使用字符串或几乎任何库。

编辑:我尝试将new char[garums]部件更改为new char[100],它神奇地开始工作。问题是我然后将其更改为new char[10]在这种情况下一切仍然有效。我什至将保存的文本输出到控制台,它正确保存了所有内容。它怎么能在一个 10 个字符长的 char 数组中保存大词(我正在测试的词长于 10 个字符)?当我将其更改为new char[1]但是它再次开始崩溃,但仅在第三次循环迭代之后再次崩溃。所以它以某种方式将前 2 个单词保存在 1 个字符长的数组中?

EDIT2:现在它甚至神奇地开始工作了new char[garums]. 这里确实有问题,有人有什么想法吗?

4

3 回答 3

0

由于我不知道您有什么输入数据,我将不得不猜测:

在这里您分配指针数组,但请注意所有指针都未初始化。

strings = new char*[count]

然后,当您解析代码时,您使用一个curr让您自由运行的变量,因此不确定所有strings[]变量是否都已设置为某个值或是否curr落在大于count.

如果我是你,我会检查以确保:

a)curr不超过count

b) 如果curr落在小于 的值上count,则将其余指针设置为nullptr

于 2014-04-27T17:22:22.520 回答
0

当您尝试使用从 explode 函数返回的指针的指针时,您在问题中提到的错误可能会突然出现。一些指针;如果您必须编写 C 代码,请不要使用 C/C++ 的混搭,使用库函数而不是重新发明轮子(复制字符串中的 strncpy)您的字数已关闭,因为您没有考虑到这个词在最后一个分隔符和 EOL 之间 以下是您的代码的一些细微更改作为完整示例:

#include <stdio.h>
#include <strings.h>

void copystring(const char *from, char **to, const int numchars)
{
    if (numchars > 0) {
            *to = new char[numchars];
            strncpy(*to, from, numchars) ;
            (*to)[numchars] = '\0' ;
    }
}

char **explode(const char * buffer, const char delim)
{
    int count = 0 ;

    if (strlen(buffer) > 0) {
            int inword = 0 ;
            int idx = 0 ;
            do {
                    if (buffer[idx] == delim || buffer[idx] == '\0') {
                            if (inword == 1) {
                                    count++ ;
                                    inword = 0 ;
                            }
                    } else {
                            inword = 1 ;
                    }
            } while (buffer[idx++] != 0) ;
    }

    int start = 0;
    int end = 0 ;
    int curr = 0 ;
    int idx = 0 ;

    char **values = new char*[count+1];

    do {
            if (buffer[idx] == delim || buffer[idx] == '\0') {
                    end = idx;
                    if (end-start > 0) {
                            copystring(&buffer[start], &values[curr++], end - start) ;
                    }
                    start = ++end ;
            }
    } while (buffer[idx++] != 0) ;

    values[curr] = NULL ;
    for (int idx = 0; idx < count; idx++) {
            fprintf(stdout, "'%s'\n", values[idx]) ;
    }

    return values;
}

int main(int argc, char *argv[])
{
    char inputstr[] = "The, quick, brown, fox, jumped, over,,, ,,, ,,,,, ,,,, the, lazy, dog's, back" ;
    char **values = explode(inputstr, ',') ;

    while (*values != NULL) {
            fprintf(stdout, "%s\n" , *values) ;
            *values++ ;
    }

    return (0) ;
}
于 2014-04-27T21:26:27.150 回答
-1

这可能与totypechar*&而不是 type 有关char*。另一方面,我从来没有像这样编写过 C++(你确定这不是 C 吗?)。使用显式内存管理(如“新”)与玩俄罗斯轮盘赌一样好。

这是一种更标准的 C++ 方法:

#include <vector>
#include <string>
#include <iostream>

std::vector<std::string> splitString(std::string& str, char c) {
  std::vector<std::string> substrings;
  while(true) {
    unsigned pos = str.find(c);
    substrings.push_back(str.substr(0,pos));
    if(pos == std::string::npos) break;
    str = str.substr(pos+1);
  }
  return substrings;
}

int main()
{
  char c = '*';
  std::string str = "Some*string*that we need to split*properly*";
  std::vector<std::string> result = splitString(str,c);

  for(unsigned i = 0; i < result.size(); ++i) {
    std::cout << i << ": " << result[i] << "\n";
  }
}

输出:

0: Some
1: string 
2: that we need to split
3: properly
4:
于 2014-04-27T15:30:54.310 回答