【问题标题】:Split string to 140 char chunks将字符串拆分为 140 个字符块
【发布时间】:2014-10-28 11:03:33
【问题描述】:

这是我的功能:

char** split_string(char* message){

  int i = 0;
  int j = 0;
  int numberOfMsgs = 0;
  int charsInLastMsg = (int)(strlen(message)%140);


  if((int)strlen(message) > 140*4){
    return NULL;
  }

  if((int)(strlen(message)%140)){
    numberOfMsgs = (int)(strlen(message)/140) + 1;
  }
  else{
    numberOfMsgs = (int)(strlen(message)/140);
  }

  printf("message length = %d, we will have %d messages, and last msg will have %d characters\n", (int)strlen(message), numberOfMsgs, charsInLastMsg);


  char **m = malloc(numberOfMsgs * sizeof(char*));
  for (j =0 ; j <= numberOfMsgs; j++){
    m[j] = malloc(141 * sizeof(char));
  }

  for(i=0;i<numberOfMsgs;i++){
    if(i == numberOfMsgs - 1){

      memcpy(m[i], message + (140*i), charsInLastMsg);
      m[i][charsInLastMsg] = '\0';
    }
    else{
      memcpy(m[i], message + (140*i), 140);
      m[i][140] = '\0';

    }
    printf("m%d = %s\n", i, m[i]);
  }
  return m;
}

我是这样称呼的:

char* message = "1, 2, 3, 4, 5, 6, 7, 8, 9 and 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.";

int i=0;
char** m = split_string(message);
while(*m){
  printf("string%d = %s\n", i, m[i]);       //Problem at this line.
  m++;
}

但是,当我运行它时,我在上面指示的行中遇到了分段错误。如果我不打印,程序运行良好,所以我认为函数 split_string() 是可以的。

我做错了什么?我是新手,请帮忙。

/************************************预期的 O/P****** ******************************/

我希望将字符串拆分为 140 个字符字符串,如下所示:

string0 = 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36
string1 = , 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71
string2 = , 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.

【问题讨论】:

  • 你超出了数组m..分配m[j] = malloc(140 * sizeof(char))然后尝试m[i][140] = '\0';..m0139的范围
  • 问题不在 printf 中,这是您的 split_string 函数不起作用的结果。顺便说一句,您的预期输出是什么?
  • 感谢您指出缓冲区溢出。我已经编辑了这个问题。请看一下。顺便说一句,split_string() 中的 printf 工作正常。

标签: c string segmentation-fault


【解决方案1】:

您的代码中有几个问题。你已经修复了一些。

您的客户代码

while (*m) {
    printf("string%d = %s\n", i, *m);
    i++;
    m++;
}

(我冒昧地将m[i] 替换为i 始终为0 与*m)表明字符指针数组mNULL 终止的,即NULL 指针表示字符串列表的结束。 (很像 '\0' 字符表示字符串的结尾。)

但是您的函数 split_string 没有在末尾放置 NULL 指针:您的客户端代码将读取超出有效内存。

char **m = malloc(numberOfMsgs * sizeof(char*));

在这里,您应该分配(numberOfMsgs + 1) 字符串,为NULL 额外分配一个。

for (j =0 ; j <= numberOfMsgs; j++){
    m[j] = malloc(141 * sizeof(char));
}

在这里,您应该只分配numberOfMsgs 字符串。 NULL 字符串不必分配,只需设置为NULL

m[numberOfMsgs] = NULL;

最后,您应该释放分配的内存。在您的情况下,您不能这样做,因为您已经增加(并因此更改了)基本指针m。操作系统无法释放内存,因为新的m 没有被内存分配器注册。

所以,例如:

char **m = split_string(message, 140);
int i = 0;

while (m[i]) {
    printf("%d: '%s'\n", i, m[i]);
    free(m[i]);
    i++;
}

free(m);

【讨论】:

  • 感谢您抽出宝贵时间撰写此答案。我正在进行建议的更改。
【解决方案2】:

这就是使用数组的问题,有关其大小的信息应该存储在某个地方,你永远无法知道查看char ** 它有多少成员。

这就是为什么存在以 null 结尾的字符串(c 字符串)的原因,NULL 字符标志着它的结束,因此您必须遍历整个字符串,直到找到 NULL 才能知道它的长度。

无论如何,我建议您将 split_string() 函数修改为:

char** split_string(char* message, size_t * n_msgs) {
   //...
   *n_msgs = numberOfMsgs;
   ///
}

然后:

size_t msgs = 0;
char** m = split_string(message, &msgs);
//...

【讨论】:

  • 感谢您的建议!好主意!
【解决方案3】:

您的 while 循环是一个无限循环。您正在测试永远不会改变的表达式*m,因此您将不断增加i,最终m[i] 将引用尚未分配的内存。

【讨论】:

  • 我的错误,我已经编辑了问题。 i++ 应该是 m++。
【解决方案4】:

你应该改变
for (j =0 ; j <= numberOfMsgs; j++){ m[j] = malloc(141 * sizeof(char));

for (j =0 ; j < numberOfMsgs; j++){
m[j] = malloc(141 * sizeof(char));

【讨论】:

  • 我刚试过。和 valgrind 一起跑。摆脱了一些无效的读取。但是段错误仍然存​​在。
  • 试试 memmove 而不是 memcopy。 memcopy 有一些重叠数组的问题。只需搜索 memmove
  • memmove() 仍然存在同样的问题。
  • 这并不奇怪:inthis case memcpy` 是首选函数,因为您正在从输入字符串复制到新分配的内存,这绝对不会重叠。 (并不是说使用memmove 不会有什么坏处。)
猜你喜欢
  • 1970-01-01
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多