目的:
首先用戶輸入一個(gè)字符串噪服,然后再次輸入一個(gè)字符串黔寇,然后輸出第二個(gè)字符串在第一個(gè)字符串中出現(xiàn)的次數(shù)灵巧。
步驟
1.分配內(nèi)存
2.從終端接收字符串
3.比較長(zhǎng)度
4.比較
5.輸出
分配內(nèi)存
int main(){
char str1[100] = {};
char str2[100] = {},*p1,*p2;
printf("請(qǐng)輸入語(yǔ)句\n");
Myscanf(str1);
printf("請(qǐng)輸入單詞\n");
Myscanf(str2);
接收字符串抬虽。
- scanf不能輸入帶空格的字符串
略号,只能自己定義一個(gè)輸入語(yǔ)句的方法
void Myscanf(char *str){
int i = 0;
while (1) {
char c = getchar();
if (c == '\n') {
str[i] = '\0';
break;
}
str[i] = c;
i++;
}
}
比較長(zhǎng)度
如果第二次輸入的字符串比第一次輸入的長(zhǎng)刑峡,那么沒有必要進(jìn)行比較洋闽,所以首先進(jìn)行長(zhǎng)度比較
int length(char *p){
int i = 0;
//for (; p[i] != '\0'; i++);
while (1) {
if (p[i] == '\0') {
break;
}
i++;
}
return i;
}
int find(char *sentence, char *word){
//1.獲取兩個(gè)字符串的長(zhǎng)度
int sLength = length(sentence);
int wLength = length(word);
//2.判斷查詢的字符串長(zhǎng)度是否比句子短
if (sLength < wLength) {
return 0;
}
如果字符串一比字符串二長(zhǎng),那么就進(jìn)行比較
方法一
int time;
p1 = str1;
p2 = str2;
while(*p1 != '\0'){
if((*p1 == *p2)){
while((*p1 == *p2)&&(*p2 != '\0')) {
p1++;
p2++;
}
}
else
p1++;
if(*p2 == '\0'){
time++;
p2 = str2;
}
}
printf("重復(fù)的次數(shù)為%d次",time);
getchar();
return 0;
}
方法二
int start = 0;
int count = 0;
for (int i = 0; i < sLength; i++) {
//記錄當(dāng)前開始的位置
start = i;
//從當(dāng)前位置開始去和查找的單詞進(jìn)行比較
int j = 0;
for(; j < wLength; j++){
//判斷j對(duì)應(yīng)的值和start+j比較
if (sentence[start+j] != word[j]) {
break;
}
}
//判斷怎么出來(lái)的
if (j == wLength){
//都相同
//將i的值定位到start+j的位置
i = start + j-1;
count++;
}
}
return count;
}
- 可以看到突梦,最開始用數(shù)組分配內(nèi)存诫舅,已經(jīng)設(shè)定了兩個(gè)數(shù)組的長(zhǎng)度,由于輸入的字符串的長(zhǎng)度是未知的阳似,難免就會(huì)造成內(nèi)存空間的不足或浪費(fèi)骚勘。
所以我們可以進(jìn)行動(dòng)態(tài)分配內(nèi)存。
動(dòng)態(tài)分配內(nèi)存
原因
1.存儲(chǔ)的數(shù)據(jù)需要延長(zhǎng)生命周期
2.一個(gè)指針變量需要存儲(chǔ)數(shù)據(jù)撮奏,變量本身只能存地址俏讹,不能存數(shù)據(jù),需要分配內(nèi)存空間來(lái)存儲(chǔ)數(shù)據(jù)
特點(diǎn)
1.不需要預(yù)先分配儲(chǔ)存空間
2.分配的空間可以根據(jù)程序的需要擴(kuò)大或縮小畜吊。
過程
頭文件為<stdlib.h>
1.定義指針p泽疆,
2.分配數(shù)組空間,用來(lái)存儲(chǔ)數(shù)組元素玲献,空間大小按元素個(gè)數(shù)計(jì)算殉疼;
3.按一維數(shù)組方式使用這個(gè)數(shù)組
若是一維數(shù)組,則元素為p[i]捌年;若是二維數(shù)組瓢娜,則元素為p[i*M+j],其中M為列元素個(gè)數(shù)
4.釋放數(shù)組空間
例如:
char *name礼预;
name = (char *)malloc(10*sizeof(char));
//1.用malloc申請(qǐng)內(nèi)存空間
name = (char *)realloc(name,20*sizeof(char));
//2.使用realloc動(dòng)態(tài)改變已經(jīng)分配內(nèi)存的大小
free(name)
//3.手動(dòng)釋放內(nèi)存
對(duì)于動(dòng)態(tài)分配內(nèi)存眠砾,可以舉如下例子
輸入人名,并為其分配內(nèi)存托酸。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//從終端接收字符串 返回這個(gè)字符串的首地址
char *inputName(){
//1.定義一個(gè)指針變量 指向字符串的首地址
char *pName = NULL;
//2.接收輸入褒颈。一定要進(jìn)行指針初始化。
int i = 0;
//3.提示操作
printf("請(qǐng)輸入人名:");
while (1) {
//接收一個(gè)字符
char c = getchar();
//判斷這個(gè)字符是不是\n
if (c == '\n') {
//輸入結(jié)束
break;
}
//判斷是不是第一個(gè)字符
if(i == 0){
//使用malloc分配內(nèi)存
pName = (char *)malloc(1*sizeof(char));
//判斷是否分配成功
if(pName == NULL){
exit(EXIT_FAILURE);
}
pName[0] = c;
}else{
//使用realloc在之前的基礎(chǔ)上加一個(gè)
pName = realloc(pName, (i+1)*sizeof(char));
//判斷是否分配成功
if(pName == NULL){
exit(EXIT_FAILURE);
}
pName[i] = c;
}
i++;
}
//將當(dāng)前的字符串首地址返回
return pName;
}
是否繼續(xù)
bool isContinue(){
printf("是否繼續(xù)(y/n)?:");
while (1) {
char c = getchar();
getchar();
if (c == 'y'){
return true;
}else if(c == 'n'){
return false;
}else{
printf("輸入格式不對(duì)励堡,請(qǐng)重新輸入:");
}
}
}
輸入人名 將地址放到pHead對(duì)應(yīng)位置
//初始化整個(gè)數(shù)組
char **initNames(int *pNum){
//1.定義指針變量指向每個(gè)名字的首地址的內(nèi)存
char **pHead = NULL;
//2.記錄元素個(gè)數(shù)
int i = 0;
while (1) {
//判斷是不是第一個(gè)
//第一個(gè)使用malloc分配內(nèi)存
if (i == 0) {
pHead = malloc(1*sizeof(char *));
if (pHead == NULL) {
exit(EXIT_FAILURE);
}
//輸入人名 將地址放到pHead對(duì)應(yīng)位置
pHead[0] = inputName();
}else{
//使用realloc重新再增加一個(gè)元素
pHead = realloc(pHead, (i+1)*sizeof(char *));
if (pHead == NULL) {
exit(EXIT_FAILURE);
}
//輸入人名 將地址放到pHead對(duì)應(yīng)位置
pHead[i] = inputName();
}
i++;
//是否繼續(xù)
bool result = isContinue();
if (result == false) {
break;
}
}
*pNum = i;
return pHead;
}
輸入人名
void show(char **pHead, int num){
printf("輸入%d個(gè)名字:\n",num);
for (int i = 0; i < num; i++) {
printf("%s\n",pHead[i]);
}
printf("\n");
}
主函數(shù)
int main(int argc, const char * argv[]) {
char **pHead = NULL;
int count = 0;
pHead = initNames(&count);
show(pHead, count);
return 0;
}
可以觀察到谷丸,運(yùn)用函數(shù)實(shí)現(xiàn)功能,使得主函數(shù)非常簡(jiǎn)潔应结。
注意
在使用完內(nèi)存空間之后刨疼,一定要手動(dòng)釋放內(nèi)存!
作者有話說(shuō)
如果可以摊趾,大家連上自己的熱點(diǎn)再寫簡(jiǎn)書吧币狠,因?yàn)檫@個(gè)校園網(wǎng)可能不知道什么時(shí)候就悄悄咪咪的就給你斷掉了!即使斷掉了,也不要像我一樣去點(diǎn)刷新砾层!