欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言使用函數(shù)實現(xiàn)字符串部分復(fù)制問題

 更新時間:2022年11月14日 14:42:12   作者:率真的瓜子  
這篇文章主要介紹了C語言使用函數(shù)實現(xiàn)字符串部分復(fù)制問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

使用函數(shù)實現(xiàn)字符串部分復(fù)制

本題要求編寫函數(shù),將輸入字符串t中從第m個字符開始的全部字符復(fù)制到字符串s中。

函數(shù)接口定義

void strmcpy( char *t, int m, char *s );

函數(shù)strmcpy將輸入字符串char *t中從第m個字符開始的全部字符復(fù)制到字符串char *s中。若m超過輸入字符串的長度,則結(jié)果字符串應(yīng)為空串。

裁判測試程序樣例

#include <stdio.h>
#define MAXN 20

void strmcpy( char *t, int m, char *s );
void ReadString( char s[] ); /* 由裁判實現(xiàn),略去不表 */

int main()
{
    char t[MAXN], s[MAXN];
    int m;

    scanf("%d\n", &m);
    ReadString(t);
    strmcpy( t, m, s );
    printf("%s\n", s);

    return 0;
}

/* 你的代碼將被嵌在這里 */

輸入樣例:
7
happy new year
輸出樣例:
new year

由于這道題題目中沒有把string.h頭文件include進來,

所以自己寫一個計算長度的函數(shù)

int strlen(char *t)
{
    int i=0;
	while(*t)
	{
		t++;
		i++;
	}
	return i;
}

首先很直觀地就可以把代碼寫出來:

void strmcpy( char *t, int m, char *s )
{
    int n=strlen(t);
    for(int i=0;i<=n-m;i++)
    {
    	s[i]=t[m+i-1];
    	printf("s[%d]=%c\n",i,s[i]);
	}
}

但是這種做法導(dǎo)致最后出來會有多余的空格,因為數(shù)組s沒有添加結(jié)束標(biāo)記。

沒有添加結(jié)束標(biāo)記時,一次性輸出數(shù)組將導(dǎo)致格式錯誤。因此還需添加結(jié)束標(biāo)記:

void strmcpy( char *t, int m, char *s )
{
    int n=strlen(t);
    for(int i=0;i<=n-m+1;i++)   /*把n-m改成了n-m+1,為添加標(biāo)記創(chuàng)造條件*/
    {
    	if(t[m+i-1]=='\0') s[i]='\0';   /*當(dāng)掃描時發(fā)現(xiàn)目標(biāo)數(shù)組中出現(xiàn)結(jié)束標(biāo)記時,為本字符串添加結(jié)束標(biāo)記*/
		s[i]=t[m+i-1];         /*掃描*/
	}
}

來一遍完整代碼:

#include <stdio.h>
#define MAXN 20

void strmcpy( char *t, int m, char *s );
void ReadString( char s[] ); /* óé2??Dêμ??£???è¥2?±í */

int main()
{
    char t[MAXN], s[MAXN];
    int m;

    scanf("%d\n", &m);
    ReadString(t);
    strmcpy( t, m, s );
    printf("%s\n", s);

    return 0;
}

/* ??μ?′ú????±????ú?aà? */
int strlen(char *t)
{
    int i=0;
	while(*t)
	{
		t++;
		i++;
	}
	return i;
}

void ReadString( char s[] )
{
	gets(s);
}

void strmcpy( char *t, int m, char *s )
{
    int n=strlen(t);
    for(int i=0;i<=n-m+1;i++)
    {
    	if(t[m+i-1]=='\0') s[i]='\0';
		s[i]=t[m+i-1];
	}
}

復(fù)制字符串及復(fù)制函數(shù)匯總(strcpy()/memcpy()/strncpy()/memmove())

我們首先來考慮一個簡單的問題,我們定義了一個字符串,然后想要復(fù)制這個字符串,在C語言中,我們可以用for循環(huán)和指針來實現(xiàn),假如我們用指針來操作

#include <stdio.h>

char  str1[20]= "Zxiaoxuan";
char  str2[20];
char * pts1 = str1 ;
char * pts2 = str2;

int main () {
	pts2=pts1;
	return  0;
}

這樣pts2只是復(fù)制字符串str1的地址,而不是復(fù)制整個字符串。

那么如何進行整個字符串的復(fù)制呢

1. 我們可以采用數(shù)組的方式來進行

#include<stdio.h>

void copy_string(char str1[],char str2[]) {
	int i = 0;
	while(str2[i] != '\0') {
		str1[i] = str2[i];
		i++;
	}
	str1[i] = '\0';
}

int main() { 
	char a[100]="zxiaoxuan"; 
    char b[100]=" ";

	copy_string(b,a);
	printf("%s\n",b);
	return 0;
}

輸出:

2. 可以采用指針的方式來進行

#include<stdio.h>

void copy_string(char *p1,char *p2) {
	while(*p2 != '\0') {
		*p1 = *p2;
		*p1++;
		*p2++;
	}
	*p1 = '\0';
}
int main() {
	char a[100]="zxiaoxuan";
	char b[100]=" ";

	copy_string(b,a);
	printf("%s\n",b);
	return 0;
}

輸出:

除了上面兩種,C語言有沒有內(nèi)置的函數(shù)來進行拷貝復(fù)制呢,當(dāng)然是有的,下面我們來逐一介紹。

strcpy()

使用頭文件:#include <string.h>

定義:char *strcpy(char *dest, const char *src);

參數(shù):

  • destinin:目標(biāo)字符數(shù)組;
  • source:源字符數(shù)組;

函數(shù)說明:strcpy()會將參數(shù)src 字符串拷貝至參數(shù)dest 所指的地址。 用于對字符串進行復(fù)制,識別到字符串的結(jié)束符號‘\0’自動停止

返回值:返回參數(shù)dest 的字符串起始地址。

注意:

  • 參數(shù) dest 的內(nèi)存空間要足夠大,否則拷貝可能會造成緩沖溢出。
  • strcpy() 在復(fù)制結(jié)束后會添加結(jié)束符\0,這點和strncpy()不同

strcpy()的參數(shù)是兩個字符串指針,其中 *src源字符串可以是指針,數(shù)組名,或者字符串常量,但是*dest目標(biāo)字符串必須位一個確定的數(shù)據(jù)對象(字符數(shù)組),而且應(yīng)該已經(jīng)開辟好了存儲空間(已經(jīng)做好初始化)

舉例:

#include <stdio.h>
#include <string.h>
int main ()
{
    char  str1[]= "Zxiaoxuan";
    char  str2[20];
    char  str3[20];
    strcpy  (str2,str1);
    strcpy  (str3, "copy successful");
    printf  ( "str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
    return  0;
}

輸出:

memcpy()

使用頭文件:C語言:#include <string.h> C++:#include<cstring>

定義:void memcpy(void *dest, const void *src, size_t n);

參數(shù):

  • destinin:目標(biāo)地址;
  • source:源地址;
  • n:復(fù)制的字節(jié)長度。

函數(shù)說明:memcpy()復(fù)制 src 所指的內(nèi)存數(shù)據(jù)的 n 個字節(jié)到 dest所指的內(nèi)存地址上。也就是從源地址復(fù)制n 個字節(jié)到目標(biāo)地址

第一個和第二個指針都是void型且第二個指針不能被修改,第三個參數(shù)是需要拷貝的內(nèi)存長度按字節(jié)記。

返回值:返回指向 dest 的指針。返回的指針類型是void。

注意:

  • memcpy()并不限制被復(fù)制的數(shù)據(jù)類型,只是逐字節(jié)地進行復(fù)制,任何數(shù)據(jù)類型都可以進行復(fù)制,例如字符數(shù)組、整型、結(jié)構(gòu)體、類等
  • memcpy() 會完整的復(fù)制 num個字節(jié),不會遇到‘\0’而結(jié)束,這點與 strcpy() 不同
  • dest 和 src所指的內(nèi)存空間地址不能重疊
  • 參數(shù) dest 的內(nèi)存空間要足夠大,起碼要大于等于 num個字節(jié)
  • 通常在復(fù)制字符串時用strcpy,而需要復(fù)制其他類型數(shù)據(jù)時則一般用memcpy

舉例:

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

#define N (20)

int main() {
	char *p1 = "zxiaoxuan";
	char *p2 = (char *)malloc(sizeof(char) * N);
	memcpy(p2, p1, N);

	printf("p2 = %s\n", p2);


	system("pause");
	return 0;
}

strncpy()

使用頭文件:#include <string.h>

定義:char *strncpy(char *dest, const char *src, size_t len);

參數(shù):

  • destinin:目標(biāo)字符數(shù)組;
  • source:源字符數(shù)組;
  • len:復(fù)制的字符串長度。

函數(shù)說明:strncpy()復(fù)制字符串 src 的前 len 個字節(jié)到 dest所指的內(nèi)存地址上。

返回值:返回字符串dest

注意:

  • strncpy()在復(fù)制結(jié)束后不會向dest結(jié)尾添加’\0’結(jié)束符 這個是很重要的一個點,要記住
  • 如果source(源字符數(shù)組)的長度>復(fù)制的字符串?dāng)?shù)len,則只復(fù)制source(源字符數(shù)組)的前l(fā)en個字符,不會自動添加結(jié)束符\0
  • 如果source(源字符數(shù)組)的長度<復(fù)制的字符串?dāng)?shù)len,則以NULL填充dest(目標(biāo)字符數(shù)組),直到復(fù)制完n個字節(jié)
  • 參數(shù) dest 的內(nèi)存空間要足夠大,起碼要大于等于 num個字節(jié)
  • 在使用strncpy()的時候,拷貝長度最好為strlen(src)+1,以保證最后的結(jié)束符\0也能被復(fù)制

舉例:

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

int main () {

	char str1[]= "Z Xiao Xuan";
	char str2[40];
	char str3[40];
	/* 拷貝到緩沖區(qū): */
	strncpy ( str2, str1, sizeof(str1)+1); //拷貝長度為 str1+1,將結(jié)束符\0也進行拷貝

	/* 拷貝 5 個字符: */
	strncpy ( str3, str2, 5 );
	str3[5] = '\0';   /* 手動加上終止符 */

	puts (str1);
	puts (str2);
	puts (str3);

	system("pause");

	return 0;
}

memmove()

使用頭文件:#include <string.h>

定義:void *memmove( void* dest, const void* src, size_t count );

參數(shù):

  • destinin:目標(biāo)地址;
  • source:源地址;
  • count:復(fù)制的字節(jié)長度。

函數(shù)說明memmove()復(fù)制 src 所指的內(nèi)存數(shù)據(jù)的 n 個字節(jié)到 dest所指的內(nèi)存地址上。也就是從源地址復(fù)制n 個字節(jié)到目標(biāo)地址。

如果目標(biāo)區(qū)域和源區(qū)域有重疊的話,memmove能夠保證源串在被覆蓋之前將重疊區(qū)域的字節(jié)拷貝到目標(biāo)區(qū)域中,但復(fù)制后源內(nèi)容會被更改。但是當(dāng)目標(biāo)區(qū)域與源區(qū)域沒有重疊則和memcpy函數(shù)功能相同。

緩沖區(qū)重疊這個需要講解一下:

根據(jù)dest(目標(biāo)字符數(shù)組)內(nèi)存區(qū)域和src(源字符數(shù)組)內(nèi)存區(qū)域可分為三種情況:

src內(nèi)存區(qū)域和dest內(nèi)存區(qū)域完全不重疊

src(源字符數(shù)組)內(nèi)存區(qū)域和dest(目標(biāo)字符數(shù)組)內(nèi)存區(qū)域存在重疊 且dest所在區(qū)域在src所在區(qū)域前

如上圖,dest(目標(biāo)字符數(shù)組)和src(源字符數(shù)組)存在三個字節(jié)的內(nèi)存區(qū)域重疊

但是在復(fù)制的時候,先把src的前三個字節(jié)復(fù)制到了dest的前三個內(nèi)存區(qū)域內(nèi),再繼續(xù)復(fù)制到重疊區(qū)域時,就算被覆蓋,也不會有數(shù)據(jù)錯誤 所以這樣可以正常復(fù)制

src(源字符數(shù)組)內(nèi)存區(qū)域和dest(目標(biāo)字符數(shù)組)內(nèi)存區(qū)域存在重疊,且在dst所在區(qū)域在src所在區(qū)域后面

這時候如果使用memcpy()進行復(fù)制,會把三個重疊內(nèi)存字節(jié)覆蓋為src的前三個字節(jié)內(nèi)容,導(dǎo)致復(fù)制到重疊部分的時候出現(xiàn)錯誤

如果使用memmove(),會先將src(源字符數(shù)組)中的內(nèi)容復(fù)制到緩沖區(qū),然后再復(fù)制到dest(目標(biāo)字符數(shù)組)中去,有效的避免了數(shù)據(jù)重疊。

舉例:

下面舉一個例子:

首先定義一個字符串str:memmove can be very useful......

然后把字符串的第15個字節(jié)~第25個字節(jié)的11個字節(jié)數(shù)據(jù),復(fù)制到第20個字節(jié)~第30個字節(jié)中去

  • src(源字符數(shù)組):very useful
  • dest(目標(biāo)字符數(shù)組):useful.....

重疊部分: 第20個字節(jié)~第25個字節(jié)

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

int main () {
	char str[] = "memmove can be very useful......";
	memmove (str+20,str+15,11);
	puts (str);

	system("pause");
	return 0;
}

先將11個字節(jié)的src(源字符數(shù)組)數(shù)據(jù)(very useful)內(nèi)容復(fù)制到緩沖區(qū)中,再用緩沖區(qū)中的內(nèi)容覆蓋dest(目標(biāo)字符數(shù)組)指向的內(nèi)存(第20個字節(jié)~第30個字節(jié)),這樣就避免了第20個字節(jié)~第25個字節(jié)的重疊

最后就變成了memmove can be very very useful.

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++11模板元編程-std::enable_if示例詳解

    C++11模板元編程-std::enable_if示例詳解

    這篇文章主要給大家介紹了關(guān)于C++11模板元編程-std::enable_if的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • C++智能指針shared_ptr

    C++智能指針shared_ptr

    這篇文章主要介紹了C++智能指針shared_ptr,C++11中包括shared_ptr在內(nèi)的多種指針,都是模板類型,意味著使用者可以指定想要操作的類型下文從shared_ptr創(chuàng)建方式展開全文,介紹詳細具有一的參考價值,需要的小伙伴可以參考一下
    2022-03-03
  • C++ stringstream類用法詳解

    C++ stringstream類用法詳解

    這篇文章主要介紹了C++ stringstream類用法詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C語言逆向分析語法超詳細分析

    C語言逆向分析語法超詳細分析

    這篇文章主要介紹了C語言逆向分析語法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • C語言數(shù)組a和&a的區(qū)別講解

    C語言數(shù)組a和&a的區(qū)別講解

    今天小編就為大家分享一篇關(guān)于C語言數(shù)組a和&a的區(qū)別講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • matlab?GUI指紋識別門禁系統(tǒng)介紹及源碼實現(xiàn)

    matlab?GUI指紋識別門禁系統(tǒng)介紹及源碼實現(xiàn)

    這篇文章主要為大家介紹了matlab?GUI指紋識別門禁系統(tǒng)的介紹及源碼實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • C/C++動態(tài)分配與釋放內(nèi)存的區(qū)別詳細解析

    C/C++動態(tài)分配與釋放內(nèi)存的區(qū)別詳細解析

    以下是對C與C++中動態(tài)分配與釋放內(nèi)存的區(qū)別進行了詳細的分析介紹,需要的朋友可以過來參考下
    2013-09-09
  • 用C語言實現(xiàn)圣誕樹(簡易版+進階版)

    用C語言實現(xiàn)圣誕樹(簡易版+進階版)

    大家好,本篇文章主要講的是用C語言實現(xiàn)圣誕樹(簡易版+進階版),感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 關(guān)于C++中strcpy函數(shù)例題講解

    關(guān)于C++中strcpy函數(shù)例題講解

    在本篇文章里小編給大家整理的是關(guān)于C++中strcpy函數(shù)例題講解內(nèi)容,需要的朋友們可以參考下。
    2020-05-05
  • C語言實現(xiàn)三子棋的示例代碼

    C語言實現(xiàn)三子棋的示例代碼

    所謂三子棋,就是三行三列的棋盤,玩家可以和電腦下棋,率先連成三個的獲勝。這篇文章主要為大家詳細介紹了如何通過C語言實現(xiàn)三子棋小游戲,感興趣的小伙伴可以嘗試一下
    2023-01-01

最新評論