c primer plus第11章答案--个人注释及额外理解版本

11.1

采用了

do
{

}
while ()

的方式

//11.1
#include <stdio.h>
#define LEN 10

int main(int argc, char *argv[])
{
	int i;
	char input[LEN];

	printf("请输入%d个字符(遇EOF停止读取):\n", LEN -1);
	getnchar(input, LEN - 1);//捕获我们的输入
	printf("打印结果(包括空白符)是:\n");
	puts(input);//捕获不为空,即可输出地址里的内容

	printf("本程序完成!\n");

	return 0;
}

void getnchar(char st[], int n)///指向的字符串   长度
{
	int i = 0;
//先获取,再判断
	do
	{
		st[i] = getchar();//将我们的输入赋值到数组里
	
	} while ( (st[i] != EOF) && (++i < n) );//内部字符不可以是结束标志、不可以超过数组大小,超出退出循环
	
    //结束循环后,最后一个字符添加一个结束标志
	st[i] = '\0';

	return;
}

11.2

/* Programming Exercise 11-2 */
#include <stdio.h> 
#define LEN 10 //定义从输入中获取10个字符 

char * getnchar(char * str, int n); //定义储存函数,返回参数为char类型指针 

int main(void)
{
	char input[LEN];//存储字符串的数组     
	char *check;

	puts("please enter the string which characters size below 10:");
	check = getnchar(input, LEN - 1);//返回存储数组的首字符地址     
	if (check == NULL) //如果返回的是空指针        
		puts("Input failed.");
	else
		puts(input);
	puts("Done.\n");

	return 0;
}
char * getnchar(char * str, int n)
{
	int i;
	char ch;

	//1.开始把输入的字符赋值给数组
	for (i = 0; i < n; i++)//读取9个字符,超过跳出。     
	{
		ch = getchar();
		if (ch != EOF && ch != ' ' && ch != '\n' && ch != '\t')//从键盘的输入赋值给ch不是特殊字符,就赋值给数组
		{
			str[i] = ch;
		}
		else        //读取到文件结尾,空白,换行符,制表符结束      
		{
			break;
		}
	}

	//2.对尾部的结束进行判断
	if (ch == EOF)     //如果读到文件结尾,则说明未读取10个字符    
		return NULL;   //返回空指针  
	else
	{
		str[i] = '\0';  //添加字符串空字符(\0)       
		return str;     //返回指针名 
	}
}

11.3

第一种

直接输入一窜字符,利用指针差,得到空白字符的位置,换为‘\0’,结束,打印空字符之前的字符串

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

#define N 80

void getword(char * st);
char *s_gets(char *st, int n);

int main(int argc, char *argv[])
{
	char input[N];

	s_gets(input, N);//人为输入字符
	getword(input); //捕获不为空,下面输出
		puts(input);
	puts("Done.\n");

	return 0;


}

void getword(char *st)
{
	
	char *ch = st;
	while (!isspace(*ch++));//不是空白字符继续往下读取(下找),空白字符为真,‘ !’取反为假跳出循环,此时'ch'找到空白字符

	//st数组名相当于首地址指向字符串开头
	//ch此时指向空白字符位置,地址差即为此时空白字符的位置(相当于偏移量)
	st[ch - st] = '\0';//数组方式不需要加*,且为[]方括号形式

}

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

	ret_val = fgets(st, n, stdin);
	if (ret_val != NULL)
	{
		int i = 0;
		while (st[i] != '\n' && st[i] != '\0')
		{
			i++;
		}

		if (st[i] == '\n')
		{
			st[i] = '\0';
		}
		else
			while (getchar() != '\n')
			{
				continue;
			}
	}
	return ret_val;
}

在这里插入图片描述

第二种

一个一个的获取从键盘输入的字符,然后赋值给数组,对开头、中间、结尾进行判断。

#include <stdio.h>
#include <ctype.h> //判断空白字符头文件 
#define LEN 80 

char *getword(char *st);

int main(void)
{
	char input[LEN];
	char *ch;

	while ((getword(input)) != NULL)//返回的char类型指针地址不为空
	{
		puts(input);
	}
	puts("Done.\n");

	return 0;
}

char *getword(char *st)
{
	int ch;//字符型数据与整型数据之间可以通用
	char *a = st;//用一个指针变量接收数组首地址,会方便


	while ((ch = getchar()) != NULL && isspace(ch))//开头判断输入的是不是特殊字符等,跳过
	{
		continue;
	}
	//1.跳过特殊字符的第一个是不是正常字符
	if (ch == EOF)
	{
		return NULL;
	}
	else
	{
		//*st++ :先取值,在++指向下一个
		*st++ = ch;//先把跳过特殊字符的第一个正常字符给了数组第一个元素
	}


	//2.第一个字符OK,后面的持续赋值给数组
	while ((ch = getchar()) != NULL && !isspace(ch))//为空字符就停止
	{
		*st++ = ch;
	}
	*st = '\0'; //ch赋值结束,数组最后一个位置给空字符,添加单词字符串结尾空字符 

	//3.输入的字符赋值结束后,上诉已经为结尾赋予空字符,所以此处只需呀判断是否读取到空或者 丢弃掉剩余字符
	if (ch == EOF)
	{
		return NULL;
	}
	else
	{
		while (ch != '\n')
		{
			ch = getchar();//舍弃剩下的字符,
		}
		return a;
	}
}

11.4

第一种

直接在定义中给定允许输入字符大小。

从我们输入到数组中的字符串中(s_gets负责接收我们的输入),找到我们输入的单个字符,且返回地址信息。

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

#define N 80


char *s_gets(char *st, int n);
char *findfirst(char st[], char ch);

int main(int argc, char *argv[])
{
	char input[N];
	char ch;
	char *pt;

	while (( s_gets(input, N) != NULL ) && ( input[0] != '\0'))
	{
		puts("请输入一个你想找的字符:");
		ch = getchar();

		while (getchar() != '\n');//消耗掉回车,只取出字符串的第一个字符

		pt = findfirst(input, ch);//找到了会返回一个指针,没有为空
		if (pt == NULL)
		{
			puts("为空。");
		}
		else
		{
			printf("找到的字符是%c,位置%p",ch, pt);
		}

	}
	
		
	puts("Done.\n");

	return 0;


}

char *findfirst(char st[], char ch)
{
	while (*st != '\0')
	{
		if (*st++ == ch)//st每次都需要跟新位置,去和我们输入的字符比较判断
		{
			return st;//找到了,返回当前数组元素所在位置的地址信息
		}
				
	}
	return NULL;//未找到
}


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

	ret_val = fgets(st, n, stdin);
	if (ret_val != NULL)
	{
		int i = 0;
		while (st[i] != '\n' && st[i] != '\0')
		{
			i++;
		}

		if (st[i] == '\n')
		{
			st[i] = '\0';
		}
		else
			while (getchar() != '\n')
			{
				continue;
			}
	}
	return ret_val;
}

第二种

输入一个允许的最大个数,且在捕获字符的函数中,定义一个整形常量,做元素个数赋值统计。
当它大于允许最大个数时,判断失效。

输出我们允许的多少个字符串

#include <stdio.h>
#include <ctype.h> //判断空白字符头文件 
#define LEN 80 

char *getword(char *st, int n);//定义存储字符的函数 

int main(void)
{
	char input[LEN];
	char *ch;
	int n;
	printf("please enter maxium number :\n");
	scanf("%d", &n);

	while ((getword(input, n)) != NULL)//返回的char类型指针地址不为空
	{
		puts(input);
		printf("please enter maxium number :\n");
		scanf("%d", &n);
		puts("please enter the string:");
	}
	puts("Done.\n");

	return 0;
}

char *getword(char *st, int n)
{
	int ch;//字符型数据与整型数据之间可以通用
	char *pt = st;//用一个指针变量接收数组首地址,会方便
	int m = 0;

	while ((ch = getchar()) != NULL && isspace(ch))//输入的是特殊字符等,跳过
	{
		continue;
	}
	//1.跳过特殊字符的第一个是不是正常字符
	if (ch == EOF)
	{
		return NULL;
	}
	else
	{
		//*st++ :先取值,在++指向下一个
		*st++ = ch;//先把跳过特殊字符的第一个正常字符给了数组第一个元素
		m++;
	}


	//2.第一个字符OK,后面的持续赋值给数组
	while ((ch = getchar()) != NULL && !isspace(ch) && m < n)
	{
		*st++ = ch;
		m++;//字符数不可以大于允许数***
	}
	*st = '\0'; //ch赋值结束,数组最后一个位置给空字符,添加单词字符串结尾空字符 

	//3.输入的字符赋值结束后,上诉已经为结尾赋予空字符,所以此处只需呀判断是否读取到空或者 丢弃掉剩余字符
	if (ch == EOF)
	{
		return NULL;
	}
	else
	{
		while (ch != '\n')
		{
			ch = getchar();//舍弃剩下的字符,
		}
		return pt;
	}
}

11.5

与11.4的第一种方法异曲同工

#include <stdio.h>
#include <string.h> 
#define LEN 80 

char *get_position(char *str, char a);

int main(void)
{
	char str[LEN];
	char a;
	char *strback;

	puts("please enter the string:");
	while (fgets(str, LEN, stdin) && str[0] != '\0')
	{
		puts("what character/字符 are you looking for?");
		a = getchar();//获取想查找的单独字符

		while (getchar() != '\n')
			continue;
		//清空缓冲区,如果没有这一条语句,缓冲区会还剩一个换行符。
			//第二次循环fgets()语句读到这个换行符就结束了 
			//还有一个作用舍弃多输入的字符。 
	
		strback = get_position(str, a);
		if (strback != NULL)
		{
			puts("the character and its address:");
			putchar(*strback);
			printf("%p\n", strback);
		}
		else
		{
			puts("该字符不会出现在字符串中!");
			puts("please enter the next string:");
		}
	}


	return 0;
}

char *get_position(char *str, char a)
{
	while (*str != '\0')
	{
		if (*str++ == a) //不断比较,相同就返回该处的指针
			return str;

	}
	return NULL;

}

11.6

自定义bool类型,查找字符在字符串中是否存在,返回0、1

人为输入字符串,和要查找的字符。
通过布尔类型函数的返回值判断字符存在否。

#include <stdio.h> 
#include <string.h> 
#include <stdbool.h>
#define LEN 80 

#ifndef __cplusplus //在C语言中使用bool类型,可以自己定义

typedef char bool;
#define false 0
#define true  1

#endif

bool is_within(const char * str, char c); //定义查找字符是否在字符串中的函数 
char * s_gets(char * st, int n);//定义一个自定义的输入函数 

int main(void)
{
	char input[LEN];
	char ch;
	int found;

	puts("Enter a string:");
	while (s_gets(input, LEN) && input[0] != '\0')
	{
		puts("Enter a character: ");
		ch = getchar();

		while (getchar() != '\n')//清空缓冲区
			continue;

		found = is_within(input, ch);
		if (found == 0)
		{
			printf("%c not found in string.\n", ch);
		}
		else
			printf("%c found in string %s\n", ch, input);
		puts("Next string: ");


	}
	puts("Done.\n");
	return 0;
}

bool is_within(const char *st, char ch)
{
	while (*st != ch && *st != '\0')
		st++;

	return *st;//如果知道指针指向\0时都没有找到指定字符的时候,将返回空字符的值为0 
}

char * s_gets(char * st, int n) //定义一个自定义的输入函数 
{
	char * ret_val;
	char * find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');   // 返回指向下一行的首字符的指针        
		if (find)                  // 如果该指针不是空指针,             
			*find = '\0';          // 添上一个空字符表示字符串输入完毕        
		else
			while (getchar() != '\n')//清空缓冲区                 
				continue;
	}
	return ret_val;
}

11.7

利用赋值的方式,取出数组a中元素赋值给数组b,人为输入限定大小,n减减至0结束赋值,且给受拷贝的数组b最后添加上空字符

#include <stdio.h>
#define SIZE 30 

char *mystrncpy(char *a, char *b, int n);

int main(int argc, char *argv[])
{
	char a[SIZE];
	char b[SIZE];
	int len;

	puts("please enter a string to copy:");
	while (fgets(a, SIZE, stdin) && a[0] != '\0')
	{
		puts("please enter the length you want to capture:");
		scanf("%d", &len);

		getchar();//清除scanf当中产生的换行符!
		mystrncpy( b, a, len);
		//a人为输入字符串,拷贝给b,拷贝len个字符
		puts("数组a现在是:");
		puts(a);
		puts("数组b现在是:");
		puts(b);
		puts("please enter the next string:");
	}


	return 0;
}

char *mystrncpy( char *b, char *a, int n)
{
	while (n--)//从a中拷贝n个字符到b,直到可拷贝数量为0停
	{
		*b = *a;
		a++;
		//不断指向下一个位置
		b++;
	}
	//可拷贝大小结束
	if (n <= 0)
	{
		*b = '\0';
		//n个字符拷贝结束,为b添加上空字符,结束拷贝~
	}
	return (char*)b;
	//拷贝返回char类型指针,同strncpy类型
}

11.8

一、仅仅判断第二个字符包含于第一个字符中与否

输入第一串字符,输入第二串字符,第二串与第一串字符串进行单独的字符比较,当二在一中被包含,返回这两个字符串首地址信息,否则重新输入第二串字符串。

可以依次进行两个数组的数组元素比较,元素个数++, pt数组与str数组元素相同, 继续下一个字符比较, 当不相同的时候, str数组从当前第二个字符(元素)开始-------作为新的第一个字符,再次去与pt数组的初始字符比较。

比较的元素个数==pt数组长度,说明比较结束,可以返回当前的str数组首地址了。

#include <stdio.h>
#include <string.h>
#define LEN 20

char *s_gets(char *st, int n);
char *string_in(char *str, char *pt);

int main(int argc, char *argv[])
{
	char str1[LEN];
	char str2[LEN];

	printf("请输入第1串字符串(换行结束输入):\n");
	while (s_gets(str1, LEN) && (*str1 != '\0'))
	{
		printf("Your input: \"%s\"\n", str1);
		printf("请输入第2串字符串:\n");
		if (s_gets(str2, LEN) && (*str2 != '\0'))
		{
			  //开始判断
			if (string_in(str1, str2))
			{
				printf("The rest:\n");
				printf("字符串%s在字符串%s中\n", str2, str1);
			}
			else
			{
				printf("No such string,\n");
				printf("字符串%s不在字符串%s中\n", str2, str1);
			}
			printf("您可以再次输入2串字符串(或换行退出):\n");
			  //输入的第二个字符串不在第一个字符串中
		}
	}
	printf("本程序完成!\n");

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

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
		{
			*find = '\0';
		}
		else
		{
			while (getchar() != '\n')
				continue;
		}
	}
	return ret_val;
}

char *string_in(char *str, char * pt)
{
	int i = 0;
	int j = 0;

	int str_len = strlen(str);
	int pt_len = strlen(pt);

	while (i < str_len && j < pt_len) //统计数(数组元素个数) < 字符串长度
	{
		if (str[i] == pt[j])
		{
			i++;
			j++;
			//如果字符相同则两个字符都增加;数组元素相同,继续下一个字符比较
		}
		else
		{
			i = i - j + 1; 
			//当前第一个字符str[i]与pt[j]不同,从~当前~第二个字符开始比较
			j = 0; 
			//pt[j] : 第二个数组的元素重新从字符串第一个字符开始
		}
	}

	return j == pt_len ? str : NULL; 
									//加加的元素个数 == 字符串长度 :pt数组都可以遍历完成或者说pt数组遍历完毕(~匹配成功)
	                           //那么此时可以返回当前str数组中第一个字符-与-pt数组中第一个字符(初始字符)相同的字符地址
						   //此时的str虽说是与pt初始字符相同的字符地址,不过也算是数组的‘首地址’,因此返回str即可
						//可以返回地址信息,自然说明了第二个字符串含于第一个字符串喽
}


  /*	return j == pt_len ? str\pt : NULL; 
  		j++统计数组pt的元素下标个数,当j的个数==其数组长度的时候,
	说明在str数组中对与pt数组中相同的字符遍历完成;因为若是str数
	组中的字符与pt中的字符不等,j会从新开始统计。
		既然可以遍历完成,那么pt字符肯定在str中存在,此时renturn 
	str还是pt都不无可以。==》2020-12-3-14点49分再次重新理解(广东
	珠海)
    */

返回pt首地址:
在这里插入图片描述
返回str首地址:
在这里插入图片描述

二、二字符在一字符中包含,且报出此时的i、j指向一、二字符的位子 和 二字符在一字符中的位置

#include <stdio.h>
#include <string.h>
#define LEN 20

char *s_gets(char *st, int n);
char *string_in(char *str, char *pt);
int is_in(char *s, char *c, int location[]);

int main(int argc, char *argv[])
{
	char str1[LEN];
	char str2[LEN];
	int loc[250] = { 0 };
	 //额外定义一个数组去保存统计的位置信息
	int *location = loc;
     //使用指针变量方便操作
      
	printf("请输入第1串字符串(换行结束输入):\n");
	while (s_gets(str1, LEN) && (*str1 != '\0'))
	{
		printf("请输入第2串字符串:\n");
		if (s_gets(str2, LEN) && (*str2 != '\0'))
		{
			  //开始判断
			if (string_in(str1, str2))
			{
				printf("字符串%s在字符串%s中\n", str2, str1);
				if (is_in(str1, str2, location) == 1) //开始判断查字符串在原字符串中的位置
				{
					printf("原文件包含比较字符串\n");
					              		//新数组中包含了几个数据信息,就循环几次
					for (int i = 0; i < sizeof(location); i++)
					{
						if (location[i] != 0) //待查字符串在原字符串中不为空
						{
							printf("所在的位置:%d\n", location[i]);
						}
					}
				}
			}
			else
			{
				printf("字符串%s不在字符串%s中\n", str2, str1);
			}
			printf("您可以再次输入2串字符串(或换行退出):\n");
			  //输入的第二个字符串不在第一个字符串中
		}
	}
	printf("本程序完成!\n");

	return 0;
}

char *string_in(char *str, char * pt)
{
	int i = 0;
	int j = 0;

	int str_len = strlen(str);
	int pt_len = strlen(pt);

	while (i < str_len && j < pt_len) //统计数(数组元素个数) < 字符串长度
	{
		if (str[i] == pt[j])
		{
			i++;
			j++;
			//数组元素相同,继续下一个字符比较
		}
		else
		{
			i = i - j + 1; 
			//当前第一个字符str[i]与pt[j]不同,从~当前~第二个字符开始比较
			j = 0; 
			//pt[j] : 第二个数组的元素重新从字符串第一个字符开始
		}
	}

	return j == pt_len ? str : NULL; //加加的元素个数 == 字符串长度 :pt数组都可以遍历完成或者说pt数组遍历完毕
	                           //那么此时可以返回当前str数组中第一个字符~与pt数组中第一个字符(初始字符)相同的字符地址
						   //此时的str虽说是与pt初始字符相同的字符地址,不过也算是数组的‘首地址’,因此返回str即可
}

// 子函数
int is_in(char *s, char *c, int location[])
{
	int i = 0, j = 0;
	int flag = -1;//先让其为假
	int firstW = 0;
	int num = 0;
	
	//同上诉初始操作一样
	while (i < strlen(s) && j < strlen(c)) // s:原字符串,c: 比较字符串
	{
		if (s[i] == c[j]) // 指针所指位置的字符
		{                 //如果字符相同则两个字符都增加
			i++;
			j++;
		}
		else
		{
			i = i - j + 1; //主串字符回到比较 最开始比较的 后一个字符
			j = 0;         //字串字符重新开始
		}

		if (j == strlen(c)) //如果匹配成功
		{
			flag = 1; //字串出现
			//i-strlen(c) 比较字符在原字符串中第一次出现的位置(中文字符再+2, 英文+1可手动计算验证)
			printf("此时原字符串指针i的位置 %d\n", i);
			printf("此时比较字符串指针j的位置 %d\n", j);
			printf("比较字符串在原字符串中第一次出现的位置 %d\n\n", i - strlen(c) + 1); // i-strlen(c)+2 : 中文字符是+2
			location[num] = i - strlen(c) + 1;
			//将得出的位置数据存进新数组内
			num++;//存了几次统计一下
			j = 0; //第二个数组每次都重新读取
			continue;

		}
	}

	return flag; //统计完存在肯定返回真了呗
	
}
char *s_gets(char *st, int n)
{
	char *ret_val;
	char *find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
		{
			*find = '\0';
		}
		else
		{
			while (getchar() != '\n')
				continue;
		}
	}
	return ret_val;
}

在这里插入图片描述

11.9

简易二分法实现思想

#include <stdio.h>
#include <string.h>
#define LEN 20

char *s_gets(char *st, int n);
void reverse(char *str);

int main(int argc, char *argv[])
{
	char input[LEN];
	printf("请输入一串字符串(只读取前%d个字符):\n", LEN-1);
	while (s_gets(input, LEN) && (*input != '\0'))
	{
		printf("此字符串是:\n");
		puts(input);
		reverse(input);
		printf("反序后字符串是:\n");
		puts(input);
		printf("您可以再次输入一串字符串(或换行退出):\n");
	}
	printf("本程序完成!\n");


	return 0;
}

//简易二分法操作,九章有类似习题(个人附有专项二分法例子)
void reverse(char *str)
{
	int i;
	char temp;

	for (i = 0; i < sizeof(str) / 2; i++)
	{
		temp = str[i];
		str[i] = str[strlen(str) - 1 - i]; //交换前的数组元素最后一个赋值给第一个
		str[strlen(str) - 1 - i] = temp;
	}

	return;

}

11.10

第一种

将数组的首地址赋值给一个指针,判断该指针指向了空格与否,有指向—将其指向的下一个位置的值,赋给当前指向的位置,然后++继续指向下一个位置;

若pt没指到空格‘ ’,那么数组地址++。

#include<stdio.h>
#define LENGTH 20
char* s_gets(char* st, int n);
void d_blank(char* st);
int main(void)
{
	char string[LENGTH];

	printf("Please enter some text(empty line to quit).\n");
	while (s_gets(string, LENGTH) && *string != '\0')
	{
		printf("Original String: \n\"%s\"\n", string);
		d_blank(string);
		printf("Remove Space: \n\"%s\"\n", string);
		printf("\nEnter other string(empty line to quit).\n");
	}
	printf("bye\n");

	return 0;
}

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

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		while (*st != '\n' && *st != '\0')
			st++;
		if (*st == '\n')
			* st = '\0';
		else
			while (getchar() != '\n')
				continue;
	}

	return ret_val;
}

void d_blank(char* st)
{
	char* p;

	while (*st != '\0')
	{
		p = st;
		/*↑修改pt指向的内容就相当
            于修改了str所指向的内容;*/

		if (*p == ' ') //是空格就把下一个字符赋值到当前空格所在位置
		{
			while (*p != '\0')
			{
				*p = *(p + 1);
				p++;//继续指向下一个字符
			}
		}
		else
			st++; //不是空格就继续指向下一个字符
	}
}

第二种

str不是空格的时候,把地址上的值赋给pt,否则str++且统计一下空格数量;
str把地址信息赋值给pt,此时二者地址上的信息是一样的;

*pt = *str,此举是重新覆盖掉pt地址上的数据,以达到消除空格的操作。

在把有效字符覆盖到pt所指向的地址上的数据后,会有最后两个位置(一个空格、一个字符)多余,因此count–,且赋值给这两个位置’\0’。

最后:
在这里插入图片描述

#include <stdio.h>
#include <string.h>
#define LEN 20
#define SPACE ' '

char *s_gets(char *st, int n);
void delete_space(char *str); //接收数组的地址信息,删除掉存储在数组中的字符串中的空格

int main(int argc, char *argv[])
{
	char source[LEN];

	printf("请输入一串字符(只读取前%d个字符)\n", LEN -1);
	while (s_gets(source, LEN) && source[0] != '\0')
	{
		puts("源字符串:");
		puts(source);
		puts("-----------------");

		delete_space(source);
		puts("删除空格后的字符串:");
		puts(source);
		puts("您可以再次输入一串字符串(或换行退出):\n");
	}
	printf("本程序完成!\n");

	return 0;
}

void delete_space(char *str)
{
	int count = 0;
	char *pt = str;

	while (*str)
	{
		if (*str != SPACE)//1.此处仅处理了非空格字符的操作
		{
			*pt++ = *str++;
			/*↑修改pt指向的内容就相当
		   于修改了str所指向的内容;*/
		}
		else 
		{
			str++;
			count++;			
			/*↑若是空格则统计空格数并
		   指向下一个内存空间去赋值,空格跳过不做赋值操作;*/
		}
		/*int ret = count;
		printf("有%d个空格\n", ret);*/
	}

	while (count--)
	{
		*pt++ = '\0';
		//↑删除空格后在末尾覆盖原有字符;
	   //↑并且清除剩余字符;
	}
	
	return;
}

char *s_gets(char *st, int n)
{
	char *ret_val;
	char *find;


	ret_val = fgets(st, n ,stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
		{
			*find = '\0';
		}
		else
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

11.11

对按照ASCII码排序,可以使用strcmp函数做判断功效,实现可以使用冒泡排序同时加深对冒泡排序的理解。

int word(char *str);第一个单词字符长度的计算中的bool布尔判断,可加可不加

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#define ROWS 10
#define COLUMNS 50


int get_string(char string[][COLUMNS], char *str[], int n);
int get_choice(void);
int get_first(void);

char *s_gets(char *st, int n);
int word(char *str);

void origin_output(char string[][COLUMNS], int n);
void ascll_output(char *str[], int n);
	//char *str[ROWS];中每个元素都是一个指向char类型的指针,所以此处用地址的地址来指向这些char *类型的指针
	
void length_up_output(char *str[], int n);
void first_word_output(char *str[], int n);

int main(void)
{
	int n, choice;

	char *str[ROWS];//每个元素都是一个指向char类型的指针
	  //"字符串"本就相当于一个指针,现在可以有10个这样的字符串
	char string[ROWS][COLUMNS];
	   //存储我们的输入,赋值给str

	printf("请输入%d串(行)字符串(或遇EOF结束读取):\n", ROWS);
	if (n = get_string(string, str, ROWS))
	{
		while ((choice = get_choice()) != 'q')
		{
			switch (choice)
			{
				case 'a':
				{
					origin_output(string, n);
					break;
				}
				case 'b':
				{
					ascll_output(str, n);
					break;
				}
				case 'c':
				{
					length_up_output(str, n);
					break;
				}
				case 'd':
				{
					first_word_output(str, n);
					break;
				}
				default:
					break;

			}

		}

	}

	printf("本程序完成!\n");
	return 0;
}



int get_string(char string[][COLUMNS], char *str[], int n)
{
	int i;

	for (i = 0; i < n; i++)//一行算作一个字符串
	{
		if (s_gets(string[i], COLUMNS))//每行(二维数组中)输入多少个(列)字符
		{
			str[i] = string[i];//每行字符串赋值给str

		}
		else
			break;

	}

	return i;
}

int get_first(void)
{
	int ch;

	do
	{
		ch = towlower(getchar());
	} while (isspace(ch));

	while (getchar() != '\n') //仅仅获取一个字符,剩下的丢弃
	{
		continue;
	}

	return ch;
}

int get_choice(void)
{
	int ch;
	printf("=======================================\n");
	printf("a)打印源字符串列表\n");
	printf("b)以ASCII中的顺序打印字符串\n");
	printf("c)按长度递增顺序打印字符串\n");
	printf("d)按字符串中第一个单词长度打印字符串\n");
	printf("q)退出\n");
	printf("=======================================\n");
	printf("请您输入选择:");

	ch = get_first();

	while ((ch != 'a') && (ch != 'b') && (ch != 'c') && (ch != 'd') && (ch != 'q'))
	{
		printf("输入无效!请输入a,b,c,d或q:");
		ch = get_first();

	}
	return ch;
}

void origin_output(char string[][COLUMNS], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		puts(string[i]);

	}

	putchar('\n');
	return;
}

		//1.ASCII码排序(第一个字符)
void ascll_output(char *str[], int n)
{
	int i, j;
	char *temp;

			//这样理解比如11个数0-10,i是0-9,j是1-10
			//↓永远是前一个与后一个比较
	for (i = 0; i < n-1; i++) 
	{
		for (j = i+1; j < n; j++)
		{
				//↓按ASCII码顺序进行排序;
				//strcmp函数完美满足需求 : >0 说明i 在j的后面
			if (strcmp(str[i], str[j]) > 0)
			{
				temp = str[i];
				str[i] = str[j];
				str[j] = temp;
			}

		}
	}

	printf("以ASCII中的顺序(从小到大)打印%d串字符串:\n", n);
	for (i = 0; i < n; i++)
	{
		puts(str[i]);

	}
	putchar('\n');
	return;

}

		//全部字符的长度排序
void length_up_output(char *str[], int n)
{
	int i, j;
	char *temp;
	for (i = 0; i < n - 1; i++)
	{
		for (j = i+1; j < n; j++)
		{
				//↓按字符串中字符数的多少进行排序;
			if (strlen(str[i]) > strlen(str[j]))
			{
				temp = str[i];
				str[i] = str[j];
				str[j] = temp;

			}

		}

	}

	printf("按长度递增顺序打印%d串字符串:\n", n);
	for ( i = 0; i < n; i++)
	{
		puts(str[i]);

	}
	putchar('\n');
	return;
}


	//第一个单词长度计算
int word(char *str) //接收一维数组的地址信息(一行一行比较)
{
	int lenght = 0;
	bool inword = false;

	/*↓统计字符串第一个非空白字符的单词
		长度并作为返回值传递给调用函数;*/
	while (*str)
	{
		
		if (!isspace(*str)/* && !inword*/)
		{
			/*↑从第一个非空白字符
				开始统计单词长度*/
			//inword = true;
			lenght++;

		}
		//else if (!isspace(*str) && inword)
		//{
		//	lenght++;
		//}
		else if (isspace(*str))
		{
			/*↑若遇到第一个单词后的空白符
		   则退出循环*/
			break;

		}
				
		str++; //不是空格,进入第一个if,长度加一次,然后str再指向下一个地址,再进入if判断一下
	}

	return lenght;
}

  //按照第一个单词长度排序
void first_word_output(char *str[], int n) //str二维数组首地址(x行y列)、*str第一行一维数组首地址(1行y列)、**str(一维数组的第一个元素的地址)
{
	int i, j;
	char *temp;

	for (i = 0; i < n - 1; i++)
	{
		for (j = i + 1; j < n; j++)
		{
			//↓按第一个单词长度进行排序;
			if (word(str[i]) > word(str[j]))
			{
				temp = str[i];
				str[i] = str[j];
				str[j] = temp;

			}
		}
	}

	printf("按字符串中第一个单词长度(从小到大)打印%d串字符串:\n", n);
	for (i = 0; i < n; i++)
	{
		puts(str[i]);

	}
	putchar('\n');
	return;

}


char *s_gets(char *st, int n)
{
	char *ret_val;
	char *find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
		{
			*find = '\0';
		}
		else
		{
			while (getchar() != '\n')
				continue;
		}
	}
	return ret_val;
}

11.12

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

int main(int argc, char *argv[])
{
	int ch;
	int lower;
	int upper;
	int digit;
	int punct;
	int words;

	lower = upper = digit = 0;
	punct = words = 0;

	bool inword = false;

	printf("请输入一些字符(遇EOF结束):\n");
	while ((ch = getchar()) != EOF)
	{
		if (islower(ch))
		{
			lower++;
		}
		else if (isupper(ch))
		{
			upper++;
		}
		else if (ispunct(ch))
		{
			punct++;
		}
		else if (isdigit(ch))
		{
			digit++;
		}
		if (!isspace(ch) && !inword)
		{
			inword = true;
			words++;
		}
		if (isspace(ch) && inword)
		{
			inword = false;
		}


	}
	printf("单词:%d个\n", words);
	printf("小写字母:%d个\n", lower);
	printf("大写字母:%d个\n", upper);
	printf("数字:%d个\n", digit);
	printf("标点符号:%d个\n", punct);



	return 0;
}

11.13

注意两种运算器下的运行

正序:从开头i=初始值输出;i < argc;i++
倒叙:从结尾-1处输出;i > 0; i–

Linux下一个空格结束,就相当于一个命令行输入完成

#include <stdio.h>
#include <string.h>
#define ROW 20
#define COL 20

char *s_gets(char *st, int n);

int main(int argc, char *argv[])
{
	int i = 0;
	
	printf("本程序名称%s.\n", argv[i]); 
		//字符串的第一行是程序名称,例如:main.c; 之后才是我们想要输出的信息

	if (argc < 2) //直有程序名称而已
	{
		printf("命令行参数中没有单词!\n");
	}
	else
	{
	//Linux下一个空格结束,就相当于一个命令行输入完成
		puts("原单词是:");
		for (i = 1; i < argc; i++)
		{
			 //从第一个单词输出
			printf("%s", argv[i]);

		}
		printf("\n反序显示原单词是:\n");
		for (i = argc -1; i > 0; i--)
		{
			//之前是从第一个命令行输出,现在从最后一个输出
			//不是字符前后交换,不会改变字符顺序,不要理解错误
			printf("%s", argv[i]);
		}
		putchar('\n');
	}


	return 0;
}

Linux下运行(通过命令行运行的程序最好在此环境下运行)

在这里插入图片描述
图中,有五个命令行
./main
i
love
you
lei

vs2017下运行

在这里插入图片描述

11.14

利用for循环,指数exp作为条件判断值,在实现中不断的乘以num

命令行需要有三个:文件名、浮点数、指数次幂

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

int main(int argc, char *argv[])
{
	int i, exp;
	double num, sum;
	sum = 1.0;

	if (argc != 3)
	{
		 //命令行需要有三个:文件名、浮点数、指数次幂
		printf("参数错误!无法计算幂!\n");
	}
	else
	{
		num = atof(argv[1]);
		exp = atoi(argv[2]);

		for (i = 1 ; i < exp; i++) //循环exp次(指数)
		{
			 //开始计算num的exp次,不断的乘以自己本身
			sum *= num;

		}
		printf("%g的%d次方是%g.\n", num, exp, sum);
	}


	return 0;
}

atoi()函数
https://blog.csdn.net/CLZHIT/article/details/104041529?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160687882319724813243533%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=160687882319724813243533&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-1-104041529.first_rank_v2_rank_v28p2&utm_term=atoi%E5%87%BD%E6%95%B0&spm=1018.2118.3001.4449

atof ( ) 函数
https://blog.csdn.net/weixin_43809563/article/details/104564203?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160687871119215668869363%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=160687871119215668869363&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-1-104564203.first_rank_v2_rank_v28p2&utm_term=atof%E5%87%BD%E6%95%B0&spm=1018.2118.3001.4449
在这里插入图片描述
上述图中->
main:是第一行命令行、
6:第二行、
2:第三行命令行

11.15

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LEN 10

char *s_gets(char *st, int n);
int myatoi(char *str);

int main(int argc, char *argv[])
{
	char input[LEN];

	printf("请输入一串字符串(只读取前%d个字符):\n", LEN - 1);//为‘\0’留出位置
	while (s_gets(input, LEN) && (input[0] != '\0') )
	{
		printf("字符串%s转换成整数是%d\n", input, myatoi(input));
		printf("您可以再次输入一串字符串(或换行退出):\n");

	}
	printf("本程序完成!\n");

	return 0;
}

int myatoi(char *str)
{
	int i;
	int n = 0;

	for (i = 0; i < strlen(str); i++)
	{
		if (!isdigit(str[i]))
		{
			return 0;

		}
		else
		{
			//算法分栏有验算图解
			n = n * 10 + (str[i] - '0');
			printf("str[i] - '0' = %d", str[i] - '0');

		}
	}
	return n; 
	//返回转换完成的整数

}

char *s_gets(char *st, int n)
{
	char *ret_val;
	char *find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
		{
			*find = '\0';
		}
		else
		{
			while (getchar() != '\n')
				continue;
		}
	}
	return ret_val;
}

在这里插入图片描述

11.16

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

int main(int argc, char *argv[])
{
    int ch;
    int flag = 1;
    char mode = 'p';

    if (argc > 2) //命令行仅包含文件名与我们的输入的单个字符
    {
        printf("命令行参数无效!\n");
        flag = 0;

    }
    else if (argc == 2) //只显示有文件名 和 我们输入的三个字符的其中一个,分别位于的行为0、1
    {
        if (argv[1][0] != '-')
        {
        		//命令行第二行的第一个字符
            printf("命令行参数输入前要加'-'!\n");
            flag = 0;

        }
        else
        {
            switch (argv[1][1])
            {
            	 //命令行第二行的第二个字符
                case 'p':
                case 'u':
                case 'l':
                {
                    mode = argv[1][1];
                    break;
                }
                default:
                {
                    puts("命令行参数无效!程序将使用-p方式运行!");

                }


            }


        }
    }

    if (flag)
    {
        printf("请输入一些字符(遇EOF停止读取):\n");
        while (( ch = getchar())!= EOF)
        {
            switch (mode)
            {
                case 'p':
                {
                    putchar(ch);
                    break;
                }
                case 'u':
                {
                    putchar(toupper(ch));
                    break;
                }
                case 'l':
                {
                    putchar(tolower(ch));
                    break;
                }

            }

        }

    }

    printf("本程序完成!\n");

    return 0;
}

在这里插入图片描述
命令行一:./main
命令行二:-u

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扳手的海角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值