第十一章 字符串和字符串函数
编程练习
设计并测试一个函数,可以输入读取n个字符(包括空格、制表符、换行符),把结果存储在一个数组中,这个数组的地址通过参数来传递。
#include <stdio.h>
#define LEN 80
char * getch(char a[], int n);
int main(void)
{
char a[LEN];
if (getch(a, 4))
puts(a);
else
printf("没有读取\n");
return 0;
}
char * getch(char a[], int n)
{
int i;
for (i = 0; i < n; i++)
{
a[i] = getchar();
if (EOF == a[i])
{
a[i] = '\0';
break;
}
}
a[i] = '\0';
if (!a[0])
return NULL;
return a;
}
2.修改编程练习1中的函数,使得可以在N个字符后,或第一个空格、制表、换行符后停止读取输入,由上述情况中最先满足的那个终止读取(不能用scanf()函数)。
#include <stdio.h>
#include <ctype.h>
#define LEN 80
char * getch(char a[], int n);
int main(void)
{
char a[LEN];
if (getch(a, 6))
puts(a);
else
printf("没有读取\n");
return 0;
}
char* getch(char a[], int n)
{
int i;
for (i = 0; i < n; i++)
{
a[i] = getchar();
if (EOF == a[i] || isspace(a[i]))
{
a[i] = '\0';
break;
}
}
a[i] = '\0';
if ('\0' == a[0])
return NULL;
return a;
}
3.设计并测试一个函数,其功能是读取输入行里的第一个单词到数组,并丟掉该行中其它的字符。
一个单词的定义是一个字符串,其中不含空格、制表符和换行符
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h> //不支持bool,可以返回int类型 0 或 1
bool getword(char * );
int main(void)
{
char array[20];
if (getword(array))
puts(array);
else
puts("没有读取到单词。");
return 0;
}
bool getword(char * array)
{
char ch;
int a = 0;
char * p = array;
while ((ch = getchar()) != '\n')
{
//怱略一行开始处的空格。
if (a == 0 && isspace(ch))
continue;
else
a = 1;
if (!isspace(ch))
*array++ = ch;
else
break;
}
*array = '\0';
if (*p == '\0')
return false;
return true;
}
4.设计并测试一个函数,其功能是搜索由第一个参数指定的字符串,在其中查找由函数的第二个参数指定的字符的第一次出现的位置。如果找到,返回指向这个字符的指针;如果没找返回空字符(这种方式和strchr()函数的功能一样)。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。
#include <stdio.h>
#define LEN 80
char * search(char *str, char ch);
int main(void)
{
char ch;
char target[LEN];
char * pstr;
puts("请输入字符串(在一行的开始处输入回车结束):");
while (gets(target) && target[0] != '\0')
{
puts("请输入字符:");
ch = getchar();
while (getchar() != '\n')
;
pstr = search(target, ch);
if (pstr == NULL)
printf("字符%c不在字符串中\n", ch);
else
printf("找到字符%c,它的地址为%p\n", ch, pstr);
puts("请输入下一个字符串(在一行的开始处输入回车结束:");
}
return 0;
}
char * search(char *str, char ch)
{
while (*str != '\0')
{
if (*str++ == ch)
return str;
}
return NULL;
}
5.编写一个函数is_within(),它接受两个参数,一个是字符,另一个是字符串指针。其功能是如果字符在字符串中,就返回一个非0值(真);如果字符不在字符串中,就返回0值(假)。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。
#include <stdio.h>
#define LEN 80
int search(char *str, char ch);
int main(void)
{
char ch;
char target[LEN];
puts("请输入源字符串(在一行的开始处输入回车结束):");
while (gets(target) && target[0] != '\0')
{
puts("请输入目标字符:");
ch = getchar();
while (getchar() != '\n')
;
if (search(target, ch))
printf("字符%c在字符串中\n", ch);
else
printf("字符%c不在字符串中\n", ch);
puts("请输入下一个源字符串(在一行的开始处输入回车结束:");
}
return 0;
}
int search(char *str, char ch)
{
while (*str != '\0' && *str != ch)
str++;
return *str;
}
6.strncpy(s1, s2, n)函数从s2复制n个字符给s1,并在必要时截断s2或为其填充额外的空字符。如果s2的长度等于或大于n,目标字符串没有标志结束的空字符。函数返回s1。自己编写这个函数,并在一个使用循环语句为这个函数提供输入的完整程序中进行测试。
#include <stdio.h>
#define LEN 80
char * strncpy1(char *, char *, int);
int main(void)
{
char str1[LEN], str2[LEN];
int n;
printf("请输入要复制的字符串:");
while (gets(str2))
{
printf("请输入要复制的字符个数:");
scanf("%d", &n);
strncpy1(str1, str2, n);
printf("复制的字符串:");
puts(str1);
printf("请输入要复制的字符串:");
while (getchar() != '\n')
;
}
return 0;
}
#include <string.h>
char * strncpy1(char *str1, char *str2, int n)
{
int l = strlen(str2);
int i;
if (l > n)
n = l;
for (i = 0; i < n; i++)
str1[i] = str2[i];
str1[i] = '\0';
return str1;
}
7.编写一个函数string_in(),它接受两个字符串指针参数。如果第二个字符串被包含在第一个字符串中,函数就返回被包含的字符串开始的地址。例如,string_in("hats", "at")返回hats中a的地址,否则,函数返回空指针。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。
#include <stdio.h>
#define LEN 80
char * string_in(char *, char *);
int main(void)
{
char str1[LEN], str2[LEN];
char * pstr;
printf("请输入被查找的字符串:");
while (gets(str1))
{
printf("请输入要查找的字符串:");
gets(str2);
pstr = string_in(str1, str2);
if (pstr != NULL)
{
printf("字符串已找到在内存中的地址为%p\n", pstr);
}
else
{
printf("未找到字符串。\n");
}
printf("请输入被查找的字符串:");
}
printf("结束!");
return 0;
}
#include <string.h>
char * string_in(char * str1, char * str2)
{
int len2 = strlen(str2);
int match;
int len1 = strlen(str1);
int i = len1 - len2 + 1;
if (i > 0)
{
while ((match = strncmp(str1, str2, len2)) && i-- )
{
str1++;
}
}
if(match)
return NULL;
else
return str1;
}
8.编写一个函数,其功能是使输入字符串反序。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。
#include <stdio.h>
#define LEN 80
char * antitone(char * pstr);
int main(void)
{
char str[LEN];
printf("请输入要反序的字符串:");
while (gets(str))
{
printf("反转后的字符串:");
puts(antitone(str));
printf("请输入要反序的字符串:");
}
printf("结束!\n");
return 0;
}
#include <string.h>
char * antitone(char * pstr)
{
int len = strlen(pstr) - 1;
int i;
char temp;
for (i=0, i<len - i; i++)
{
temp = pstr[len - i];
pstr[len - i] = pstr[i];
pstr[i] = temp;
}
return pstr;
}
9.编写一个函数,其参数为一个字符串,函数删除字符串中的空格。在一个可以循环读取的程序中进
行测试,直到用户输入空行。对于任何输入字符串,函数都应该适用并可以显示结果
#include <stdio.h>
#define LEN 80
char * del_space(char * pstr);
int main(void)
{
char str[LEN];
printf("请输入要删空格的字符串:");
while (gets(str) && str[0] != '\0')
{
printf("删掉空格后的字符串:");
puts(del_space(str));
printf("请输入要删空格的字符串:");
}
printf("结束!\n");
return 0;
}
#include <ctype.h>
char * del_space(char * pstr)
{
char * temp = pstr;
char * temp1;
while (*temp)
{
if (isspace(*temp))
{
temp1 = temp;
do
{
*temp1 = *(temp1 + 1);
}
while(*++temp1) ;
}
else
{
temp++;
}
}
return pstr;
}
10,编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程。这个程序可以为用户提供一个有5个选项的菜单:输出字符串列表、按ASCII顺序输出字符串、长度递增顺序输出字符串、按字符串中第一个单词的长度输出字符串、退出。菜单可以循环直到用户输入退出请求。当然,程序要能真正完成菜单中的各项功能。
/*
* 10,编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程。
* 这个程序可以为用户提供一个有5个选项的菜单:输出字符串列表、按ASCII顺序输出字符串、
* 长度递增顺序输出字符串、
* 按字符串中第一个单词的长度输出字符串、退出。菜单可以循环直到用户输入退出请求。
* 当然,程序要能真正完成菜单中的各项功能。
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define ROWS 10
#define COLS 81
void menu(void); //显示菜单
char get_char(void); //读取用户输入的正确选项
int in_str(char str[][COLS]); //输入字符串,返回字符串的个数
void show_str(const char * str[], int n); //输出参数传递过来字符串
void show_ascii(char * str[], int n); //按ASCII顺序输出
void show_strlen(char * str[], int n); //按字符串长度输出
void show_wordlen(char * str[], int n); //按字符串第一个单词的长度输出
int wordlen(char * str); //求字符串第一个单词找度
int main(void)
{
char str[ROWS][COLS]; //保存输入的原始字符串,值不做改变,方便用户循环选择时,任何时候都能输出原始值。
char str_copy[ROWS][COLS]; //原始数据的备份可改变
char * pstr[ROWS]; //声明指针做为函数参数传送
char * pcopy[ROWS];
char ch; //菜单选项
int i; //字符串的个数
int j; //用于数组赋值
i = in_str(str);
for (j = 0; j < i; j++)
{ //数组赋值
pstr[j] = str[j];
pcopy[j] = str_copy[j];
strcpy(pcopy[j],pstr[j]);
}
menu();
while ((ch = get_char()) != 'q')
{
switch (ch)
{
case 'a': show_str(pstr, i);
break;
case 'b': show_ascii(pcopy, i);
break;
case 'c': show_strlen(pcopy, i);
break;
case 'd': show_wordlen(pcopy, i);
break;
default: printf("Error!");
}
menu();
}
return 0;
}
int wordlen(char * str)
{ //首单词字母个数
int count = 0;
char ch;
while (ch = *str++)
{
if (isspace(ch) && count == 0) continue;
if (isspace(ch) && count != 0) break;
if (!isspace(ch)) count++;
}
return count;
}
void show_wordlen(char *str[], int n)
{ //按照首单词字母长度排序后输出
char * temp;
int i, j;
for (i = 0; i < n - 1; i++)
for (j = i; j < n; j++)
if (wordlen(str[i]) > wordlen(str[j]))
{
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
show_str(str, n);
}
void show_strlen(char *str[], int n)
{ //按照字符串长度排序后输出
char * temp;
int i, j;
for (i = 0; i < n - 1; i++)
for (j = i; j < n; j++)
if (strlen(str[i]) > strlen(str[j]))
{
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
show_str(str, n);
}
void show_ascii(char *str[], int n)
{ //按照字符ASCII编码顺序排序后输出
char * temp;
int i, j;
for (i = 0; i < n - 1; i++)
for (j = i; j < n; j++)
if (strcmp(str[i], str[j]) > 0)
{
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
show_str(str, n);
}
void show_str(const char *str[], int n)
{ //输出字符串数组
int i = 0;
while (i < n)
puts(str[i++]);
}
int in_str(char(*str)[COLS])
{ //输入字符串
int i = 0;
do
{
printf("请输入字符串%d(输入EOF结束): ", i + 1);
} while (gets(str[i]) && ++i < ROWS);
puts("输入结束。");
return i;
}
void menu(void)
{ //显示菜单
puts("请选择字符串输出方式:");
puts(" a)输出字符串列表");
puts(" b)按ASCII顺序输出字符串");
puts(" c)长度递增顺序输出字符串");
puts(" d)按字符串中第一个单词的长度输出字符串");
puts(" q)退出");
}
char get_char(void)
{ //确认输入符合要求
char ch;
while (ch = getchar())
{
while (getchar() != '\n')
;
if (!strchr("abcdq", ch))
puts("请输入正确的选项,(如:a b c d q):");
else
break;
}
return ch;
}
11.编写一个程序。功能是读取输入,直到遇到EOF,并报告单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用ctype.h系列函数。
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
int count_word = 0;
int count_lower = 0;
int count_upper = 0;
int count_digit = 0;
int count_punct = 0;
bool sign = false;
char ch;
while ((ch = getchar()) != EOF)
{
if (islower(ch)) count_lower++;
else if (isupper(ch)) count_upper++;
else if (isdigit(ch)) count_digit++;
else if (ispunct(ch)) count_punct++;
if (!isspace(ch) && !sign)
{ //单词的界定为单个非空格字符和不包含空格字符的字符串,
count_word++;
sign = true;
}
else if (isspace(ch) && sign)
{
sign = false;
}
}
puts("统计结果:");
printf("单词数:%d\n", count_word);
printf("小写字母数:%d\n", count_lower);
printf("大写字母数:%d\n", count_upper);
printf("标点符号数:%d\n", count_punct);
printf("数字个数:%d\n", count_digit);
return 0;
}
12.编写一个程序,按照相反的单词顺序显示命令行参数。即,如果命令行参数是see you later,程序的显示应该为later you see。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LEN 80
int main()
{
char str[LEN] = "see you later";
char temp;
int len = strlen(str) - 1;
int i, j, wordlen;
puts(str);
for (i = 0; i < len - i; i++)
{
temp = str[i];
str[i] = str[len - i];
str[len - i] = temp;
}
puts(str);
wordlen = 0;
i = 0;
do
{
if (!isspace(str[i]) && str[i] != '\0')
//isspace()不能识别'\0'条件中要加上str[i] != '\0'
wordlen++;
else
{
if (wordlen > 0)
{
for (j = 0; j < wordlen - j; j++)
{
temp = str[i -1 - j]; //i-1 位置在单词的最后一个了符
str[i - 1 -j] = str[i - wordlen+j]; //[i - wordlen]位置在单词的第一个字符。
str[i - wordlen+j] = temp;
}
wordlen = 0;
}
}
} while (str[i++] != '\0');
puts(str);
return 0;
}
13.编写一个计算乘幂的基于命令行和程序。第一个命令行参数为double类型数,作为幂的底数;第二个参数为整数,作为幂的指数。
#include <stdio.h>
#include <stdlib.h> //提供atof()
#include <math.h> //提供pow()
int main(int argc, char *argv[])
{
double num, exp;
if (argc != 3)
printf("参数不符\n");
else
{
num = atof(argv[1]);
exp = atof(argv[2]);
printf("%.2lf的%.0lf次幂为:%lf", num, exp, pow(num, exp));
}
return 0;
}
14.使用字符分类函数实现atoi()函数。
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
char str[20];
while(gets(str))
printf("%d\n", my_atoi(str));
return 0;
}
int my_atoi(char * pstr)
{
int sign = 1;
int num = 0;
//字符串不能为空
if (pstr == NULL)
return 0;
//去掉空格
while (isspace(*pstr))
pstr++;
//判数首位是否有符号
if (*pstr == '-')
sign = -1;
if (*pstr == '-' || *pstr == '+')
pstr++;
//转换直到遇到非数字时结束。
while (isdigit(*pstr))
{
num = (num * 10) + (*pstr - '0');
pstr++;
}
//增加符号位
num *= sign;
return num;
}
15.编写一个程序,其功能是读取输入,直到遇到文件结尾,并把文件显示出来,要求程序可以识别并执行下面的命令行参数:
-p 按原样显示输入
-u 把输入全部转换为大写
-l 把输入全部转换为小写
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int ch;
if (argc > 2)
{
printf("%s不是正确的指令,请输入正确的指禽 -p -u 或-l\n", argv[1]);
printf("例如: %s [-p | -u | -l]\n", argv[0]);
}
else if (argc == 2)
{
if (argv[1][0] != '-')
{
printf("%s不是正确的指令,请输入正确的指禽 -p -u 或-l\n", argv[1]);
printf("例如: %s [-p | -u | -l]\n", argv[0]);
}
else
switch (argv[1][1])
{
case 'p':while ((ch = getchar()) != EOF)
putchar(ch);
break;
case 'u':while ((ch = getchar()) != EOF)
putchar(toupper(ch));
break;
case 'l': while ((ch = getchar()) != EOF)
putchar(tolower(ch));
break;
default: printf("%s不是正确的指令,请输入正确的指禽 -p -u 或-l\n", argv[1]);
printf("例如: %s [-p | -u | -l]\n", argv[0]);
}
}
return 0;
}
转载于:https://blog.51cto.com/xiongyi85/1657464