C primer plus自用知識點整理(第十一章)字符串和字符串函數

書籍整理內容:
最近在看C primer plus(加深鞏固自己的C語言技巧,爲以後學習C++打個基礎)。
裏面知識針對自己以後要查的點整理出來。
使用工具:visual studio 2013
第二、三章內容:概述、變量、基本數據類型等:https://blog.csdn.net/answerMack/article/details/103766020
第四章內容:字符串和格式化輸入輸出:https://blog.csdn.net/answerMack/article/details/103805900
第五章內容:運算符、表達式和語句:https://blog.csdn.net/answerMack/article/details/103855794
第六章內容:循壞、賦值運算符等:https://blog.csdn.net/answerMack/article/details/103870182
第七章內容:if、if else、?:、switch、goto、continue、邏輯運算符優先級https://blog.csdn.net/answerMack/article/details/103891048
第八章內容:字符輸入輸出函數、輸入驗證(混合輸入)https://blog.csdn.net/answerMack/article/details/103953376
第九章內容:函數和指針:https://blog.csdn.net/answerMack/article/details/103978471
第十章:數組和指針:https://blog.csdn.net/answerMack/article/details/104114028

在這裏插入圖片描述

puts()和printf()

相同:輸出函數
不同:puts()只顯示字符串且自動在字符串末尾加換行符。

字符串常量

雙引號括起來的內容爲字符串常量(字符串字面量),自動在末尾加入\0字符,屬於靜態存儲類別,只會被存儲一次。

字符數組

字符數組和其他數組名一樣,是該數組首元素的地址。
在這裏插入圖片描述
指針表示法:
在這裏插入圖片描述
數組表示法
在這裏插入圖片描述
不同:
在這裏插入圖片描述
數組中的字符串被儲存兩次:字符串常量(靜態存儲區)、數組中的字符串(動態存儲區(程序運行纔會分配內存))

在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

#include <stdio.h>
#define SLEN 40
#define LIM 5
int main(void)
{
	const char *mytalents[LIM] = {
		"Adding numbers swiftly",
		"Multiplying accurately", "Stashing data",
		"Following instructions to the letter",
		"Understanding the C language"
	};
	char yourtalents[LIM][SLEN] = {
		"Walking in a straight line",
		"Sleeping", "Watching television",
		"Mailing letters", "Reading email"
	};
	int i;

	puts("Let's compare talents.");
	printf("%-36s  %-25s\n", "My Talents", "Your Talents");
	for (i = 0; i < LIM; i++)
		printf("%-36s  %-25s\n", mytalents[i], yourtalents[i]);
	printf("\nsizeof mytalents: %zd, sizeof yourtalents: %zd\n",
		sizeof(mytalents), sizeof(yourtalents));
	getchar();
	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

字符串輸入

讀取字符串的函數
char word[20];
int a;


scanf()

scanf()—用法見第四章
scanf()使用指向變量的指針

字符串到字符數組,不需要使用&;
讀取其他變量,需要在變量名前加&。

scanf()函數用%s 只能讀取一個單詞
scanf("%d",&a);
scanf("%s",word);
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
多類型輸入可選擇scanf函數。


gets()輸入函數

    puts()輸出函數

gets()函數可以讀取整行輸入,直到遇到換行符。後丟棄換行符,儲存其他字符,並在末尾添加空字符構成字符串。
gets(word);
在vs中使用gets_s函數替代gets函數
puts()函數只顯示字符串且自動在字符串末尾加換行符
puts(word);
puts(“i am ok.”)==printf(“i am ok.\n”);
在這裏插入圖片描述
當緩字符串過長,緩衝區溢出報錯:
在這裏插入圖片描述


fgets

fgets()輸入函數
fputs()輸出函數
fgets()函數通過第2個參數限制讀入的字符數來解決溢出的問題,是專門設計用於處理文件輸入的函數。
fgets(word,20,stdin);//stdin:從鍵盤讀入
fputs(word,stdout);//stdout:標準輸出:顯示在顯示器上。

fgets()和gets()區別:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
puts()和fputs()區別:
在這裏插入圖片描述在這裏插入圖片描述

#include <stdio.h>
#define STLEN 10
int main(void)
{
	char words[STLEN];

	puts("Enter strings (empty line to quit):");
	while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n')
		fputs(words, stdout);
	puts("Done.");

	return 0;
}

結果:
在這裏插入圖片描述
分析程序:
while條件:
(1)fgets(words, STLEN, stdin) != NULL:即字符串讀取完成(會讀取換行符),讀取文件結尾纔會有NULL。
(2)words[0] != ‘\n’:即首行不爲換行符
程序結果:
因爲數組長度爲10,會循環讀取
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
(1)將換行符替換爲空字符:
在這裏插入圖片描述
(2)若目標數組裝不下一整行輸入,就丟棄多出的字符。
在這裏插入圖片描述
例子:

#include <stdio.h>
#define STLEN 10
int main(void)
{
	char words[STLEN];
	int i;

	puts("Enter strings (empty line to quit):");
	while (fgets(words, STLEN, stdin) != NULL
		&& words[0] != '\n')
	{
		i = 0;
		while (words[i] != '\n' && words[i] != '\0')
			i++;
		if (words[i] == '\n')
			words[i] = '\0';
		else // must have words[i] == '\0'
			while (getchar() != '\n')
				continue;
		puts(words);
	}
	puts("done");
	return 0;
}

結果:
在這裏插入圖片描述
解析:fgets()函數一次只能讀取STLEN-1個字符構成字符串,其末尾有兩種情況
(1)字符少於STLEN-1,且末尾有\n換行符
(2)字符多於STLEN-1,則會去讀其中的STLEN-1字符,添加\0組成字符串。若不解決,則會循環讀取,全部顯示。

第一種情況解決:fgets()函數會讀取換行符,而對空字符,fgets會返回NULL,因此用puts()函數需將換行符替換爲NULL

第二種情況解決:因爲字符多於STLEN-1,則須將多餘STLEN的字符串丟棄,因此讀取words字符串,遇到\0後,將其餘的讀取但不存儲,丟棄。


gets_s()函數

gets_s(word);
gets_s(word,20);
gets_s()與fgets()區別:
在這裏插入圖片描述在這裏插入圖片描述


gets、gets_s、fgets三者比較:

在這裏插入圖片描述
(1)目標存儲區裝得下:三個函數都可以,但fgets()會保留換行符
(2)輸入行太長:
gets()不安全
gets_s()需要編寫特殊函數(或程序中止或退出)。
fgets()可以循環讀取,也可丟棄超出的字符。


創建s_gets()函數

在這裏插入圖片描述
利用fgets()函數返回指向char的指針。


字符串輸出

puts()

在這裏插入圖片描述

fputs()

在這裏插入圖片描述

printf()

在這裏插入圖片描述
在這裏插入圖片描述

自定義輸入輸出函數

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

字符串函數

處理字符串的函數在string.h文件中,常用的有:
strlen() 、 strcat()、 strcmp()、 strncmp() 、 strcpy()、 strncpy()、sprintf()原型在stdio.h文件中、

strlen()

統計字符串長度
strlen(word);

strcat()

strcat()用於拼接字符串,接受兩個字符串爲參數,將第2個字符串備份附加在第1個字符串末尾,然後拼接後形成新字符串1,第2字符串不變。
函數類型爲 char *
strcat函數返回的第一個參數爲新字符串1的地址。
strcat(word,mesg);

strncat()

在這裏插入圖片描述

#include <stdio.h>
#include <string.h>
#define SIZE 30
#define BUGSIZE 13
char * s_gets(char * st, int n);
int main(void)
{
	char flower[SIZE];
	char addon[] = "s smell like old shoes.";
	char bug[BUGSIZE];
	int available;

	puts("What is your favorite flower?");
	s_gets(flower, SIZE);
	if ((strlen(addon) + strlen(flower) + 1) <= SIZE)
		strcat(flower, addon);
	puts(flower);
	puts("What is your favorite bug?");
	s_gets(bug, BUGSIZE);
	available = BUGSIZE - strlen(bug) - 1;
	strncat(bug, addon, available);
	puts(bug);

	return 0;
}
char * s_gets(char * st, int n)
{
	char * ret_val;
	int i = 0;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		while (st[i] != '\n' && st[i] != '\0')
			i++;
		if (st[i] == '\n')
			st[i] = '\0';
		else // must have words[i] == '\0'
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

結果:
在這裏插入圖片描述
超限結果:
在這裏插入圖片描述

strcmp()

用戶的響應與已儲存的字符串作比較。
在這裏插入圖片描述
在這裏插入圖片描述
其中:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

#include <stdio.h>
#include <string.h>
#define SIZE 80
#define LIM 10
#define STOP "quit"
char * s_gets(char * st, int n);

int main(void)
{
	char input[LIM][SIZE];
	int ct = 0;

	printf("Enter up to %d lines (type quit to quit):\n", LIM);
	while (ct < LIM && s_gets(input[ct], SIZE) != NULL &&
		strcmp(input[ct], STOP) != 0)
	{
		ct++;
	}
	printf("%d strings entered\n", ct);

	return 0;
}

char * s_gets(char * st, int n)
{
	char * ret_val;
	int i = 0;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		while (st[i] != '\n' && st[i] != '\0')
			i++;
		if (st[i] == '\n')
			st[i] = '\0';
		else // must have words[i] == '\0'
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

strncmp()

在這裏插入圖片描述
strncmp(字符串1,字符串2,比較指定的字符數)
順序比較,前幾個指定的字符數

#include <stdio.h>
#include <string.h>
#define LISTSIZE 6
int main()
{
	const char * list[LISTSIZE] =
	{
		"astronomy", "astounding",
		"astrophysics", "ostracize",
		"asterism", "astrophobia"
	};
	int count = 0;
	int i;

	for (i = 0; i < LISTSIZE; i++)
		if (strncmp(list[i], "astro", 3) == 0)
		{
			printf("Found: %s\n", list[i]);
			count++;
		}
	printf("The list contained %d words beginning"
		" with astro.\n", count);

	return 0;
}

在這裏插入圖片描述

strcpy() strncpy()

strcpy() 拷貝整個字符串,相當於給字符串賦值。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

#include <stdio.h>
#include <string.h>    // declares strcpy()
#define WORDS  "beast"
#define SIZE 40

int main(void)
{
	const char * orig = WORDS;
	char copy[SIZE] = "Be the best that you can be.";
	char * ps;
	int a;
	puts(orig);
	puts(copy);
	a=strcpy_s(copy + 7,strlen(orig)+1, orig);
	puts(copy);
	//puts(ps);
	printf("%d\n", a);
	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
strncpy():
strncpy_s(qwords[i], temp, 7 - 1);

/* copy3.c -- strncpy() demo */
#include <stdio.h>
#include <string.h>  /* declares strncpy() */
#define SIZE 40
#define TARGSIZE 7
#define LIM 5
char * s_gets(char * st, int n);

int main(void)
{
    char qwords[LIM][TARGSIZE];
    char temp[SIZE];
    int i = 0;
    
    printf("Enter %d words beginning with q:\n", LIM);
    while (i < LIM && s_gets(temp, SIZE))
    {
        if (temp[0] != 'q')
            printf("%s doesn't begin with q!\n", temp);
        else
        {
            strncpy_s(qwords[i], temp, TARGSIZE - 1);
            qwords[i][TARGSIZE - 1] = '\0';
            i++;
        }
    }
    puts("Here are the words accepted:");
    for (i = 0; i < LIM; i++)
        puts(qwords[i]);
    
    return 0;
}

strncpy(target,source,n);
把source中的n個字符或空字符之前的字符拷貝到target中。
若拷貝字符數小於source字符數,則未拷貝空字符。
在這裏插入圖片描述

sprintf()

sprintf()在stdio.h文件中。是把數據寫入字符串,不是打印顯示。
在這裏插入圖片描述

#include <stdio.h>
#define MAX 20
char * s_gets(char * st, int n);

int main(void)
{
	char first[MAX];
	char last[MAX];
	char formal[2 * MAX + 10];
	double prize;

	puts("Enter your first name:");
	s_gets(first, MAX);
	puts("Enter your last name:");
	s_gets(last, MAX);
	puts("Enter your prize money:");
	scanf_s("%lf", &prize);
	sprintf_s(formal, "%s, %-19s: $%6.2f\n", last, first, prize);
	puts(formal);

	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述

其他字符串函數

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

字符串示例:排序

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

#define  LIMB 5
#define  HIMB 40

char * s_gets(char * st, int n);
void paixu(char *string[], int num);

int main(void) {

	char CMPS[LIMB][HIMB];
	char * ptr[LIMB];

	int i = 0;
	puts("shu ru zhi:");
	while (i<LIMB&&s_gets(CMPS[i],HIMB)!=NULL&&CMPS[i][0]!='\0')
	{
		ptr[i] = CMPS[i];
		i++;
	}
	
	paixu(ptr, i);
	puts("jie guo wei :");
	for (int a = 0; a < i;a++)
	{
		puts(ptr[a]);
	}

		return 0;
}



char * s_gets(char * st, int n)
{
	char * ret_val;
	int i = 0;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		while (st[i] != '\n' && st[i] != '\0')
			i++;
		if (st[i] == '\n')
			st[i] = '\0';
		else // must have words[i] == '\0'
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

void paixu(char *string[], int num) {
	char * temp;
	int top, seek;
	for (top = 0; top < num - 1; top++)
		for (seek = top + 1; seek < num;seek++)
			if (strcmp(string[top],string[seek])>0)////seek>top
			{
				temp = string[top];
				string[top] = string[seek];
				string[seek] = temp;
			}
	
}

在這裏插入圖片描述
排序的是指針,並不是字符串。
在這裏插入圖片描述
排序方法爲:
在這裏插入圖片描述

在這裏插入圖片描述
高級排序函數:qsort();見第16章

ctype.h字符函數和字符串

第七章講過:
在這裏插入圖片描述

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

#define LIMIT 8
void ToUpper(char *);
int PunctCount(const char *);

int main(void)
{
	char line[LIMIT];
	char * find;

	puts("Please enter a line:");

	fgets(line, LIMIT, stdin);
	find = strchr(line, '\n');   // look for newline
	if (find)                    // if the address is not NULL,
		*find = '\0';            // place a null character there

	ToUpper(line);
	puts(line);
	printf("That line has %d punctuation characters.\n",
		PunctCount(line));

	return 0;
}

void ToUpper(char * str)
{
	while (*str)
	{
		*str = toupper(*str);
		str++;
	}
}

int PunctCount(const char * str)
{
	int ct = 0;
	while (*str)
	{
		if (ispunct(*str))
			ct++;
		str++;
	}

	return ct;
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

命令行參數:int main(int argc,char * argv [])

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
例子:main函數中含參數,argc(argument count 參數計數)argv(argument value 參數值)爲指針數組。

#include <stdio.h>
int main(int argc, char *argv[])
{
	int count;

	printf("The command line has %d arguments:\n", argc - 1);
	for (count = 1; count < argc; count++)
		printf("%d: %s\n", count, argv[count]);
	printf("\n");
	getchar();
	return 0;
}

運行方法:
找到文件目錄:
在這裏插入圖片描述
打開cmd,命令行窗口
在這裏插入圖片描述
輸入命令:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

字符串轉爲數字

#include <stdio.h>
#include <stdlib.h>//程序包含此頭文件,包含了atoi函數原型
//#include <string.h>

int main(int argc, char ** argv) {
	int times;
	if (argc<2||(times=atoi(argv[1]))<1)
	{
		printf("%s shi cuo wu de. \n", argv[0]);
	}
	else
	{
		for (int i = 0; i < times;i++)
		 {
			 printf("hhhhhhhhhh.\n");
		 }
	}
		
	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述

stdlib.h

附錄B 頁數p698
在這裏插入圖片描述

strtol()

函數原型:
long strtol(const char * restrict nptr, char ** restrict endptr,int base);

nptr是指向待轉換字符串的指針,
endptr是一個指針的地址,該指針被設置爲標識輸入數字結束字符的地址,如‘\0’ '\n’或輸入數字後面的其他字符等。
base表示以什麼進制寫入數字。
restrict 限制函數參數的用法,例如不能將字符串拷貝給本身。詳見16章。

#include <stdio.h>
#include <stdlib.h>
#define LIM 30
char * s_gets(char * st, int n);

int main()
{
	char number[LIM];
	char * end;
	long value;

	puts("Enter a number (empty line to quit):");
	while (s_gets(number, LIM) && number[0] != '\0')
	{
		value = strtol(number, &end, 10);  /* base 10 */
		printf("base 10 input, base 10 output: %ld, stopped at %s (%d)\n",
			value, end, *end);
		value = strtol(number, &end, 16);  /* base 16 */
		printf("base 16 input, base 10 output: %ld, stopped at %s (%d)\n",
			value, end, *end);
		puts("Next number:");

	}
	puts("Bye!\n");

	return 0;
}

在這裏插入圖片描述
進制
base 10進制 輸入輸出都爲10進制
base 16進制 輸入輸出都爲16進制。
第一輸入:
輸入字符串10 相當於“10\0”
end 指向“\0”空字符,打印end,會顯示一個空字符,%d輸出*end的值爲空字符的ASCII碼值0。
第2輸入:
10aaaa
10進制中:end爲指向“aaaa\0”字符串的首地址“a”,打印字符串%s,結果爲aaaa,%d爲‘a’字符的ASCII碼值。
16進制中:“a”爲16進制數,故將10aaaa其轉爲十進制數爲1092266,end爲指向空字符的指針。
在這裏插入圖片描述
在這裏插入圖片描述

關鍵概念和本章小結

在這裏插入圖片描述
可以讀一下,值得一讀的小結:
在這裏插入圖片描述
在這裏插入圖片描述


2020-04-02 疫情還未結束,加油加油!!!!剛把得!!!!
大連


對fgets()函數的理解:

fgets函數讀取n-1個字符,後加入‘\0’組成字符串形式。
對於stdin(鍵盤輸入),在按下enter鍵之前,數據都存放於臨時緩衝區,按下enter之後,會增加換行符,並把數據發送給fgets接收。但是如果n-1的數量小於輸入數量,則其他字符仍會存在輸入行。在下次fgets調用後,會接着讀取n-1後面的字符。此時需要對其中的字符進行處理,採用while (getchar() != ‘\n’) continue;形式丟棄。
在while判斷字符輸入時可採用:(單獨的null條件會使得程序一直運行)
while (fgets(words, STLEN, stdin) != NULL && words[0] != ‘\n’)
while (s_gets(words, STLEN, stdin) != NULL && words[0] != ‘\0’)

#include <stdio.h>
#define MAX 5
char * s_gets(char * st, int n);

int main(void)
{
	char first[MAX];
	char last[MAX];
	char formal[2 * MAX + 10];
	double prize;

	puts("Enter your first name:");
	
	/*puts("Enter your last name:");
	s_gets(last, MAX);
	puts("Enter your prize money:");
	scanf_s("%lf", &prize);
	sprintf_s(formal, "%s, %-19s: $%6.2f\n", last, first, prize);*/
	while (s_gets(first, MAX)!=NULL&&first[0]!='\0')
	{
		puts(first);
	}
	
	puts("bye");
	return 0;
}

char * s_gets(char * st, int n)
{
	char * ret_val;
	int i = 0;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		while (st[i] != '\n' && st[i] != '\0')
			i++;
		if (st[i] == '\n')
			st[i] = '\0';
		else // must have words[i] == '\0'
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

2020-04-03


課後習題值得做一做的!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章