| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1385 人关注过本帖
标题:关于c语言malloc函数开辟字符串的问题!
只看楼主 加入收藏
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
结帖率:90.24%
收藏
已结贴  问题点数:20 回复次数:10 
关于c语言malloc函数开辟字符串的问题!
楼主想通过键盘输入一个字符串,并用指针char *p指向该字符串的首地址,请问应该如何操作:

楼主以前通常这样处理:

char x[100];
char *p;
p=x;
gets(p);

这样虽然可以处理,但是开辟一个数组x[100]是相当浪费内存的!
请问楼主能够通过绕过x[100]的定义,直接开辟输入一个字符串(长度不固定,有输入长度决定),并使用*p指向该字符串?

求助!
搜索更多相关主题的帖子: 字符串 c语言 键盘 如何 
2015-04-10 10:33
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:4 
解决方案有三:
1.用更耗费内存的链表;
2.用支持C99标准的编译器构造“动态数组”,不过这个方案对你的需求其实不大适合,因为无法在输入完毕之前知道需要“动态”的尺寸;
3.用C++新的string类型(这是现代编程的推荐方案)

授人以渔,不授人以鱼。
2015-04-10 10:42
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
收藏
得分:4 
栈,默认情况下,有 1Mb 大小的空间,是随函数的进入而分配、函数的退出而清除。因此,只要不是特别特别的大,在栈上分配点内存用用,比如你示例里的 100 byte ,是非常非常无所谓的。

第二, gets() 函数是一个古老的函数,从C起源开始就存在,这个函数默认需要程序员自己管理好缓存区,当输入过大,导致缓存溢出(比如受到超长字符串恶意溢出攻击),那它是不管的。

综合上述两项,因为是栈上分配,当函数结束的时候,内存空间全部归还,一点都没有浪费。你是否已经觉得心里好受些了?

malloc 函数是在堆上分配内存,也就是常说的进程内存,每个进程最大通常是 4Gb,但分配了就必须销毁,不然这个进程就没有其他人可以使用这块内存了。而且实践中,我们还会遇到大量使用 malloc 分配小块内存后,存在内存碎片问题,导致最后无法分配出一块大的连续内存。

嗯,我的回答真的好像不是你要的回答,有点答非所问了 ,但按照我这个观点,你上面的代码一点问题都没有,不需要再说什么的。
2015-04-10 10:56
TAAAAB
Rank: 7Rank: 7Rank: 7
来 自:湖南
等 级:黑侠
威 望:1
帖 子:243
专家分:635
注 册:2011-5-29
收藏
得分:4 
在输入之前确定字符串的长度,以免浪费内存空间。问题本身看上去好像无解。
从限制输入来避免浪费行不行?
或者先监时动态分配一个,发现有浪费了再把换个不浪费的,把监时的释放?
反正也不比浪费那么一点好。坐等大神高见

人有多懒,编程就有多难。
2015-04-10 14:01
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
考慮这些枝节问题没用的,得不偿失。

授人以渔,不授人以鱼。
2015-04-10 14:06
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:4 
动态无限长的字符串手段太多了,甚至可以用int、double返回值的手段解决。

能编个毛线衣吗?
2015-04-10 14:29
wyw19880809
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:3
帖 子:178
专家分:738
注 册:2013-3-14
收藏
得分:4 
使用getchar函数,存储用malloc 读入一个非终止符就remalloc一下,就不会浪费空间了,就看这开销你愿意接受不了
2015-04-10 19:56
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
//谢谢大家,我用动态链表的方法得到了解决

#include<stdio.h>
#include<stdlib.h>
#define LEN sizeof(struct Word)

struct Word
{
    char letter;
    struct Word *next;
};

int main()
{
    struct Word *creat(void);
    void print(struct Word *p);
    struct Word *p;
    p=creat();
    print(p);
    return 0;
}

struct Word *creat(void)
{
    struct Word *p1,*p2,*head;
    int n;
    n=0;
    head=NULL;
    puts("Please input the array:");
    p1=p2=(struct Word*)malloc(LEN);
    scanf("%c",&p1->letter);
    while(p1->letter!='\n')
    {
        n++;
        if(n==1)head=p1;
        else p2->next=p1;
        p2=p1;
        p1=(struct Word*)malloc(LEN);
        scanf("%c",&p1->letter);
    }
    p2->next=NULL;
    return head;              //返回一个指向表首的指针
}

void print(struct Word *p)
{
    puts("the array that putted is:");
    if(p!=NULL)
    while(p!=NULL)
    {
        printf("%c",p->letter);
        p=p->next;
    }
    else
        puts("The array is NULL");
    putchar('\n');
}

既然还有不甘心
就还没到放弃的时候~
2015-04-12 09:15
z_j_j_1
Rank: 4
等 级:业余侠客
威 望:1
帖 子:62
专家分:213
注 册:2015-4-4
收藏
得分:0 
回复 8楼 S140131022
这个不错!很多地方都用的到
2015-04-13 10:35
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
收藏
得分:0 


真有心,代码写得有点古怪,总体思路倒是很清晰的,赞一个

我通常还是以实际使用为目的来考虑问题,就事论事的就你帖子最初的问题来说,可以非常非常简单地如下处理:

char* gets_safe()
{
    const int LENGTH = 1024;
    size_t len = 0;
    char* ret = NULL;
    char buffer[LENGTH + 1] = {0};

    while( LENGTH != 0 ){
        size_t iLen = 0;
        if( fgets(buffer, LENGTH + 1, stdin) == NULL ){
            buffer[0] = 0;
            break;
        }
        iLen = strlen(buffer);
        if(iLen != 0){
            if( ret == NULL )
                ret = (char*)malloc(iLen + 1);
            else{
                // 原来代码在这里准备使用 realloc() 函数
                // 但发现 realloc() 函数对 C 运行时库有版本依赖
                // 因此改成自己实现:
                char* tmp = (char*)malloc(len + iLen + 1);
                strncpy(tmp, ret, len);
                free(ret);
                ret = tmp;
            }
            strncpy(ret + len, buffer, iLen);
            len += iLen;
            ret[len] = 0;
        }
        if(buffer[iLen - 1] == 0x0A){
            ret[len - 1] = 0;
            break;
        }
    }

    return ret;
}

对的,就一个函数。就把你需要的东西都完成了。

你可以看到我在函数里有一个常量 const int LENGTH = 1024,代码里初始化为 1024 是我认为常规情况下,这个大小足够做为输入缓存使用,这样,在这个大小之下,这个函数和常规的 C 运行时库里提供的函数做完全同样的工作。但一旦输入超过这个大小,这个函数就显示出比 C 运行时库更安全更完善的特点。

对于这个常量,你在使用时,也可以按照你最后那个代码里一个字节一个字节那样去分配,即写成:const int LENGTH = 1 也一样可以工作,缺点就是会导致不断调用 malloc() 函数,从而可能引起函数运行速度变慢、内存碎片增加的缺点。

另外,这个函数也是可以接收任意输入大小,直到电脑内存耗尽。这里有一点需要说明,就是函数内部分配的 buffer,在整个函数期间只分配了一次,函数执行完毕后,该内存自动返还给栈,不会导致内存碎片也不会导致性能损失,更不会对后续代码造成任何影响。

利用这个函数,对于你最初提的问题,就变得很简单了,再也不需要在使用前分配 char x[100] 这样的内存,直接可以这样使用:

char* p = gets_safe();
2015-04-13 11:42
快速回复:关于c语言malloc函数开辟字符串的问题!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.031328 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved