字符串的读入程序总结

为什么要动态内存分配?

(一)给字符串使用动态内存分配是为了高效占用内存

(二)只有使用指针,才能动态内存分配

(三)要给字符串分配内存时,不仅要考虑字符串的长度,还要考虑字符串个数

堆中的内存是由程序员控制的。

创建指针变量引用字符串

//从键盘上读取一个字符串(创建字符指针)

const size_t BUF_SIZE = 100;
char buffer[BUF_SIZE];
scanf_s("%s",buffer,BUF_SIZE);

//Allocate space for the string给字符串分配空间
size_t length = strnlen_s(buffer,BUF_SIZE)+1char *pString = malloc(length);
if(!pString)
{
    printf("Memory allocation failed.\n");
    return 1;
}
strcpy_s(pString,length,buffer);/复制字符串给新内存
printf("%s",pString);
free(pString);
pString = NULL;

这段代码把一个字符串读入一个char数组中,给读入的字符串分配堆上的内存,将字符串复制到新内存中。把字符串复制到pString引用的内存中,就允许重用buffer,来读取更多的字符

使用指针数组
如何处理任意长度的字符串?

//从键盘上读取多个字符串,并存储它们(创建字符指针数组)
//字符串的个数是指定的 

#define STR_COUNT 10
const size_t BUF_SIZE = 100;
char buffer[BUF_SIZE];
char *pS[STR_COUNT] ={NULL};

for(size_t i = 0; i < str_count ;++i)
{
    scanf("%s",buffer,BUF_SIZE);
    str_size = strnlen_s(buffer,BUF_SIZE) + 1;
    pS[i] = malloc(str_size);//给字符串分配内存
    if(!pS[i])
    return 1;
    strcpy_s(pS[i],str_size,buffer);复制字符串新内存
}
//Do something with strings

//Release the heap memory 释放堆内存
for(size_t i = 0;i < STR_COUNT; ++i)
{
    free(pS[i]);
    pS[i] = NULL;
}

注意:
在初始化数组时,不能使用变量指定数组的维数,
用变量指定数组的维数,该数组就是变长的,不允许初始化它,但总是可以在创建数组后,在循环中设置元素的值。

Allocate space for the string
Allocation failed so end
Copy string to new memory

字符串在for循环中输入。字符串读入buffer后,就使用malloc()在堆上分配足够的内存,来存储字符串。malloc()函数返回的指针存储在pS数组的一个元素中。把buffer中的字符串复制到为它分配的内存中,使buffer可用于读取下一个字符串。最后得到一个字符串数组。其中的每一个字符串都占用它需要的字节数,这是非常高效的。
为什么要把buffer中的字符串复制到为它分配的新内存中

不知道要输入多少个字符串

//Read multiple lines of prose from the keyboard
while(true)
{
    fgets(buf,BUF_LEN,stdin);
    if(buf[0] == '\n')
    break;

    if(strnlen(pStr,str_size)+strnlen_s(buf,BUF_SIZE)+1 > str_size)
    {
        str_size = strnlen_s(pStr,str_size) + strnlen_s(buf,BUF_LEN) + 1;
        pStr = realloc(pStr,str_size);
    }
    if(strcat_s(pStr,str_size,buf))
    {
        printf("Something's wrong,String concatenation failed.\n");
        return 1;
    }
}

Read in all the strings

char *ptr = NULL;
while(true)
{
    ptr = fgets(buf,BUF_LEN,stdin);
    if(!ptr)
    {
        printf("Error reading string.\n");
        free(pS);
        pS = NULL;
        return 1;
    }

    if(*ptr == '\n')
    break;

    if(str_count ==capacity)
    {
        capacity += capacity/4;
        if(!(psTemp = realloc(pS,capacity)))
        return 1;
        pS = psTemp;
    }
    str_len = strnlen_s(buf,BUF_LEN) +1;
    if(!(pS[str_count] = malloc(str_len)))
    return 2;
    strcpy_s(pS[str_count++],str_len,buf);
}

计算字符串的个数和长度

#include <stdio.h>

int main()
{
    char str[][70] = {
        "Computers do what you tell them to do ,not what you want them to do.",
        "When you put something in memory,remember you put them it.",
        "Never test for a condition you don't know what to do with.",
    };

    unsigned int count = 0;
    unsigned int strCount = sizeof(str) / sizeof(str[0]);
    printf("There are %u string.\n",strCount);

    for (unsigned int i = 0; i < strCount; ++i)
    {
        count = 0;
        while (str[i][count])
            ++count;

        printf("The string is:\n   \" %s \"\n  contain %u character.\n",str[i],count);
    }
    return 0;

}

单元化字符串

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int main(void)
{
    char delimiters[] = " \".,;:!?)(";
    char buf[100];//字符数组
    char str[1000];
    char *ptr = NULL; //创建指针
    str[0] = '\0';
    size_t str_len = sizeof(str);
    size_t buf_len = sizeof(buf);
    printf("Enter some prose that is less than %zd character.\n"
        "Terminate input by entering an empty line:\n", str_len);

    while (true)
    {
        if (!gets_s(buf, buf_len))
        {
            printf("Error reading string.\n");
            return 1;
        }
        if (!strnlen_s(buf, buf_len))
            break;
        if (strcat_s(str, str_len, buf))
        {
            printf("Maximum permitted input length exceeded.\n");
            return 1;
        }
    }
    printf("The words in the prose that you entered are:\n", str);

    unsigned int word_count = 0;
    char *pWord = strtok_s(str, delimiters, &ptr);

    if (pWord)
    {
        do
        {
            printf("%s", pWord);
            ++word_count;
            if (word_count % 5 == 0)
                printf("\n");

            pWord = strtok_s(NULL, delimiters, &ptr);
        } while (pWord);
        printf("\n%u words found.\n", word_count);
    }
    else
        printf("No words found.\n");
    return 0;

}

/*
My father's family name beings Pirrip,and my Christian name Philip,
my infant tongue could make of both names nothings longer
or more explicit than Pip.
So ,I called myself Pip, and came to be called Pip.
*/
  1. 学习如何去学习一个大的程序
    (1)先看这个程序大的框架是什么?
    (2)理解每一小部分的作用是什么?即使一个空格都有其存在的意义。
    (3)没有语法错误但是运行出现错误的时候,哪里不正确就去哪里找找问题。

  2. 我从这个程序中学到了什么呢?
    (1)使用strtok_s()函数单元化字符串
    (2)什么是单元化?
    (3)什么是标记?
    (4)对任意的理解???如何让程序实现任意呢?
    (5)只按下回车键,没有输入字符,str[0]设置为\0.(空行)

问题
开发一个程序,从键盘上读取任意长度的一段文本,确定该文本中每个单词出现的频率。该段文本的长度不完全是任意的,因为我们要给程序中的数组大小指定一个限制,但可以使数组存储任意大小的文本

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define _STDC_WANT_LIB_EXT1_ 1

#define TEXT_LEN 10000
#define BUF_SIZE 100
#define MAX_WORDS 500
#define WORD_LEN 12

int main()
{
    char delimiters[] = " \",.:;!?)(";
    char text[TEXT_LEN] = "";  //存储完整的文本
    char buf[BUF_SIZE];  //存储输入行
    char words[MAX_WORDS][WORD_LEN];//存储从文本中的单词
    int nword[MAX_WORDS] = { 0 }; // 出现的次数
    int word_count = 0;  //存储单词数

    printf("Enter text on an arbitrary number of lines.");
    printf("\nEnter an empty line to end input:\n");

    while (true)
    {
        fgets(buf, BUF_SIZE, stdin);
        if (buf[0] == '\n')
            break;
        if (strcat_s(text, TEXT_LEN, buf))
        {
            printf("操作失败");
            return 1;
        }
    }
    //Find the first word
    size_t len = TEXT_LEN;
    char *ptr = NULL;
    char* pWord = strtok_s(text, &len, delimiters, &ptr);

    if (!pWord)
    {
        printf("No words found.Ending program.\n");
        return 1;
    }
    strcpy_s(words[word_count], WORD_LEN, pWord);
    ++nword[word_count++];

    //Find the rest of the words
    bool new_word = true;
    while (true)
    {
        pWord = strtok_s(NULL,&len,delimiters,&ptr);
        if (!pWord)
            break;

        for (int i = 0; i < word_count; ++i)
        {
            if (strcmp(words[i], pWord) == 0)
            {
                ++nword[i];
                new_word = false;
            }
        }

        if (new_word)
        {
            strcpy_s(words[word_count], WORD_LEN, pWord);
            ++nword[word_count++];
        }
        else
            new_word = true;

        if (word_count > MAX_WORDS - 1)
        {
            printf("Capacity to store words exceeded.\n");
            return 1;
        }
    }

    //List the words
    for (int i = 0; i < word_count; ++i)
    {
        printf(" %-13s %3d",words[i],nword[i]);
        if ((i + 1) % 4 == 0)
            printf("\n");
    }
    printf("\n");

    return 0;
}
/*
When  I makes tea I makes tea,as old mother Grogan said.
And when I makes water I makes water
Begob, ma'am,says Mrs Cahill ,God send you don't make them in the same pot.
*/

给字符串分配内存

#define _STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#define BUF_LEN 100
#define INIT_STR_EXT1 50
#define WORDS_INCR 5

int main(void)
{
    char delimiters[] = " \",.:;!?)(";
    char buf[BUF_LEN];
    size_t str_size = INIT_STR_EXT1;
    char *pStr=(char*)malloc(str_size);
    *pStr = '\0';

    printf("Enter some prose with up to %d characters per line.\n"
        "Terminate input by entering an empty line:\n", BUF_LEN);

    //从键盘上读取多行文本
    while (true)
    {
        fgets(buf, BUF_LEN, stdin);
        if (buf[0] == '\n')
            break;
        if (strnlen_s(pStr, str_size) + strnlen_s(buf, BUF_LEN) + 1 > str_size)
        {
            str_size = strnlen_s(pStr, str_size) + strnlen_s(buf, BUF_LEN) + 1;
            pStr = (char*)realloc(pStr, str_size);
        }
        if (strcat_s(pStr, str_size, buf))
        {
            printf("操作没有实现");
            return 1;
        }
    }
    //在散文中找到并且列出所有的单词
    size_t maxWords = 10;
    int word_count = 0;
    size_t word_length = 0;
    char** pWords = (char**)calloc(maxWords, sizeof(char*));
    int* pnWord = (int*)calloc(maxWords, sizeof(int));

    size_t str_len = strnlen_s(pStr, str_size);
    char* ptr = NULL;
    char* pWord = strtok_s(pStr, delimiters, &ptr);

    if (!pWord)
    {
        printf("NO words found.Ending program.\n");
        return 1;
    }

    bool new_word = true;
    while (pWord)
    {
        for (int i = 0; i < word_count; ++i)
        {
            if (strcmp(*(pWords + i), pWord) == 0)
            {
                ++*(pWord + i);
                new_word = false;
                break;
            }
        }
    }

        if (new_word)
        {
            if (word_count == maxWords)
            {
                //
                maxWords += WORDS_INCR;
                pWords = (char**)realloc(pWords, maxWords * sizeof(char*));

                //
                pnWord = (int*)realloc(pnWord, maxWords * sizeof(int));
            }
            //Found a new word so get memory for it and copy it there
            word_length = ptr - pWord;
            *(pWords + word_count) = (char*)malloc(word_length);
            strcpy_s(*(pWords + word_count++), word_length, pWord);
            *(pnWord + word_count++) = 1;
        }
        else
            new_word = true;
        pWord = strtok_s(NULL, delimiters, &ptr);

    //输出单词和数量
    for (int i = 0; i < word_count; ++i)
    {
        printf(" %-13s %3d",*(pWords + i),*(pnWord + i));
        if ((i + 1) % 4 == 0)
            printf("\n");
    }
    printf("\n");
    //释放内存
    for (int i = 0; i < word_count; ++i)
    {
        free(*(pWords + i));
        *(pWords + i) = NULL;
    }

    free(pWords);
    pWords = NULL;
    free(pnWord);
    pnWord = NULL;
    free(pStr);
    pStr = NULL;
    return 0;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值