C语言:从键盘输入一个长度不定的字符串[C_004]

目录

背景:

Solution:

方案一:那就不要字符串

方案二:动态申请内存


背景:

在很多时候,会遇到从外部按要求输入字符串的情形,有些是明确了长度,有些只是给定了最大长度,而有些没有规定长度。对于那些给定的最大长度很长的情况,虽然我们可以定义一个很长的字符串,但是这样显得很机械,也很浪费内存空间,而对于没有规定最大长度的,我们甚至无法处理。

对于上述情况,本文提供两个解决途经。

Solution:

方案一:那就不要字符串

虽然在遇到问题时不能逃避,但我们也同样不能一味地和问题死磕,目的是解决问题,而上述的字符串本身,相较于我们正在处理的大问题,它便不是问题了。即,倘若可以不把输入全部以字符串的形式读到内存再处理,而是逐个读取,一边读取一边处理,那么上述问题便不存在了。

所以,在这种情况下,读字符串的问题便成了改变算法的问题。当然,在很多情况下,我们是需要把数据全部加载才能完成处理,或者有些情况是逐个读取并处理的算法比全部读取后再处理的算法复杂得多,这样的话字符串这个问题就跳不过了,所以有了方案二,直接解决字符串本身。

方案二:动态申请内存

之所以有这个问题,无非就两点:

1、具体需要读取的字符串长度不定,无法定义字符串。

2、如果定义一个很长的字符串,一是浪费内存,二是当数据很大时,依然有溢出的风险。

具体解决方法如下:

1、先申请一个较小的空间,如N*sizeof(char)。

2、从标准输入中逐个获取字符,放到申请的空间下,直到取到标准输入的末尾。

3、当字符串长度达到N-1时,重新申请一个长度为N=N+step的空间,将方才的字符串放到最前面,后面继续放入从标准输入中读取的字符。

4、重复步骤2和步骤3.

上述方法有两大好处:

1、既完成了不定长度字符串的读取,还不浪费内存,最多就浪费step字节,而step是自定义的,可以很小。

2、绝对不会造成溢出。

代码如下:

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

int main()
{
    char* str = NULL;
    char temp;
    //每次申请内存的大小增幅
    int step = 5;
    //申请内存的大小
    int allStrLen = 5;

    str = malloc(allStrLen * sizeof(char));
    if (str == NULL) {
        printf("Failed to request memory!\n\r");
        return 1;
    }
    memset(str, 0, allStrLen);

    int loc = 0;
    while ((temp = getchar()) != '\n' && temp != EOF) {
        if (loc < allStrLen - 1) {
            *(str + loc) = temp;
            loc++;
            continue;
        }

        char* tempStr = malloc(allStrLen * sizeof(char));
        if (tempStr == NULL) {
            printf("The requested memory is too large!\n\r");
            free(str);
            return 1;
        }

        memset(tempStr, 0, allStrLen);
        memcpy(tempStr, str, loc * sizeof(char));
        free(str);
        allStrLen += step;
        str = malloc(allStrLen * sizeof(char));

        if (str == NULL) {
            printf("The input is too long. Failed to request memory!\n\r");
            return 1;
        }

        memset(str, 0, allStrLen);
        memcpy(str, tempStr, loc * sizeof(char));
        *(str + loc) = temp;
        loc++;
        free(tempStr);
    }

    printf("Final Input:\n\r%s\n\r", str);
    free(str);
    system("pause");
    return 0;
}

 结果如图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值