C Primer Plus第十一章编程练习答案

学完C语言之后,我就去阅读《C Primer Plus》这本经典的C语言书籍,对每一章的编程练习题都做了相关的解答,仅仅代表着我个人的解答思路,如有错误,请各位大佬帮忙点出!

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

#include <stdio.h>
#define LEN 11
void getnchar(char str[], int n)
{
    for (int i = 0; i < n - 1; ++i)
    {
        str[i] = getchar();
    }
}
int main(int argc, char* argv[])
{
    char str[LEN] = { 0 };

    printf("Please enter %d characters:\n", LEN - 1);
    getnchar(str, LEN);
    printf("Result:\n");
    puts(str);
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <ctype.h>
#define LEN 11
void getnchar(char str[], int n)
{
    int i = 0;
    while (i < n - 1)
    {
        str[i] = getchar();
        if (isspace(str[i]))
        {
            break;
        }
        ++i;
    }
}
int main(int argc, char* argv[])
{
    char str[LEN] = { 0 };

    printf("Please enter %d characters:\n", LEN - 1);
    getnchar(str, LEN);
    printf("Result:\n");
    puts(str);
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <ctype.h>
#define LEN 10
char* getword(char* str)
{
    int ch;
    int n = 0;
    char* pt = str;

    while ((ch = getchar()) != EOF && isspace(ch))
        continue;

    if (ch == EOF)
    {
        return NULL;
    }
    else
    {
        n++;
        *str++ = ch;
    }
    while ((ch = getchar()) != EOF && !isspace(ch) && (n < LEN - 1))
    {
        *str++ = ch;
        n++;
    }
    *str = '\0';

    if (ch == EOF)
    {
        return NULL;
    }
    else
    {
        while (getchar() != '\n')
            continue;
        return pt;
    }
}
int main(int argc, char* argv[])
{
    char input[LEN] = { 0 };

    printf("Please enter a word (EOF to quit):\n");
    while (getword(input) != NULL)
    {
        printf("Result:\n");
        puts(input);
        printf("You can enter a word again (EOF to quit):\n");
    }
    printf("Done.\n");

    

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

#include <stdio.h>
#include <ctype.h>
#define LEN 11
char* getword(char* str, int len)
{
    int ch;
    int n = 0;
    char* pt = str;

    while ((ch = getchar()) != EOF && isspace(ch))
        continue;

    if (ch == EOF)
    {
        return NULL;
    }
    else
    {
        n++;
        *str++ = ch;
    }
    while ((ch = getchar()) != EOF && !isspace(ch) && n < len)
    {
        *str++ = ch;
        n++;
    }
    *str = '\0';

    if (ch == EOF)
    {
        return NULL;
    }
    else
    {
        while (getchar() != '\n')
            continue;
        return pt;
    }
}

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

    printf("Please enter a word (EOF to quit):\n");
    while (getword(input, LEN - 1) != NULL)
    {
        printf("Result:\n");
        puts(input);
        printf("You can enter a word again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <string.h>
#define LEN 20
char* mystrchr(char* str, char ch)
{
    while (*str)
    {
        if (*str == ch)
        {
            return str;
        }
        ++str;
    }
    return NULL;
}
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;
}
int main(int argc, char* argv[])
{
    char ch, str[LEN];

    printf("Please enter a string (EOF to quit):\n");
    while (s_gets(str, LEN) != NULL)
    {
        printf("Please enter a character: ");
        ch = getchar();
        while (getchar() != '\n')
            continue;
        printf("String:\n");
        puts(str);
        if (mystrchr(str, ch) == NULL)
        {
            printf("Not exist %c in the string.\n", ch);
        }
        else
        {
            printf("Exist %c in the string.\n", ch);
        }
        printf("You can enter a string again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <string.h>
#define LEN 20
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;
}
int is_within(char ch, const char* str)
{
    while (*str)
    {
        if (*str == ch)
        {
            return 1;
        }
        ++str;
    }
    return 0;
}
int main(int argc, char* argv[])
{
    char ch, str[LEN];

    printf("Please enter a string (EOF to quit):\n");
    while (s_gets(str, LEN) != NULL)
    {
        printf("Please enter a character: ");
        ch = getchar();
        while (getchar() != '\n')
            continue;
        printf("String:\n");
        puts(str);
        if (!is_within(ch, str))
        {
            printf("Not exist %c in the string.\n", ch);
        }
        else
        {
            printf("Exist %c in the string.\n", ch);
        }
        printf("You can enter a string again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <string.h>
#define LEN 11
void eatline(void)
{
    while (getchar() != '\n')
        continue;
    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
        {
            eatline();
        }
    }
    return ret_val;
}

char* mystrncpy(char* dest, char* src, int n)
{
    int count = 0;

    while (*src != '\0' && count < n)
    {
        *(dest + count) = *src++;
        count++;
    }
    *(dest + count) = '\0';
    return dest;
}int main(int argc, char* argv[])
{
    int len;
    char target[LEN];
    char source[LEN];

    printf("Please enter a string (EOF to quit):\n");
    while (s_gets(source, LEN) != NULL)
    {
        printf("Please enter a number for copy (> 0): ");
        while (scanf("%d", &len) != 1 || len <= 0)
        {
            eatline();
            printf("Please enter again: ");
        }
        eatline();
        printf("Source string: %s\n", source);
        printf("Target string: %s\n", mystrncpy(target, source, len));
        printf("You can enter a string again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <string.h>
#define LEN 11
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, j = 0;
    int str_len = strlen(str), pt_len = strlen(pt);

    while (i < str_len && j < pt_len)
    {
        if (str[i] == pt[j])
        {
            i++;
            j++;
        }
        else
        {
            i = i - j + 1;
            j = 0;
        }
    }
    return j == pt_len ? str + i - j : NULL;
}
int main(int argc, char* argv[])
{
    char str1[LEN];
    char str2[LEN];

    printf("Please enter the first string (EOF to quit):\n");
    while (s_gets(str1, LEN) != NULL)
    {
        printf("Please enter the second string:\n");
        if (s_gets(str2, LEN) != NULL)
        {
            const char* temp = string_in(str1, str2);
            if (temp != NULL)
            {
                printf("String %s exists in string %s\n", str2, temp);
            }
            else
            {
                printf("String %s doesn't exist in string %s\n", str2, str1);
            }
        }
        printf("You can enter again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <string.h>
#define LEN 11
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;
}
void reverse(char* str)
{
    int len = strlen(str);

    for (int i = 0; i < len / 2; i++)
    {
        char temp = str[i];
        str[i] = str[len - 1 - i];
        str[len - 1 - i] = temp;
    }
}
int main(int argc, char* argv[])
{
    char str[LEN] = { 0 };

    printf("Please enter a string (EOF to quit):\n");
    while (s_gets(str, LEN) != NULL)
    {
        printf("String:\n");
        puts(str);
        reverse(str);
        printf("After reversing:\n");
        puts(str);
        printf("You can enter a string again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <string.h>
#define LEN 11
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;
}

void cancel(char* str)
{
    int j = 0, len = strlen(str);

    for (int i = 0; i < len; ++i)
    {
        if (str[i] != ' ')
        {
            str[j++] = str[i];
        }
    }
    str[j] = '\0';
}
int main(int argc, char* argv[])
{
    char str[LEN];

    printf("Please enter a string (EOF or enter to quit):\n");
    while (s_gets(str, LEN) != NULL && str[0] != '\0')
    {
        printf("Source string: %s\n", str);
        cancel(str);
        printf("Delete space: %s\n", str);
        printf("You can enter a string again (EOF or enter to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#define ROWS 11
#define COLUMNS 11
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;
}
int get_strings(char(*string)[COLUMNS], char** str, int n)
{
    int i;

    for (i = 0; i < n; i++)
    {
        if (s_gets(string[i], COLUMNS) != NULL)
        {
            str[i] = string[i];
        }
        else
        {
            break;
        }
    }
    return i;
}
int get_first(void)
{
    int ch;

    do
    {
        ch = tolower(getchar());
    } while (isspace(ch));
    while (getchar() != '\n')
        continue;

    return ch;
}
int show_menu(void)
{
    int ch;

    printf("+-------------------------------------------------------+\n");
    printf("|a) print for the origin          b) print for the ASCII|\n");
    printf("|c) print for the length          d) print for the words|\n");
    printf("|q) quit                                                |\n");
    printf("+-------------------------------------------------------+\n");
    printf("Please you choose: ");

    ch = get_first();
    while (ch < 'a' || ch > 'd' && ch != 'q')
    {
        printf("Please enter a, b, c, d or q: ");
        ch = get_first();
    }
    return ch;
}
int word(char* str)
{
    int length = 0;
    bool inword = false;

    while (*str)
    {
        if (!isspace(*str) && !inword)
        {
            inword = true;
            length++;
        }
        else if (!isspace(*str) && inword)
        {
            length++;
        }
        else if (isspace(*str) && inword)
        {
            break;
        }
        str++;
    }
    return length;
}
void origin_output(char(*str)[COLUMNS], int n)
{
    printf("Source strings:\n");
    for (int i = 0; i < n; i++)
    {
        puts(str[i]);
    }
    putchar('\n');
}
void ascll_output(char** str, int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (strcmp(str[i], str[j]) > 0)
            {
                char* temp = str[i];
                str[i] = str[j];
                str[j] = temp;
            }
        }
    }
    printf("Print source strings for ASCII:\n");
    for (int i = 0; i < n; i++)
    {
        puts(str[i]);
    }
    putchar('\n');
}
void length_up_output(char** str, int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (strlen(str[i]) > strlen(str[j]))
            {
                char* temp = str[i];
                str[i] = str[j];
                str[j] = temp;
            }
        }
    }
    printf("Print source strings for length:\n");
    for (int i = 0; i < n; i++)
    {
        puts(str[i]);
    }
    putchar('\n');
}
void first_word_output(char** str, int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (word(str[i]) > word(str[j]))
            {
                char* temp = str[i];
                str[i] = str[j];
                str[j] = temp;
            }
        }
    }
    printf("Print source strings for the first word:\n");
    for (int i = 0; i < n; i++)
    {
        puts(str[i]);
    }
    putchar('\n');
}
int main(void)
{
    int n, choice;
    char* str[ROWS];
    char strings[ROWS][COLUMNS];

    printf("Please enter %d strings (EOF to quit):\n", ROWS);
    if ((n = get_strings(strings, str, ROWS)) != 0)
    {
        while ((choice = show_menu()) != 'q')
        {
            switch (choice)
            {
            case 'a':
            {
                origin_output(strings, 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;
            }
            }
        }
    }
    printf("Done.\n");

    return 0;
}

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

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
int main(int argc, char* argv[])
{
    int ch, lower, upper, digit;
    int punct, words;
    lower = upper = digit = 0;
    punct = words = 0;
    bool inword = false;

    printf("Please enter some characters (EOF to quit):\n");
    while ((ch = getchar()) != EOF)
    {
        if (islower(ch))
        {
            lower++;
        }
        else if (isupper(ch))
        {
            upper++;
        }
        else if (isdigit(ch))
        {
            digit++;
        }
        else if (ispunct(ch))
        {
            punct++;
        }
        if (!isspace(ch) && !inword)
        {
            inword = true;
            words++;
        }
        if (isspace(ch) && inword)
        {
            inword = false;
        }
    }
    printf("Words: %d\n", words);
    printf("Lower: %d\n", lower);
    printf("Upper: %d\n", upper);
    printf("Digit: %d\n", digit);
    printf("Punct: %d\n", punct);

    return 0;
}

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

#include <stdio.h>
int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        printf("Usage: %s words\n", argv[0]);
    }
    else
    {
        printf("Words:\n");
        for (int i = 1; i < argc; i++)
        {
            printf("%s ", argv[i]);
        }
        printf("\nReversing printing is:\n");
        for (int i = argc - 1; i > 0; i--)
        {
            printf("%s ", argv[i]);
        }
        putchar('\n');
    }

    return 0;
}

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

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
    int exp;
    double num, sum = 1.0;

    if (argc != 3)
    {
        printf("Usage: %s floating-point exp\n", argv[0]);
    }
    else
    {
        num = atof(argv[1]), exp = atoi(argv[2]);
        for (int i = 1; i <= exp; i++)
        {
            sum *= num;
        }
        printf("%g ^ %d is %g.\n", num, exp, sum);
    }

    return 0;
}

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

#include <string.h>
#include <ctype.h>
#define LEN 11
int myatoi(char* str)
{
    int n = 0, len = strlen(str);

    for (int i = 0; i < len; i++)
    {
        if (!isdigit(str[i]))
        {
            return 0;
        }
        n = n * 10 + (str[i] - '0');
    }
    return n;
}
int main(int argc, char* argv[])
{
    char str[LEN];

    printf("Please enter a string (EOF to quit):\n");
    while (scanf("%s",str) != 0)
    {
        printf("String %s convert number %d\n", str, myatoi(str));
        printf("You can enter a string again (EOF to quit):\n");
    }
    printf("Done.\n");

    return 0;
}

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

-p 按原样打印

-u 把输入全部转换成大写

-l 把输入全部转换成小写

如果没有命令行参数,则让程序像是使用了-p参数那样运行。

#include <stdio.h>
#include <ctype.h>
void print_upper(char* str)
{
    printf("转换小写字母后的字符串为:");
    while (*str != '\0')
    {
        putchar(toupper(*str++));
    }
    printf("\n");
}
void print_lower(char* str)
{
    printf("转换大写字母后的字符串为:");
    while (*str != '\0')
    {
        putchar(tolower(*str++));
    }
    printf("\n");
}
int main(int argc, char* argv[])
{
    char str[1024] = { 0 };
    char c = '0';

    printf("请输入字符串和参数(p,u,l):");
    while (scanf("%s %c", str, &c) != EOF)
    {
        switch (c)
        {
            case 'p':
                printf("原来的字符串为:%s\n", str);
                printf("请输入字符串和参数(p,u,l):");
                break;
            case 'u':
                print_upper(str);
                printf("请输入字符串和参数(p,u,l):");
                break;
            case 'l':
                print_lower(str);
                printf("请输入字符串和参数(p,u,l):");
                break;
        }
    }
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值