《C Primer Plus》(第六版)第十一章:字符串和字符串函数|复习题与编程练习答案参考

目录

复习题

1.下面字符串的声明有什么问题?

2.下面的程序会打印什么?

3.下面的程序会打印什么?

4.下面的程序会打印什么?

5.下面的练习涉及字符串、循环、指针和递增指针。首先,假设定义了下面的函数:

6.假设有如下声明:

7.下面的程序会打印出什么?

8.下面的程序会打印出什么?

9.本章定义的s_gets()函数,用指针表示法代替数组表示法便可减少一个变量i。请改写该函数。

10.strlen()函数接受一个指向字符串的指针作为参数,并返回该字符串的长度。请编写一个这样的函数。

11.本章定义的s_gets()函数,可以用strchr()函数代替其中的while循环来查找换行符。请改写该函数。

12.设计一个函数,接受一个指向字符串的指针,返回指向该字符串第1个空格字符的指针,或如果未找到空格字符,则返回空指针。

13.重写程序清单11.21,使用ctype.h头文件中的函数,以便无论用户选择大写还是小写,该程序都能正确识别答案。

编程练习

1.设计并测试一个函数,从输入中获取n个字符(包括空白、制表符、换行符),把结果储存在一个数组里,它的地址被传递作为一个参数。

2.修改编程练习1的函数,在n个字符后停止,或在读到第1个空白、制表符或换行符时停止,哪个先遇到哪个停止。不能只使用scanf()。

3.设计并测试一个函数,从一行输入中把一个单词读入一个数组中,并丢弃输入行中的其余字符。该函数应该跳过第1个非空白字符前面的所有空白。将一个单词定义为没有空白、制表符或换行符的字符序列。

4.设计并测试一个函数,它类似编程练习3的描述,只不过它接受第2个参数指明可读取的最大字符数。

5.设计并测试一个函数,搜索第1个函数形参指定的字符串,在其中查找第2个函数形参指定的字符首次出现的位置。如果成功,该函数返指向该字符的指针,如果在字符串中未找到指定字符,则返回空指针(该函数的功能与 strchr()函数相同)。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

6.编写一个名为is_within()的函数,接受一个字符和一个指向字符串的指针作为两个函数形参。如果指定字符在字符串中,该函数返回一个非零值(即为真)。否则,返回0(即为假)。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

7.strncpy(s1, s2, n)函数把s2中的n个字符拷贝至s1中,截断s2,或者有必要的话在末尾添加空字符。如果s2的长度是n或多于n,目标字符串不能以空字符结尾。该函数返回s1。自己编写一个这样的函数,名为mystrncpy()。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

8.编写一个名为string_in()的函数,接受两个指向字符串的指针作为参数。如果第2个字符串中包含第1个字符串,该函数将返回第1个字符串开始的地址。例如,string_in("hats", "at")将返回hats中a的地址。否则,该函数返回空指针。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

9.编写一个函数,把字符串中的内容用其反序字符串代替。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

10.编写一个函数接受一个字符串作为参数,并删除字符串中的空格。在一个程序中测试该函数,使用循环读取输入行,直到用户输入一行空行。该程序应该应用该函数读取每个输入的字符串,并显示处理后的字符串。

11.编写一个函数,读入10个字符串或者读到EOF时停止。该程序为用户提供一个有5个选项的菜单:打印源字符串列表、以ASCII中的顺序打印字符串、按长度递增顺序打印字符串、按字符串中第1个单词的长度打印字符串、退出。菜单可以循环显示,除非用户选择退出选项。当然,该程序要能真正完成菜单中各选项的功能。

12.编写一个程序,读取输入,直至读到 EOF,报告读入的单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用ctype.h头文件中的函数。

13.编写一个程序,反序显示命令行参数的单词。例如,命令行参数是see you later,该程序应打印later you see。

14.编写一个通过命令行运行的程序计算幂。第1个命令行参数是double类型的数,作为幂的底数,第2个参数是整数,作为幂的指数。

15.使用字符分类函数实现atoi()函数。如果输入的字符串不是纯数字,该函数返回0。

16.编写一个程序读取输入,直至读到文件结尾,然后把字符串打印出来。该程序识别和实现下面的命令行参数:


复习题

1.下面字符串的声明有什么问题?

int main(void)
{
char name[] = {'F', 'e', 's', 's' };
...
}
如果要得到一个字符串,初始化列表中应该包含空字符“\0”;
也可以用另种语法自动添加字符:char name[]="Fess"。

2.下面的程序会打印什么?

#include <stdio.h>
int main(void)
{
char note[] = "See you at the snack bar.";
char *ptr;
ptr = note;
puts(ptr);
puts(++ptr);
note[7] = '\0';
puts(note);
puts(++ptr);
return 0;
}
See you at the snack bar.
ee you at the snack bar.
See you
e you //上一次++ptr已经移动到note[1],所以从这开始递增到\0处

3.下面的程序会打印什么?

#include <stdio.h>
#include <string.h>
int main(void)
{
char food [] = "Yummy";
char *ptr;
ptr = food + strlen(food);
while (--ptr >= food)
puts(ptr);
return 0;
}
y
my
mmy
ummy
Yummy
循环每次从递减指针指向的位置输出到末尾位置

4.下面的程序会打印什么?

#include <stdio.h>
#include <string.h>
int main(void)
{
char goldwyn[40] = "art of it all ";
char samuel[40] = "I read p";
const char * quote = "the way through.";
strcat(goldwyn, quote);
strcat(samuel, goldwyn);
puts(samuel);
return 0;
}
I read part of it all the way through

5.下面的练习涉及字符串、循环、指针和递增指针。首先,假设定义了下面的函数:

#include <stdio.h>
char *pr(char *str)
{
char *pc;
pc = str;
while (*pc)
putchar(*pc++);
do {
putchar(*--pc);
} while (pc - str);
return (pc);
}
考虑下面的函数调用:
x = pr("Ho Ho Ho!");
a. 将打印什么?
b.x 是什么类型?
c.x 的值是什么?
d. 表达式 *--pc 是什么意思?与 --*pc 有何不同?
e. 如果用 *--pc 替换 --*pc ,会打印什么?
f. 两个 while 循环用来测试什么?
g. 如果 pr() 函数的参数是空字符串,会怎样?
h. 必须在主调函数中做什么,才能让 pr() 函数正常运行?
a.Ho Ho Ho!!oH oH oH
b.char *(指向char的指针)
c.第一个H的地址
d.*--pc的意思是把指针递减1,并使用储存在该位置上的值。--*pc的意思是解引用pc指向的值,然后把该值减1(例如,H变成G)。
e. Ho Ho Ho!!oH oH o;注意, 在两个!之间有一个空字符,但是通常该字符不会产生任何打印的效果。
f.while (*pc)检查 pc 是否指向一个空字符(即,是否指向字符串的末尾)。while 的测试条件中使用储存在指针指向位置上的值。
while (pc - str) 检查 pc 是否与 str 指向相同的位置(即,字符串的开头)。 while的测试条件中使用储存在指针指向位置上的值。
g.进入第1个while循环后,pc指向空字符。进入第2个while循环后,它指向空字符前面的存储区(即,str 所指向位置前面的位置)。把该字节解释成一个字符,并打印这个字符。然后指针退回到前面的字节处。永远都不会满足结束条件(pc == str),所以这个过程会一直持续下去。
h. 必须在主调程序中声明 pr() char * pr(char *);

6.假设有如下声明:

char sign = '$';
sign 占用多少字节的内存? '$' 占用多少字节的内存? "$" 占用多少字节的内存?
字符变量占用一个字节,所以 sign 1 字节。但是字符常量储存为 int 类型,意思是'$' 通常占用 2 4 字节。但是实际上只使用 int 1 字节储存 '$' 的编码。字符串"$" 使用 2 字节:一个字节储存 '$' 的编码,一个字节储存的 '\0' 编码。

7.下面的程序会打印出什么?

#include <stdio.h>
#include <string.h>
#define M1 "How are ya, sweetie? "
char M2[40] = "Beat the clock.";
char * M3 = "chat";
int main(void)
{
char words[80];
printf(M1);
puts(M1);
puts(M2);
puts(M2 + 1);
strcpy(words, M2);
strcat(words, " Win a toy.");
puts(words);
words[4] = '\0';
puts(words);
while (*M3)
puts(M3++);
puts(--M3);
puts(--M3);
M3 = M1;
puts(M3);
return 0;
}
How are ya,sweetie?How are ya,sweetie?
Beat the clock.
eat the clock.
Beat the clock. Win a toy.
Beat
chat
hat
at
t
t
at
How are ya,sweetie?

8.下面的程序会打印出什么?

#include <stdio.h>
int main(void)
{
char str1 [] = "gawsie";
char str2 [] = "bletonism";
char *ps;
int i = 0;
for (ps = str1; *ps != '\0'; ps++) {
if (*ps == 'a' || *ps == 'e')
putchar(*ps);
else
(*ps)--;
putchar(*ps);
}
putchar('\n');
while (str2[i] != '\0') {
printf("%c", i % 3 ? str2[i] : '*');
++i;
}
return 0;
}
faavrhee
*le*on*sm

9.本章定义的s_gets()函数,用指针表示法代替数组表示法便可减少一个变量i。请改写该函数。

#include <stdio.h> // 提供fgets()和getchar()的原型
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;
}

10.strlen()函数接受一个指向字符串的指针作为参数,并返回该字符串的长度。请编写一个这样的函数。

int strlen(char* st)
{
	int length = 0;
	while (*st != '\0')
	{
		st++;
		length++;
	}
	return length;
}

11.本章定义的s_gets()函数,可以用strchr()函数代替其中的while循环来查找换行符。请改写该函数。

#include <stdio.h> // 提供fgets()和getchar()的原型
#include<string.h>
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!=NULL)//也可以写成if(find)
			find = '\0';
		else
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

12.设计一个函数,接受一个指向字符串的指针,返回指向该字符串第1个空格字符的指针,或如果未找到空格字符,则返回空指针。


#include <stdio.h> // 提供fgets()和getchar()的原型

char* space(char* st)
{
	while (*st != ' ' && *st != '\0')
		st++;
	if (*st == '\0')
		return NULL;
	else
		return st;
}

13.重写程序清单11.21,使用ctype.h头文件中的函数,以便无论用户选择大写还是小写,该程序都能正确识别答案。

# pragma warning (disable:4996)
#include <stdio.h>
#include <string.h> // strcmp()函数的原型在该头文件中
#include<ctype.h>
#define ANSWER "GRANT"
#define SIZE 40
void ToUpper(char* str);
char* s_gets(char* st, int n);
int main(void)
{
	char choice[SIZE];
	puts("Who is buried in Grant's tomb?");
	s_gets(choice, SIZE);
	ToUpper(choice);
	while (strcmp(choice, ANSWER) != 0)
	{
		puts("No, that's wrong. Try again.");
		s_gets(choice, SIZE);
		ToUpper(choice);
	}
	puts("That's right!");
	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
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

void ToUpper(char* str)
{
	while (*str != '\0')
	{
		*str = toupper(*str);
		str++;
	}
}

toupper():把小写字母转成大写字母

编程练习

1.设计并测试一个函数,从输入中获取n个字符(包括空白、制表符、换行符),把结果储存在一个数组里,它的地址被传递作为一个参数。

#include <stdio.h>
#include <ctype.h>  // 用于isspace()函数

// 函数声明
void read_n_chars(char* buffer, int n);

int main() {
    int n;
    char arr[100];

    printf("请输入要读取的字符数量: ");
    scanf_s("%d", &n);
    getchar();  // 消耗掉输入缓冲区中的换行符

    read_n_chars(arr, n);

    // 手动添加null终止符
    arr[n] = '\0';

    printf("读取的字符串: %s\n", arr);

    return 0;
}

// 函数定义:从标准输入读取n个字符到buffer中
void read_n_chars(char* buffer, int n) {
    for (int i = 0; i < n; i++) {
        buffer[i] = getchar();
    }
}

2.修改编程练习1的函数,在n个字符后停止,或在读到第1个空白、制表符或换行符时停止,哪个先遇到哪个停止。不能只使用scanf()

#include <stdio.h>
#include <ctype.h>  // 用于 isspace() 函数

// 函数声明
void read_n_chars(char* buffer, int n);

int main() {
    int n;
    char arr[100];

    printf("请输入要读取的字符数量: ");
    char input[20];
    fgets(input, sizeof(input), stdin);  // 读取用户输入的字符数量
    sscanf_s(input, "%d", &n);  // 将字符串转换为整数

    read_n_chars(arr, n);

    printf("读取的字符串: %s\n", arr);

    return 0;
}

// 函数定义:从标准输入读取 n 个字符到 buffer 中,或在遇到空白、制表符、换行符时停止
void read_n_chars(char* buffer, int n) {
    int i = 0;
    char c;

    while (i < n) {
        c = getchar();

        // 如果遇到空白、制表符或换行符,停止读取
        if (isspace(c)) {
            break;
        }

        buffer[i] = c;
        i++;
    }

    // 在字符串末尾添加 null 终止符
    buffer[i] = '\0';
}

3.设计并测试一个函数,从一行输入中把一个单词读入一个数组中,并丢弃输入行中的其余字符。该函数应该跳过第1个非空白字符前面的所有空白。将一个单词定义为没有空白、制表符或换行符的字符序列。

#include <stdio.h>
#include <ctype.h>  // 用于 isspace() 函数

// 函数声明
void read_word(char* word);

int main() {
    char word[100];  // 用于存储读取的单词

    printf("请输入一行文本: ");
    read_word(word);

    printf("读取的单词是: %s\n", word);

    return 0;
}

// 函数定义:从一行输入中读取一个单词并存储到数组中
void read_word(char* word) {
    int i = 0;
    char c;

    // 跳过第一个非空白字符前面的所有空白
    while ((c = getchar()) != EOF && isspace(c)) {
        // 继续跳过空白字符
    }

    // 读取单词,直到遇到空白字符或输入结束
    while (c != EOF && !isspace(c)) {
        word[i] = c;
        i++;
        c = getchar();
    }

    // 在单词末尾添加 null 终止符
    word[i] = '\0';

    // 丢弃输入行中的其余字符
    while (c != EOF && c != '\n') {
        c = getchar();
    }
}

4.设计并测试一个函数,它类似编程练习3的描述,只不过它接受第2个参数指明可读取的最大字符数。

#include <stdio.h>
#include <ctype.h>  // 用于 isspace() 函数

// 函数声明
void read_word(char* word, int max_len);

int main() {
    char word[100];  // 用于存储读取的单词
    int max_len;

    printf("请输入要读取的最大字符数: ");
    scanf_s("%d", &max_len);
    getchar();  // 消耗掉输入缓冲区中的换行符

    printf("请输入一行文本: ");
    read_word(word, max_len);

    printf("读取的单词是: %s\n", word);

    return 0;
}

// 函数定义:从一行输入中读取一个单词并存储到数组中,最多读取 max_len 个字符
void read_word(char* word, int max_len) {
    int i = 0;
    char c;

    // 跳过第一个非空白字符前面的所有空白
    while ((c = getchar()) != EOF && isspace(c)) {
        // 继续跳过空白字符
    }

    // 读取单词,直到遇到空白字符、输入结束或达到最大字符数
    while (c != EOF && !isspace(c) && i < max_len) {
        word[i] = c;
        i++;
        c = getchar();
    }

    // 在单词末尾添加 null 终止符
    word[i] = '\0';

    // 丢弃输入行中的其余字符
    while (c != EOF && c != '\n') {
        c = getchar();
    }
}

5.设计并测试一个函数,搜索第1个函数形参指定的字符串,在其中查找第2个函数形参指定的字符首次出现的位置。如果成功,该函数返指向该字符的指针,如果在字符串中未找到指定字符,则返回空指针(该函数的功能与 strchr()函数相同)。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

#include <stdio.h>
#include<string.h>
// 函数声明
char* find_char(const char* str, char ch);

int main() {
    char str[100];
    char ch;
    char* result;

    while (1) {
        // 获取用户输入的字符串
        printf("请输入一个字符串(输入空行退出): ");
        if (fgets(str, sizeof(str), stdin) == NULL || str[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        str[strcspn(str, "\n")] = '\0';

        // 获取用户输入的字符
        printf("请输入要查找的字符: ");
        ch = getchar();
        while (getchar() != '\n');  // 清除输入缓冲区中的剩余字符

        // 调用函数查找字符
        result = find_char(str, ch);

        // 输出结果
        if (result != NULL) {
            printf("字符 '%c' 在字符串中的位置: %d\n", ch, result - str);
        }
        else {
            printf("字符 '%c' 未在字符串中找到。\n", ch);
        }
    }

    printf("程序结束。\n");
    return 0;
}

// 函数定义:在字符串中查找字符首次出现的位置
char* find_char(const char* str, char ch) {
    while (*str != '\0') {
        if (*str == ch) {
            return (char*)str;  // 返回指向该字符的指针
        }
        str++;
    }
    return NULL;  // 未找到字符,返回空指针
}

6.编写一个名为is_within()的函数,接受一个字符和一个指向字符串的指针作为两个函数形参。如果指定字符在字符串中,该函数返回一个非零值(即为真)。否则,返回0(即为假)。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

#include <stdio.h>
#include<string.h>
// 函数声明
int is_within(char ch, const char* str);

int main() {
    char str[100];
    char ch;

    while (1) {
        // 获取用户输入的字符串
        printf("请输入一个字符串(输入空行退出): ");
        if (fgets(str, sizeof(str), stdin) == NULL || str[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        str[strcspn(str, "\n")] = '\0';

        // 获取用户输入的字符
        printf("请输入要查找的字符: ");
        ch = getchar();
        while (getchar() != '\n');  // 清除输入缓冲区中的剩余字符

        // 调用函数检查字符是否在字符串中
        if (is_within(ch, str)) {
            printf("字符 '%c' 在字符串中。\n", ch);
        }
        else {
            printf("字符 '%c' 不在字符串中。\n", ch);
        }
    }

    printf("程序结束。\n");
    return 0;
}

// 函数定义:检查字符是否在字符串中
int is_within(char ch, const char* str) {
    while (*str != '\0') {
        if (*str == ch) {
            return 1;  // 找到字符,返回真
        }
        str++;
    }
    return 0;  // 未找到字符,返回假
}

7.strncpy(s1, s2, n)函数把s2中的n个字符拷贝至s1中,截断s2,或者有必要的话在末尾添加空字符。如果s2的长度是n或多于n,目标字符串不能以空字符结尾。该函数返回s1。自己编写一个这样的函数,名为mystrncpy()。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

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

// 函数声明
char* mystrncpy(char* s1, const char* s2, int n);

int main() {
    char s1[100];  // 目标字符串
    char s2[100];  // 源字符串
    int n;

    while (1) {
        // 获取用户输入的源字符串
        printf("请输入源字符串(输入空行退出): ");
        if (fgets(s2, sizeof(s2), stdin) == NULL || s2[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        s2[strcspn(s2, "\n")] = '\0';

        // 获取用户输入的拷贝字符数
        printf("请输入要拷贝的字符数: ");
        scanf_s("%d", &n);
        while (getchar() != '\n');  // 清除输入缓冲区中的剩余字符

        // 调用函数拷贝字符串
        mystrncpy(s1, s2, n);

        // 输出结果
        printf("拷贝后的目标字符串: \"%s\"\n", s1);
    }

    printf("程序结束。\n");
    return 0;
}

// 函数定义:将 s2 中的 n 个字符拷贝到 s1 中
char* mystrncpy(char* s1, const char* s2, int n) {
    int i;

    // 拷贝字符
    for (i = 0; i < n && s2[i] != '\0'; i++) {
        s1[i] = s2[i];
    }

    s1[i] = '\0';
    return s1;  // 返回目标字符串
}

8.编写一个名为string_in()的函数,接受两个指向字符串的指针作为参数。如果第2个字符串中包含第1个字符串,该函数将返回第1个字符串开始的地址。例如,string_in("hats", "at")将返回hatsa的地址。否则,该函数返回空指针。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

#include <stdio.h>
#include <string.h>
// 函数声明
const char* string_in(const char* str1, const char* str2);

int main() {
    char str1[100];  // 第一个字符串
    char str2[100];  // 第二个字符串

    while (1) {
        // 获取用户输入的第一个字符串
        printf("请输入第一个字符串(输入空行退出): ");
        if (fgets(str1, sizeof(str1), stdin) == NULL || str1[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        str1[strcspn(str1, "\n")] = '\0';

        // 获取用户输入的第二个字符串
        printf("请输入第二个字符串: ");
        if (fgets(str2, sizeof(str2), stdin) == NULL || str2[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        str2[strcspn(str2, "\n")] = '\0';

        // 调用函数检查第一个字符串是否在第二个字符串中
        const char* result = string_in(str1, str2);

        // 输出结果
        if (result != NULL) {
            printf("'%s' 在 '%s' 中找到,起始位置为: %ld\n", str1, str2, result - str2);
        }
        else {
            printf("'%s' 不在 '%s' 中。\n", str1, str2);
        }
    }

    printf("程序结束。\n");
    return 0;
}

// 函数定义:检查第一个字符串是否在第二个字符串中
const char* string_in(const char* str1, const char* str2) {
    if (*str1 == '\0') {
        return str2;  // 如果第一个字符串为空,返回第二个字符串的起始地址
    }

    while (*str2 != '\0') {
        const char* p1 = str1;
        const char* p2 = str2;

        // 检查是否匹配
        while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
            p1++;
            p2++;
        }

        // 如果第一个字符串完全匹配,返回起始地址
        if (*p1 == '\0') {
            return str2;
        }

        str2++;  // 继续检查下一个字符
    }

    return NULL;  // 未找到,返回空指针
}

9.编写一个函数,把字符串中的内容用其反序字符串代替。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

#include <stdio.h>
#include <string.h>  // 用于 strlen 函数

// 函数声明
void reverse_string(char* str);

int main() {
    char str[100];  // 用于存储用户输入的字符串

    while (1) {
        // 获取用户输入的字符串
        printf("请输入一个字符串(输入空行退出): ");
        if (fgets(str, sizeof(str), stdin) == NULL || str[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        str[strcspn(str, "\n")] = '\0';

        // 调用函数反转字符串
        reverse_string(str);

        // 输出结果
        printf("反序后的字符串: %s\n", str);
    }

    printf("程序结束。\n");
    return 0;
}

// 函数定义:反转字符串
void reverse_string(char* str) {
    int length = strlen(str);  // 获取字符串长度
    int i, j;

    // 使用双指针法反转字符串
    for (i = 0, j = length - 1; i < j; i++, j--) {
        // 交换字符
        char temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }
}

10.编写一个函数接受一个字符串作为参数,并删除字符串中的空格。在一个程序中测试该函数,使用循环读取输入行,直到用户输入一行空行。该程序应该应用该函数读取每个输入的字符串,并显示处理后的字符串。

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

// 函数声明
void remove_spaces(char* str);

int main() {
    char str[100];  // 用于存储用户输入的字符串

    while (1) {
        // 获取用户输入的字符串
        printf("请输入一个字符串(输入空行退出): ");
        if (fgets(str, sizeof(str), stdin) == NULL || str[0] == '\n') {
            break;  // 如果输入为空行,退出循环
        }

        // 去除输入字符串末尾的换行符
        str[strcspn(str, "\n")] = '\0';

        // 调用函数删除空格
        remove_spaces(str);

        // 输出结果
        printf("删除空格后的字符串: %s\n", str);
    }

    printf("程序结束。\n");
    return 0;
}

// 函数定义:删除字符串中的空格
void remove_spaces(char* str) {
    int i = 0;  // 用于遍历原始字符串
    int j = 0;  // 用于构建新字符串

    while (str[i] != '\0') {
        if (str[i] != ' ') {  // 如果当前字符不是空格
            str[j] = str[i];  // 将字符复制到新位置
            j++;
        }
        i++;
    }

    // 在新字符串末尾添加 null 终止符
    str[j] = '\0';
}

11.编写一个函数,读入10个字符串或者读到EOF时停止。该程序为用户提供一个有5个选项的菜单:打印源字符串列表、以ASCII中的顺序打印字符串、按长度递增顺序打印字符串、按字符串中第1个单词的长度打印字符串、退出。菜单可以循环显示,除非用户选择退出选项。当然,该程序要能真正完成菜单中各选项的功能。

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

#define MAX_STRINGS 10
#define MAX_LENGTH 100

// 函数声明
void print_source_strings(char strings[MAX_STRINGS][MAX_LENGTH], int count);
void print_ascii_order(char strings[MAX_STRINGS][MAX_LENGTH], int count);
void print_length_order(char strings[MAX_STRINGS][MAX_LENGTH], int count);
int first_word_length(const char* str);
void print_first_word_length_order(char strings[MAX_STRINGS][MAX_LENGTH], int count);

int main() {
    char strings[MAX_STRINGS][MAX_LENGTH];  // 存储字符串的数组
    int count = 0;  // 实际读取的字符串数量

    // 读取字符串
    printf("请输入最多 %d 个字符串(按 Ctrl+D 或 Ctrl+Z 结束输入):\n", MAX_STRINGS);
    while (count < MAX_STRINGS && fgets(strings[count], MAX_LENGTH, stdin) != NULL) {
        // 去除输入字符串末尾的换行符
        strings[count][strcspn(strings[count], "\n")] = '\0';
        count++;
    }

    // 菜单循环
    int choice;
    do {
        printf("\n请选择一个选项:\n");
        printf("1. 打印源字符串列表\n");
        printf("2. 按 ASCII 顺序打印字符串\n");
        printf("3. 按长度递增顺序打印字符串\n");
        printf("4. 按第一个单词的长度打印字符串\n");
        printf("5. 退出\n");
        printf("请输入选项 (1-5): ");
        scanf_s("%d", &choice);

        // 根据用户选择执行操作
        switch (choice) {
        case 1:
            print_source_strings(strings, count);
            break;
        case 2:
            print_ascii_order(strings, count);
            break;
        case 3:
            print_length_order(strings, count);
            break;
        case 4:
            print_first_word_length_order(strings, count);
            break;
        case 5:
            printf("退出程序。\n");
            break;
        default:
            printf("无效选项,请重新选择。\n");
        }
    } while (choice != 5);

    return 0;
}

// 函数定义:打印源字符串列表
void print_source_strings(char strings[MAX_STRINGS][MAX_LENGTH], int count) {
    printf("源字符串列表:\n");
    for (int i = 0; i < count; i++) {
        printf("%s\n", strings[i]);
    }
}

// 函数定义:按 ASCII 顺序打印字符串
void print_ascii_order(char strings[MAX_STRINGS][MAX_LENGTH], int count) {
    char temp[MAX_LENGTH];

    // 使用冒泡排序按 ASCII 顺序排序
    for (int i = 0; i < count - 1; i++) {
        for (int j = i + 1; j < count; j++) {
            if (strcmp(strings[i], strings[j]) > 0) {
                strcpy_s(temp, strings[i]);
                strcpy_s(strings[i], strings[j]);
                strcpy_s(strings[j], temp);
            }
        }
    }

    printf("按 ASCII 顺序打印字符串:\n");
    for (int i = 0; i < count; i++) {
        printf("%s\n", strings[i]);
    }
}

// 函数定义:按长度递增顺序打印字符串
void print_length_order(char strings[MAX_STRINGS][MAX_LENGTH], int count) {
    char temp[MAX_LENGTH];

    // 使用冒泡排序按长度递增顺序排序
    for (int i = 0; i < count - 1; i++) {
        for (int j = i + 1; j < count; j++) {
            if (strlen(strings[i]) > strlen(strings[j])) {
                strcpy_s(temp, strings[i]);
                strcpy_s(strings[i], strings[j]);
                strcpy_s(strings[j], temp);
            }
        }
    }

    printf("按长度递增顺序打印字符串:\n");
    for (int i = 0; i < count; i++) {
        printf("%s\n", strings[i]);
    }
}

// 函数定义:计算字符串中第一个单词的长度
int first_word_length(const char* str) {
    int length = 0;
    while (*str != '\0' && !isspace(*str)) {
        length++;
        str++;
    }
    return length;
}

// 函数定义:按第一个单词的长度打印字符串
void print_first_word_length_order(char strings[MAX_STRINGS][MAX_LENGTH], int count) {
    char temp[MAX_LENGTH];

    // 使用冒泡排序按第一个单词的长度排序
    for (int i = 0; i < count - 1; i++) {
        for (int j = i + 1; j < count; j++) {
            if (first_word_length(strings[i]) > first_word_length(strings[j])) {
                strcpy_s(temp, strings[i]);
                strcpy_s(strings[i], strings[j]);
                strcpy_s(strings[j], temp);
            }
        }
    }

    printf("按第一个单词的长度打印字符串:\n");
    for (int i = 0; i < count; i++) {
        printf("%s\n", strings[i]);
    }
}

12.编写一个程序,读取输入,直至读到 EOF,报告读入的单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用ctype.h头文件中的函数。

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
 
int main() {
    int word_count = 0;
    int upper_count = 0;
    int lower_count = 0;
    int punct_count = 0;
    int digit_count = 0;
    bool in_word = false;
    int c;
 
    while ((c = getchar()) != EOF) {
        if (isspace(c)) {
            in_word = false;
        } else if (!in_word) {
            in_word = true;
            word_count++;
        }
 
        if (isupper(c)) {
            upper_count++;
        } else if (islower(c)) {
            lower_count++;
        } else if (ispunct(c)) {
            punct_count++;
        } else if (isdigit(c)) {
            digit_count++;
        }
    }
 
    printf("Words: %d\n", word_count);
    printf("Uppercase letters: %d\n", upper_count);
    printf("Lowercase letters: %d\n", lower_count);
    printf("Punctuation marks: %d\n", punct_count);
    printf("Digits: %d\n", digit_count);
 
    return 0;
}

13.编写一个程序,反序显示命令行参数的单词。例如,命令行参数是see you later,该程序应打印later you see

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

int main(int argc, char* argv[]) {
    // argc至少为1,因为argv[0]是程序本身的名称
    if (argc <= 1) {
        printf("No arguments provided.\n");
        return 1; // 返回非零值表示程序异常退出
    }

    // 从最后一个参数开始打印,直到第一个参数(不包括程序名)
    for (int i = argc - 1; i > 0; i--) {
        printf("%s ", argv[i]);
    }
    // 打印第一个参数(不包括程序名),后面不加空格
    printf("%s\n", argv[1]);

    return 0; // 返回0表示程序正常退出
}

14.编写一个通过命令行运行的程序计算幂。第1个命令行参数是double类型的数,作为幂的底数,第2个参数是整数,作为幂的指数。

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

int main(int argc, char *argv[]) {
    // 验证命令行参数的数量
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <base> <exponent>\n", argv[0]);
        return 1; // 非零返回值表示程序异常退出
    }

    // 将第一个命令行参数(底数)转换为double类型
    double base;
    char *endptr;
    base = strtod(argv[1], &endptr);
    // 检查转换是否成功
    if (*endptr != '\0') {
        fprintf(stderr, "Error: Invalid base (not a number).\n");
        return 1;
    }

    // 将第二个命令行参数(指数)转换为整数类型
    int exponent;
    exponent = atoi(argv[2]);

    // 计算幂并输出结果
    double result = pow(base, exponent);
    printf("%g^%d = %g\n", base, exponent, result);

    return 0; // 零返回值表示程序正常退出
}

15.使用字符分类函数实现atoi()函数。如果输入的字符串不是纯数字,该函数返回0

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

int my_atoi(const char *str) {
    // 跳过前导空格
    while (isspace(*str)) {
        str++;
    }

    // 处理空字符串或非数字字符的情况
    if (*str == '\0' || !isdigit(*str) && *str != '-' && *str != '+') {
        return 0;
    }

    // 处理符号
    int sign = 1;
    if (*str == '-' || *str == '+') {
        sign = (*str == '-') ? -1 : 1;
        str++;
    }

    // 转换数字并检查结果是否溢出
    int result = 0;
    while (isdigit(*str)) {
        int digit = *str - '0';
        
        // 检查整数溢出
        if (result > (INT_MAX - digit) / 10) {
            return (sign == 1) ? INT_MAX : INT_MIN;
        }
        
        result = result * 10 + digit;
        str++;
    }

    return sign * result;
}

int main() {
    // 测试用例
    printf("%d\n", my_atoi("   -42")); // 输出: -42
    printf("%d\n", my_atoi("4193 with words")); // 输出: 4193
    printf("%d\n", my_atoi("words and 987")); // 输出: 0
    printf("%d\n", my_atoi("-91283472332")); // 输出: INT_MIN (通常是 -2147483648)
    printf("%d\n", my_atoi("0")); // 输出: 0
    return 0;
}

16.编写一个程序读取输入,直至读到文件结尾,然后把字符串打印出来。该程序识别和实现下面的命令行参数:

-p 按原样打印
-u 把输入全部转换成大写
-l 把输入全部转换成小写
如果没有命令行参数,则让程序像是使用了 -p 参数那样运行。
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>

int main(int argc, char *argv[]) {
    bool print_original = true; // 默认按原样输出
    bool to_upper = false; // 不转换为大写
    bool to_lower = false; // 不转换为小写

    // 解析命令行参数
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-p") == 0) {
            print_original = true;
            to_upper = false;
            to_lower = false;
        } else if (strcmp(argv[i], "-u") == 0) {
            print_original = false;
            to_upper = true;
            to_lower = false;
        } else if (strcmp(argv[i], "-l") == 0) {
            print_original = false;
            to_upper = false;
            to_lower = true;
        } else {
            fprintf(stderr, "Unknown option: %s\n", argv[i]);
            return 1; // 返回非零值表示程序异常退出
        }
    }

    int c; // 用于存储从输入中读取的单个字符
    while ((c = getchar()) != EOF) { // 持续读取输入直至EOF
        if (print_original) {
            putchar(c); // 按原样输出
        } else if (to_upper) {
            putchar(toupper(c)); // 转换为大写后输出
        } else if (to_lower) {
            putchar(tolower(c)); // 转换为小写后输出
        }
    }

    return 0; // 返回零表示程序正常退出
}

不求甚解,没必要处处都要理解,影响学习进度,往后学习,回头看,不懂的自然会被解决。

语言的学习尽快啃完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值