免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2464 | 回复: 8

[C] 字符串放在堆内存中,会不会有啥比较坏的影响? [复制链接]

论坛徽章:
6
CU大牛徽章
日期:2013-05-20 10:43:41IT运维版块每日发帖之星
日期:2016-07-29 06:20:00IT运维版块每日发帖之星
日期:2016-01-27 06:20:00CU大牛徽章
日期:2013-05-20 10:44:16CU大牛徽章
日期:2013-05-20 10:44:0615-16赛季CBA联赛之广东
日期:2018-03-09 11:17:08
发表于 2014-10-26 10:12 |显示全部楼层
本帖最后由 craaazy123 于 2014-10-27 14:29 编辑

rt,先贴一下代码,以下是to_lower_case1函数,主要是将字符串转换为小写:

char *to_lower_case1(const char *src) {
        if(is_empty(src)) return "";
         
        // 申请堆内存
        char *dst = (char *)calloc(strlen(src), sizeof(char *));
        
        // 将原来的拷贝一份
        strcpy(dst, src);
        char *p = dst;
        
       // 遍历转小写
        for(; *p != '\0'; p++) {
                if(*p >= 'A' && *p <= 'Z') {
                        *p += 32;
                }
        }
      
        return dst;
}

这样调用是比较方便的了,(方式一):
printf("%s\n", to_lower_case1("This is a String."));

较之前的(方式二):
char *src = "This Is A String.";
int len = strlen(src);
char dst[len];
printf("%s\n", to_upper_case(dst, src));

注意to_upper_case函数未贴出,其实和to_lower_case1差不多是一样的。


我比较疑惑的是to_lower_case1返回的指针是需要自己手动释放的,但是如果按照方式一调用,内存会不会释放掉?

贴两个文件,有问题的话,麻烦大家提出来,我是来学习的,谢谢:
string_util.h
  1. #ifndef __STRING_UTIL__
  2. #define __STRING_UTIL__

  3. typedef int bool;

  4. //char **split(const char* src, const char *delim);

  5. int first_index_of(const char *src, const char *chs);
  6. int last_index_of(const char *src, const char *chs);
  7. bool is_empty(const char *s);

  8. //char *to_lower_case(char *dst, const char *src);
  9. char *to_lower_case(const char *src);
  10. char *to_upper_case(const char *src);
  11. //char *to_upper_case(char *dst, const char *src);
  12. char *trim(const char *src);
  13. char *ltrim(const char *src);
  14. char *rtrim(const char *src);

  15. char *substr(const char *src, int start, int len);
  16. void destroy(char *s);

  17. #define char_at(str, i) (strlen(str) > i) ? *(str + i) : -1


  18. #endif
复制代码
string_util.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. #define TRUE 1
  5. #define FALSE 0

  6. #include "string_util.h"

  7. int main(int argc, char** argv) {
  8.            //split("This is a string", " ");

  9.     //printf("%d\n", first_index_of("This is a string.", ""));
  10.         //printf("%d\n", is_empty(""));
  11.         /*char *src = "This Is A String.";
  12.         int len = strlen(src);
  13.         char dst[len];
  14.         printf("%s\n", to_upper_case(dst, src));*/

  15.         char *s = to_lower_case("This is a String.");
  16.         printf("%s\n", s);
  17.         destroy(s);

  18. /*        char *s = substr("This is a string.", 5, -1);
  19.         int l = strlen(s);
  20.         printf("s = %s, len = %d\n", s, l);
  21.         destroy(s);*/

  22. /*        char *s = ltrim("  \t \r \n");
  23.         int l = strlen(s);
  24.         printf("s=%s, len=%d\n", s, l);
  25.         destroy(s);*/

  26. /*
  27.         char *s = trim(" \t \r \n This is a String.  \t \r \n");
  28.         int l = strlen(s);
  29.         printf("s=%s, len=%d\n", s, l);
  30.         destroy(s);*/

  31.         //printf("%c\n", char_at("This is a string.", 1));

  32.         return 0;
  33. }

  34. /*char **split(const char* src, const char *delim) {
  35.         if(src == NULL || delim == NULL) return NULL;

  36.         const char *p = src;
  37.         const char **t = NULL;
  38.         for(; *p != '\0'; p++) {
  39.                
  40.         }

  41.        

  42.         return NULL;
  43. }*/


  44. int first_index_of(const char *src, const char *chs) {
  45.         if(is_empty(src) || is_empty(chs))
  46.                 return -1;

  47.         const char *p = src;
  48.         const char *q = chs;

  49.         int len = strlen(chs);
  50.         int i;

  51.         for(i = 0; *p != '\0' || *q != '\0'; p++, i++) {
  52.                 if(*p == *q++) {
  53.                         if(*q == '\0') break;
  54.                 } else {
  55.                         q = chs;
  56.                 }
  57.         }
  58.         return (*q == '\0') ? (i - len + 1) : -1;
  59. }

  60. int last_index_of(const char *src, const char *chs) {
  61.         if(is_empty(src) || is_empty(chs))
  62.                 return -1;

  63.        
  64. }

  65. bool is_empty(const char *s) {
  66.         return (s == NULL || s == "");
  67. }



  68. /*char *to_lower_case(char *dst, const char *src) {
  69.         if(is_empty(src)) {
  70.                 strcpy(dst, "");
  71.                 return dst;
  72.         }
  73.                
  74.         strcpy(dst, src);
  75.         char *p = dst;

  76.         for(; *p != '\0'; p++) {
  77.                 if(*p >= 'A' && *p <= 'Z') {
  78.                         *p += 32;
  79.                 }
  80.         }

  81.         return dst;
  82. }        */

  83. /*char *to_upper_case(char *dst, const char *src) {
  84.         if(is_empty(src)) {
  85.                 strcpy(dst, "");
  86.                 return dst;
  87.         }

  88.         strcpy(dst, src);
  89.         char *p = dst;

  90.         for(; *p != '\0'; p++) {
  91.                 if(*p >= 'a' && *p <= 'z') {
  92.                         *p -= 32;
  93.                 }
  94.         }
  95.         return dst;
  96. }
  97. */
  98. char *to_lower_case(const char *src) {
  99.         if(is_empty(src)) return "";

  100.         char *dst = (char *)calloc(strlen(src), sizeof(char));

  101.         strcpy(dst, src);
  102.         char *p = dst;

  103.         for(; *p != '\0'; p++) {
  104.                 if(*p >= 'A' && *p <= 'Z') {
  105.                         *p += 32;
  106.                 }
  107.         }

  108.         return dst;
  109. }

  110. char *to_upper_case(const char *src) {
  111.         if(is_empty(src)) return "";

  112.         char *dst = (char *)calloc(strlen(src), sizeof(char));

  113.         strcpy(dst, src);
  114.         char *p = dst;

  115.         for(; *p != '\0'; p++) {
  116.                 if(*p >= 'a' && *p <= 'z') {
  117.                         *p -= 32;
  118.                 }
  119.         }

  120.         return dst;
  121. }

  122. char *ltrim(const char* src) {
  123.         if(is_empty(src))
  124.                 return "";

  125.         const char *p = src;
  126.         while(*p++ != '\0' && isspace(*p))
  127.                 ;

  128.         int len = strlen(p);
  129.         if(len > 0) {
  130.                 char *dst = (char *)calloc(len, sizeof(char *));
  131.                 strcpy(dst, p);
  132.                 return dst;
  133.         }
  134.         return "";
  135. }       

  136. char *rtrim(const char* src) {
  137.         if(is_empty(src))
  138.                 return "";
  139.         int len = strlen(src);
  140.         const char *p = src + len;

  141.         int i;
  142.         for(i = len - 1; i >= 0 && isspace(*(src + i)); i--)
  143.                 ;

  144.         if(i > 0) {
  145.                 char *dst = (char *)calloc(i + 1, sizeof(char *));
  146.                 strncpy(dst, src, i + 1);
  147.                 return dst;
  148.         }
  149.         return "";

  150. }

  151. char *trim(const char* src) {
  152.         return rtrim(ltrim(src));
  153. }

  154. char *substr(const char *src, int start, int len) {

  155.         if(is_empty(src))
  156.                 return "";

  157.         int n = strlen(src);
  158.         if(n < start)
  159.                 return "";

  160.         const char *p = src;
  161.         int i;
  162.         for(i = 0; i < start; i++, p++)
  163.                 ;

  164.         char *dst = (char *)calloc((n - start + 1), sizeof(char));
  165.        
  166.         if(len > 0){
  167.                 strncpy(dst, p, len);
  168.         } else {
  169.                 strcpy(dst, p);
  170.         }
  171.         return dst;
  172. }

  173. void destroy(char * s) {
  174.         if(s == NULL) return;
  175.         if(strlen(s) > 0) free(s);
  176.         s = NULL;
  177. }
复制代码

论坛徽章:
301
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2014-10-26 10:15 |显示全部楼层
返回的指针未保存,当然无法释放了

论坛徽章:
6
CU大牛徽章
日期:2013-05-20 10:43:41IT运维版块每日发帖之星
日期:2016-07-29 06:20:00IT运维版块每日发帖之星
日期:2016-01-27 06:20:00CU大牛徽章
日期:2013-05-20 10:44:16CU大牛徽章
日期:2013-05-20 10:44:0615-16赛季CBA联赛之广东
日期:2018-03-09 11:17:08
发表于 2014-10-26 10:17 |显示全部楼层
回复 2# hellioncu


非得这样吗?

char *s = to_lower_case1("This is a String.");
printf("%s\n", s);
free(s);

   

论坛徽章:
301
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2014-10-26 14:34 |显示全部楼层
craaazy123 发表于 2014-10-26 10:17
回复 2# hellioncu

对于你的to_lower_case1,只能这样

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
发表于 2014-10-27 08:29 |显示全部楼层
建议用 方式二

另外,对于 char *dst = (char *)calloc(strlen(src), sizeof(char *));
首先,根本没必要用calloc,而应该用malloc;其次,不应该是sizeof(char *),而应该是sizeof(char),同时strlen(src)应该是strlen(src)+1

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
发表于 2014-10-27 12:47 |显示全部楼层
返回空的时候这么写的:
  1.          if(is_empty(src)) return "";
复制代码
其他情况内存又是这么申请的:
  1. char *dst = (char *)calloc(strlen(src), sizeof(char *));
复制代码
这实现有问题。空的情况下调用free释放返回的指针必然是错的。

论坛徽章:
6
CU大牛徽章
日期:2013-05-20 10:43:41IT运维版块每日发帖之星
日期:2016-07-29 06:20:00IT运维版块每日发帖之星
日期:2016-01-27 06:20:00CU大牛徽章
日期:2013-05-20 10:44:16CU大牛徽章
日期:2013-05-20 10:44:0615-16赛季CBA联赛之广东
日期:2018-03-09 11:17:08
发表于 2014-10-27 14:22 |显示全部楼层
本帖最后由 craaazy123 于 2014-10-27 14:26 编辑

回复 5# bruceteen

之前看了个帖子是这么写的,当时想都没想就copy过来了,发现输出与预期一致就没管了。


   

论坛徽章:
6
CU大牛徽章
日期:2013-05-20 10:43:41IT运维版块每日发帖之星
日期:2016-07-29 06:20:00IT运维版块每日发帖之星
日期:2016-01-27 06:20:00CU大牛徽章
日期:2013-05-20 10:44:16CU大牛徽章
日期:2013-05-20 10:44:0615-16赛季CBA联赛之广东
日期:2018-03-09 11:17:08
发表于 2014-10-27 14:25 |显示全部楼层
回复 6# zhaohongjian000

以前用面向对象的语言用习惯了,用gcc编译后也没告警,不知道这样返回的问题在哪?能不能解释一下? 好久没写c代码了

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
发表于 2014-10-27 14:47 |显示全部楼层
回复 8# craaazy123


    C和C++中,字符串字面量(诸如 ""  "string"  "hello")不需要也不能用free释放。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2021中国系统架构师大会

【数字转型 架构重塑】2021年5月20日-22日第十三届中国系统架构师大会将在云端进行网络直播。

大会为期3天的议程,涉及20+专场,近120个主题,完整迁移到线上进行网络直播对会议组织来说绝非易事;但考虑到云端会议的直播形式可以实现全国各地技术爱好者的参与,也使ITPUB作为技术共享交流平台得到更好的普及,我们决定迎难而上。
http://sacc.it168.com/


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP