• 抬起头,继续前进吧,去把这个不完美的故事,变成你成所期望的样子
  • 登山路上我们会放弃很多东西,但这些被我们丢掉在我们登上山顶之际,都会一一回来
  • 不论开发还是逆向,数学水平的高低直接决定了”你的饭碗里有没有肉”
  • 万丈高楼平地起,勿在浮沙筑高台

《C语言程序设计:现代方法》第十三章练习

C 菜鸟 10个月前 (09-28) 8287次浏览 已收录 2个评论
[隐藏]

        本篇为菜鸟在学习《C 语言程序设计:现代方法》中第十三章字符串时做的练习题,如果有错误或疑问的话,欢迎大家指正~

1、转换说明

下面的函数调用应该是写出单独一个换行符,但是其中有一些是错误的。请指出哪些调用是错误的并说明理由
(a) printf(“%c”, ‘\n’);
(b) printf(“%c”, “\n”);
(c) printf(“%s”, ‘\n’);
(d) printf(“%s”, “\n”);
(e) printf(‘\n’);
(f) printf(“\n”);
(g) putchar(‘\n’);
(h) putchar(“\n”);
(i) puts(‘\n’);
(j) puts(“\n”);
(k) puts(“”);
答:
(b) %c 是单个字符的转换说明
(c) %s 是字符串的转换说明
(e) printf 函数的参数为字符串字面量
(h) putchar 函数的参数为单个字符
(j) puts 函数的参数为字符串字面量

2、函数调用

假设 p 的定义如下所示:
char *p = “abc”;
下列哪些函数调用是合法的?请说明每个合法的函数调用的输出,并解释为什么其他的是非法的
(a) putchar(p)
(b) putchar(*p)
(c) puts(p)
(d) puts(*p)
答:
(a) 非法。putchar 函数的参数为单个字符;p 为字符指针,直接赋值字符串”abc”,这时 p 就是一个数组,p 的代表指向第一个元素’a’的内存地址
(b) 合法。输出为:a
(c) 合法。输出为:abc
(d) 非法。puts 函数的参数为字符串字面量,*p 代表的的是它的第一个元素,是单个字符

3、scanf 函数

scanf(“%d%s%d”, &i, s, &j);
如果用户输入 12abc3456def78, 那么调用后 i、s 和 j 的值分别是多少?(假设 i 和 j 是 int 型变量, s 是字符数组)
答:
i 为 12
s 为 abc3456def78
j 为 0

4、read_line 函数实现

按照下述要求分别实现 read_line 函数
(a) 在开始存储输入字符前跳过空白字符
(b) 在读入第一个空白字符时停止。提示:调用 isspace 函数来检查字符是否为空白字符
(c) 在读入第一个换行符时停止,然后把换行符存储到字符串中
(d) 把没有空间存储的字符留下以备后用
答:

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

#define STRING_LENGTH 11

int ReadLine(char *szInputString, char *szRemainderString);

int main()
{
    char szInputString[STRING_LENGTH] = { 0 };
    char szRemainderString[101] = { 0 };
    int iInputNumber = 0;

    printf("Enter the message that lenth is 10: ");
    iInputNumber = ReadLine(szInputString, szRemainderString);
    
    printf("The message is: ");
    for (int i = 0; i < iInputNumber; i++)
    {
        printf("%c", szInputString[i]);
    }
    printf("\r\n");
    printf("Remainder content is: %s\r\n", szRemainderString);

    system("pause");
    return 0;
}

int ReadLine(char *szTempPointer, char *szRemainderString)
{
    int i = 0;

    for (; i < STRING_LENGTH - 1; i++)
    {
        scanf("%c", szTempPointer);
        if (*szTempPointer == '\n')
        {
            break;
        }
        if (isspace(*szTempPointer))
        {
            szTempPointer--;
            break;
        }
        szTempPointer++;
    }

    if (i != (STRING_LENGTH - 1))
    {
        szTempPointer++;
    }
    else
    {
        while ((*szRemainderString = getchar()) != '\n')
        {
            szRemainderString++;
        }
        fflush(stdin);
    }
    *szTempPointer = '\0';

    return i + 1;
}

5、strcap 函数

(a) 编写名为 strcap 的函数来把参数中的字母都改为大写字母。参数是空字符结尾的字符串,且此字符串包含任意 ASCII 字符,不仅是字母
使用数组下标的方式访问字符串中的字符。提示:使用 toupper 函数把每个字符转换成大写
(b) 重写 strcap 函数,这次使用指针来访问字符串中的字符
答:

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

#define INPUT_SIZE 32

void ArrayModeStrcap(char szString[]);
void PointerModeStrcap(char szString[]);

int main()
{
    char szInputString[INPUT_SIZE] = { 0 };

    printf("Enter a string: ");
    rewind(stdin);
    scanf("%31s", szInputString);

    ArrayModeStrcap(szInputString);

    printf("%s\r\n", szInputString);

    //清空字符串的内容
    memset(szInputString, 0, INPUT_SIZE);

    printf("Enter a string: ");
    rewind(stdin);
    scanf("%31s", szInputString);

    PointerModeStrcap(szInputString);

    printf("%s\r\n", szInputString);

    system("pause");
    return 0;
}

void ArrayModeStrcap(char szString[])
{
    int cntI = 0;

    while (szString[cntI] != '\0')
    {
        szString[cntI] = toupper(szString[cntI]);
        cntI++;
    }
}

void PointerModeStrcap(char szString[])
{
    char *pszTemp = szString;
    int cntI = 0;

    while (*pszTemp != '\0')
    {
        *pszTemp = toupper(*pszTemp);
        pszTemp++;
    }
}

6、censor 函数

编写名为 censor 的函数,用来把字符串中出现的每一处字母”foo”替换为”xxx”。例如,字符串”food fool” 会变成 “xxxd xxxl”。在不失清晰的前提下
程序越短越好
答:

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

#define INPUT_SIZE 32

void Censor(char *pszTarget, char *pszMatch, char *cRevirseDst);

int main()
{
    char szString[INPUT_SIZE] = { 0 };
    char szMatch[INPUT_SIZE] = { 0 };
    char szDst[INPUT_SIZE] = { 0 };

    printf("Enter a string: ");
    rewind(stdin);
    scanf("%31s", szString);

    printf("Enter a string to revirse: ");
    rewind(stdin);
    scanf("%31s", szMatch);

    printf("Enter revirse destination: ");
    rewind(stdin);
    scanf("%31s", szDst);

    Censor(szString, szMatch, szDst);

    printf("Result: %s\r\n", szString);

    system("pause");
    return 0;
}

void Censor(char *pszTarget, char *pszMatch, char *cRevirseDst)
{
    size_t cntI = 0;
    int cntJ = 0;
    char *pcMatch = pszMatch;
    char *pcTarget = pszTarget;
    int iMatchLen = 0;
    char *pcMatchHeadAddr = NULL;

    for (cntI = 0; cntI < strlen(pszTarget) + 1; cntI++)
    {
        if (*pcTarget == *pcMatch)
        {
            //保存首地址
            if (iMatchLen == 0)
            {
                pcMatchHeadAddr = pcTarget;
            }

            iMatchLen++;
            pcMatch++;

            //如果找到匹配则开始更改
            if (iMatchLen == strlen(pszMatch))
            {
                memmove(pcMatchHeadAddr, cRevirseDst, iMatchLen);
                iMatchLen = 0;
                pcMatch = pszMatch;
                pcMatchHeadAddr = NULL;
            }
        }
        else
        {
            iMatchLen = 0;
            pcMatch = pszMatch;
            pcMatchHeadAddr = NULL;
        }

        pcTarget++;
    }
}

7、程序输出

下面程序的输出是什么?

#include <stdio.h>

main()
{
    char s[] = "Hsjodi", *p;
    
    for (p = &s[5]; p >= s; p--) --*p;
    puts(s);
    return 0;
}

答:Grinch

8、函数判断 1

int f(char *s, char *t)
{
    char *p1, *p2;
    
    for (p1 = s; *p1; p1++) {
        for (p2 = t; *p2; p2++) {
            if (*p1 == *p2) break;
        }
        if (*p2 == '\0') break;
    }
    return p1 - s;
}

(a) f(“abcd”, “badc”)的值是多少?
(b) f(“abcd”, “bcd”)的值是多少?
(c) 通常情况下,当传递两个字符串 s 和 t 时,函数的返回值是什么?
答:
(a)4
(b)0
(c)返回值是字符串 s 中首个没有在字符串 t 中找到的字符的位置

9、字符数组

假设 str 是字符数组,下面哪条语句与其他 3 条语句不等价
(a) *str = 0;
(b) str[0] = ‘\0’;
(c) strcpy(str, “”);
(d) strcat(str, “”);
答:d

10、字符相关函数 1

在执行下列语句后,字符串 str 的值是什么?
strcpy(str, “tire-bouchon”);
strcpy(&str[4], “d-or-wi”);
strcat(str, “red?”);
答:”tired-or-wired?”

11、字符相关函数 2

在执行下列语句后,字符串 s1 与 s2 的值各是什么?

strcpy(s1, "computer");
strcpy(s2, "science");
if (strcmp(s1, s2) < 0) {
    strcat(s1, s2);
} else {
    strcat(s2, s1);
}
s2[strlen(s2) - 6] = '\0'

答:computers

12、函数判断 2

下面的函数假设用来创建字符串的相同副本。请指出这个函数中的错误?
char *strdup(const char *p)
{
char *q;
strcpy(q, p);
return q;
}
答:不能使用返回值。因为字符指针 q 在函数中创建,属于局部指针,其地址在函数运行结束后就会被回收。

13、strcmp 函数

int strcmp(char *s, char *t)
{
    int i;
    
    for (i = 0; s[i] == t[i]; i++) {
        if (s[i] == '\0') {
            return 0;
        }
    }
    return s[i] - t[i];
}

修改此函数,使用指针算术运算的方法来修改此函数
答:

int Strcmp(char *s, char *t)
{
    char *p = s;
    char *q = t;
    
    for (; *p == *q;*p++, *q++) 
    {
        if (*p == '\0') 
        {
            return 0;
        }
    }
    return *p - q*;
}

14、最大和最小

编写程序用来找到一组单词中 “最大” 单词和 “最小” 单词。当用户输入单词后,程序根据字典的排序顺序决定排在最前面和最后面的单词。
当用户输入了 4 个字母时,程序必须停止读入。假设所有单词都不超过 20 个字母。程序与用户的交互显示如下所示:
Enter word: dog
Enter word: zebra
Enter word: rabbit
Enter word: catfish
Enter word: walrus
Enter word: cat
Enter word: fish
Smallest word: cat
Largest word: zebra
答:

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

#define INPUT_SIZE 14
#define SMALLEST_SIZE 14
#define LARGEST_SIZE 14
#define TRUE 1
#define FALSE 0

typedef int BOOL;

int ReadWord(char szInputWord[], int iInputSize, BOOL *bInputCheckSign);

int main()
{
    char szInputWord[INPUT_SIZE] = { 0 };
    char szSmallestWord[SMALLEST_SIZE] = { 0 };
    char szLargestWord[LARGEST_SIZE] = { 0 };
    BOOL bInputCheckSign = TRUE;
    int iInputLength = 0;
    int cntI = 0;

    for (;;)
    {
        printf("Enter word: ");
        iInputLength = ReadWord(szInputWord, INPUT_SIZE, &bInputCheckSign);
        
        if (!bInputCheckSign)
        {
            printf("The input is outside the law! Please input again.\r\n");
            continue;
        }

        if (szSmallestWord[0] == 0 ||
            strcmp(szInputWord, szSmallestWord) < 0)
        {
            strcpy(szSmallestWord, szInputWord);
        }
        else if (strcmp(szInputWord, szLargestWord) > 0)
        {
            strcpy(szLargestWord, szInputWord);
        }

        for (cntI = 0; cntI < INPUT_SIZE; cntI++)
        {
            szInputWord[cntI] = 0;
        }

        if (iInputLength == 4)
        {
            break;
        }
    }

    printf("Smallest word: %s\r\n", szSmallestWord);
    printf("Largest word: %s\r\n", szLargestWord);

    system("pause");
    return 0;
}

int ReadWord(char szInputWord[], int iInputSize, BOOL *bInputCheckSign)
{
    int cntI = 0;
    char cTempchar = '\0';

    while ((cTempchar = (char)getchar()) != '\n')
    {
        if (isalpha(cTempchar) &&
            cntI < iInputSize - 1)
        {
            szInputWord[cntI] = cTempchar;
            cntI++;
        }
        else
        {
            *bInputCheckSign = FALSE;
            break;
        }
    }
    szInputWord[cntI] = '\0';

    return cntI;
}

15、remind.c

按如下方式改进 remind.c 程序:
(a) 如果对应的天为负数或大于 31,那么先是显示出错误信息,然后忽略提示
(b) 允许用户输入天、24 小时格式的时间(可能空白)和提示。显示的提示列表必须按天排序存储,然后再根据时间排序存储。
【原 remind.c 程序允许用户输入时间,但确是将时间作为提示的一部分来处理了】
(c) 程序需显示一年的提示列表。要求用户按照月/日的格式输入日期
答:

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

#define MAX_REMIND 50
#define MSG_LEN 60
#define TRUE 1
#define FALSE 0

typedef int BOOL;

int ReadLine(char szInputString[], int iStringLength);
int ReadMonthDay(char szMonthDayString[], int iStringLength, BOOL *bEndSign);
int ReadTime(char szTimeString[], int iStringLength);

int main()
{
    char aszReminders[MAX_REMIND][MSG_LEN + 3] = { {0} };
    char szMonthDayString[6] = { 0 };
    char szTimeString[6] = { 0 };
    char szDateString[13] = { 0 };
    char szMsgString[MSG_LEN + 3] = { 0 };
    BOOL EndSign = FALSE;
    int cntRemindNumber = 0;
    int cntI = 0;

    printf("Format: MM/DD [HH:mm] - Thing\r\n");
    printf("End: 00\r\n");
    for (;;)
    {
        if (cntRemindNumber == MAX_REMIND)
        {
            printf("-- No space left --\r\n");
            break;
        }


        printf("Enter day and reminder: ");

        ReadMonthDay(szMonthDayString, 6, &EndSign);
        if (EndSign)
        {
            break;
        }
        ReadTime(szTimeString, 6);

        
        if (szMonthDayString[0] == '-' ||
            szMonthDayString[2] != '/' ||
            szMonthDayString[3] == '-' ||
            szMonthDayString[0] > '1' ||
            (szMonthDayString[0] == '1' &&
             szMonthDayString[1] > '2') ||
            szMonthDayString[3] > '3' ||
            (szMonthDayString[3] == '3' &&
             szMonthDayString[4] > '1'))

        {
            printf("The date is outsied the law!\r\n");
            fflush(stdin);
            continue;
        }

        
        if (szTimeString[0] > '2' ||
            (szTimeString[0] == '2' &&
             szTimeString[1] > '3') ||
            szTimeString[3] > '5')
        {
            printf("The Time is outside the law!\r\n");
            fflush(stdin);
            continue;
        }

        ReadLine(szMsgString, MSG_LEN);

        strcpy(szDateString, szMonthDayString);
        strcat(szDateString, " ");
        strcat(szDateString, szTimeString);
        strcat(szDateString, " ");

        for (; cntI < cntRemindNumber; cntI++)
        {
            if (strcmp(szDateString, aszReminders[cntI]) < 0)
            {
                break;
            }
        }

        for (int cntJ = cntRemindNumber; cntJ > cntI; cntJ--)
        {
            strcpy(aszReminders[cntJ], aszReminders[cntJ - 1]);
        }

        strcpy(aszReminders[cntI], szDateString);
        strcat(aszReminders[cntI], szMsgString);

        cntRemindNumber++;
    }

    printf("\nDay Reminder\n");
    for (cntI = 0; cntI < cntRemindNumber; cntI++)
    {
        printf(" %s\n", aszReminders[cntI]);
    }
    
    system("pause");
    return 0;
}

int ReadLine(char szInputString[], int iStringLength)
{
    char cTempchar = '\0';
    int cntI = 0;

    while ((cTempchar = (char)getchar()) != '\n')
    {
        if (cntI < iStringLength)
        {
            szInputString[cntI] = cTempchar;
            cntI++;
        }
       
    }
    szInputString[cntI] = '\0';

    return cntI;
}

int ReadMonthDay(char szMonthDayString[], int iStringLength, BOOL *bEndSign)
{
    char cTempchar = '\0';
    int cntI = 0;

    while ((cTempchar = (char)getchar()) != ' ')
    {   
        if ((isdigit(cTempchar) || cTempchar == '/') &&
            cntI < iStringLength )
        {
            szMonthDayString[cntI] = cTempchar;

            if (szMonthDayString[1] == '0' &&
                szMonthDayString[0] == '0')
            {
                *bEndSign = TRUE;
                return cntI;
            }
            cntI++;
        }
    }
    szMonthDayString[cntI] = '\0';

    return cntI;
}

int ReadTime(char szTimeString[], int iStringLength)
{
    char cTempchar = '\0';
    int cntI = 0;

    while ((cTempchar = (char)getchar()) != ' ')
    {
        if ((isdigit(cTempchar) || cTempchar == '):') &&
            cntI < iStringLength)
        {
            szTimeString[cntI] = cTempchar;
            cntI++;
        }
    }
    szTimeString[cntI] = '\0';

    return cntI;
}

16、精简 count_space 函数

精简 count_space 函数。特别是要用 while 循环替换 for 语句
答:

int count_space(const char *s)
{
    int count = 0;
    
    while (*s != '\0')
    {
        if(*s++ == ' ')
        {
            count++
        }
    }
    return count;
}

17、deal.c

修改 deal.c 程序,使它显示出牌的全名:
Enter number of cards in hand: 5
Your hand:
Eight of Diamond
Three of Heart
Three of Diamond
Nine of Spade
Three of Club
答:

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

#define NUM_SUITS 4
#define NUM_RANKS 13
#define TRUE 1
#define FALSE 0

typedef int BOOL;

int main()
{
    BOOL in_hand[NUM_SUITS][NUM_RANKS] = { { 0 } };
    int num_cards, rank, suit;
    const char *rank_code[] = { "Two", "Three", "Four", "Five", "Six", 
                                "Seven", "Eight", "Nine", "Ten", "Jack", 
                                "Queen", "King", "Ace" };
    const char *suit_code[] = { "Club", "Diamond", "Heart", "Spade" };

    srand((unsigned)time(NULL));

    printf("Enter number of cards in hand: ");
    scanf("%d", &num_cards);

    printf("Your hand:\r\n");
    while (num_cards > 0)
    {
        suit = rand() % NUM_SUITS;  /* picks a random suit */
        rank = rand() % NUM_RANKS;  /* picks a random rank */
        if (!in_hand[suit][rank])
        {
            in_hand[suit][rank] = TRUE;
            num_cards--;
            printf("%s of %s\r\n", rank_code[rank], suit_code[suit]);
        }
    }
    printf("\n");

    system("pause");
    return 0;
}

18、命令行参数反序输出

编写名为 reverse.c 的程序,用来把命令行参数按反序输出。如果按下述方式执行:
reverse void and null
则应输出:
null and void
答:

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

int main(int argc, char *argv[])
{
    int cntI = 0;

    for (cntI = argc - 1; cntI >= 1; cntI--)
    {
        printf("%s ", argv[cntI]);
    }
    printf("\r\n");

    system("pause");
    return 0;
}

19、命令行参数求和

编写名为 sum.c 的程序(使用 atoi 函数),用来对命令行参数进行求和。假设参数都是整数。如果按下述方式执行程序:
sum 8 24 62
产生的输出应为:
Total: 94
答:

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

int main(int argc, char *argv[])
{
    int cntI = 0;
    int iSum = 0;

    for (cntI = 1; cntI < argc; cntI++)
    {
        iSum += atoi(argv[cntI]);
    }

    printf("Total: %d\r\n", iSum);

    system("pause");
    return 0;
}

20、改进 planets.c

改进程序 planets.c,使它在比较命令行参数与 planets 数组中的字符串时忽略大小写。
答:

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

#define NUM_PLANETS 9

int main(int argc, char *argv[])
{
    char *apszPlanets[] = { "mercury", "venus", "earth",
                            "mars", "jupiter", "saturn",
                            "uranus", "neptune", "pluto" };
    int cntI = 0;
    int cntJ = 0;
    char *pcTmpLower = NULL;

    for (cntI = 1; cntI < argc; cntI++)
    {
        pcTmpLower = argv[cntI];
        while (*pcTmpLower != '\0')
        {
            *pcTmpLower = tolower(*pcTmpLower);
            pcTmpLower++;
        }

        for (cntJ = 0; cntJ < NUM_PLANETS; cntJ++)
        {
            if (strcmp(argv[cntI], apszPlanets[cntJ]) == 0)
            {
                printf("%s is planet %d\r\n", argv[cntI], cntJ + 1);
                break;
            }
        }

        if (cntJ == NUM_PLANETS)
        {
            printf("%s is not a planet.\r\n", argv[cntI]);
        }
    }
    
    system("pause");
    return 0;
}

学习心得 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明《C 语言程序设计:现代方法》第十三章练习
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. 答案错啦!!!
    templar2019-03-20 00:09 回复
    • 菜鸟
      是哪边出错了呢? :?: (时间太长我都忘了... :razz:
      菜鸟2019-03-21 11:47 回复