《C语言程序设计学习指导与实践教程》——2.8.5 指针的定义及应用(题目分析与代码演示)

发布时间:2023年12月29日

?目录

前言

实验目的

实验内容与要求

1.分析下列程序并填空

(1)使5*5矩阵的对角线元素为1,其他为0,即输出5*5的对角矩阵。

(2)以下程序的功能是将单词book从句子中提取并输出。

(3)利用函数求两个数的和、差。

2.程序改错

(1)指针p指向数组a的最后的一个元素,求数组中所有元素之和。

(2)利用指针及函数互换两个整数的值。

3.程序设计(用指针编写程序并上机验证)

(1)用变量的指针作为函数调用的实参,降序输出3个整数。

(2)将数组a中的n个整数按相反顺序存放。

(3)从n个数中找出其中的最大值和最小值(用指针实现)。

(4)编写函数实现在字符数组w中插入字符x。函数原型为void fun(char *w,char *x,int *n);

说明:①假设w数组中的数已按由小到大的顺序存放。②n指向存储单元中数组元素的个数。③插入后数组中的数仍有序。

(5)编写函数求某字符串的长度,运行时输入字符串。

(6)用函数调用 方式,实现字符串的复制。

(7)编写函数将字符串s中的子字符串s1全部替换为子字符串s2。

(8)将输入的字符串逆序输出。

(9)将一个指针所指向的字符串中的大写字母复制到另一个指针所指向的字符数组中。

(10)输入5个国名并按字母顺序排列后输出。


前言

????????本篇基于《C语言程序设计学习指导与实践教程》(刘涛 叶明全 主编 | 上海交通大学出版社)教材书中的2.8.5章节 实验?指针的定义及应用。分析并编写相关例题程序代码以及演示结果(部分代码源于网络),供大家参考。如果有更为简洁高效的代码,或者有一些疑问等,也欢迎各位伙伴留言讨论分享。调试程序时若出现bug也请各位及时留言或私信!

? ? ? ? 欢迎大家阅读本系列的相关篇章,也希望大家给出宝贵建议,谢谢。
? ? ? ? 指针作为C语言学习中难度较高的部分,在编写代码时,需要较好掌握知识。这里引用一篇关于指针前提知识的文章,方便大家边做边学。(引用文章已经原作者同意)

C语言——指针icon-default.png?t=N7T8https://blog.csdn.net/Echo_cy_/article/details/132887777? ? ?

? 本篇暂时只提供了代码,相关思路及代码演示等,会在后期补充。


实验目的

(1)掌握指针的概念,会定义和使用指针变量。

(2)掌握指针的基本表达和运算。

(3)学会使用指针来处理数组问题。

(4)学会使用指针来处理和解决字符串数据。

(5)了解指向函数的指针变量。

(6)了解指向指针的指针的概念及其使用方法。


实验内容与要求

1.分析下列程序并填空

(1)使5*5矩阵的对角线元素为1,其他为0,即输出5*5的对角矩阵。

#include<stdio.h>
void main()
{
	int j, k, a[5][5], * p = __①__;
	for (j = 0; j < 5; j++)
		for (k = 0; k < 5; k++)
		{
			if (__②__)
				*p = 1, p++;
			else
				__③__;
		}
	for (j = 0; j < 5; j++)
	{
		for (k = 0; k < 5; k++)
			printf("%2d", a[j][k]);
		printf("\n");
	}
}

【完整程序】

#include<stdio.h>
void main()
{
	int j, k, a[5][5], * p = &a[0][0];	// 补充①:将p指向数组a的首元素
	for (j = 0; j < 5; j++)
		for (k = 0; k < 5; k++)
		{
			if (j == k) // 补充②:判断是否为对角线元素
				*p = 1, p++;
			else
				*p = 0, p++; // 补充③:将非对角线元素置为0
		}
	for (j = 0; j < 5; j++)
	{
		for (k = 0; k < 5; k++)
			printf("%2d", a[j][k]);
		printf("\n");
	}
}

(2)以下程序的功能是将单词book从句子中提取并输出。

#include<stdio.h>
void main()
{
	char __①__ ps = "this is a book";
	int n = 10;
	ps = __②__;
	printf("%s\n", __③__);
}

【完整程序】

#include <stdio.h>

void main()
{
    char *ps = "this is a book"; // 补充①:将ps声明为字符指针,并初始化为字符串的首地址
    int n = 10;
    ps = ps + n; // 补充②:将ps指针向后移动10个字节,指向单词"book"的首地址
    printf("%s\n", ps); // 补充③:输出ps指针指向的字符串
}

(3)利用函数求两个数的和、差。

#include<stdio.h>

int fun(int x, int y, int *cp, int *dp)
{
	*cp = x + y;
	*dp = x - y;
}
void main()
{
	int a, b, c, d;
	a = 30; b = 50;
	fun(a, b, __①__, __②__);
	printf("%d,%d\n", c, d);
}

【完整程序】

#include<stdio.h>

int fun(int x, int y, int* cp, int* dp)
{
	*cp = x + y;
	*dp = x - y;
}
void main()
{
	int a, b, c, d;
	a = 30; b = 50;
	fun(a, b, &c, &d); // 补充:将c和d的地址传递给函数fun
	printf("%d,%d\n", c, d);
}

2.程序改错

(1)指针p指向数组a的最后的一个元素,求数组中所有元素之和。

#include<stdio.h>
#define N 10
void main()
{
	int i, sum, * p, a[N] = { 1,3,5,7,9,11,13,15,17,19 };	/*$ERROR1$*/
	for (p = a[N - 1]; p >= &a[0]; p--)						/*$ERROR2$*/
		sum += p;											/*$ERROR3$*/
	printf("sum=%d\n", sum);
}

【正确程序】

#include<stdio.h>
#define N 10
void main()
{
	int i, sum = 0, * p, a[N] = { 1,3,5,7,9,11,13,15,17,19 };	
    //这里未将sum初始化为0,会使后续的累加溢出
	for (p = &a[N - 1]; p >= &a[0]; p--)						
    //for循环中,应该将p初始化为指向数组最后一个元素的指针,即&a[N-1]
		sum += *p;
    //应该将指针p指向的值累加到变量sum上,而不是将指针p本身累加到sum上
	printf("sum=%d\n", sum);
}

(2)利用指针及函数互换两个整数的值。

#include<stdio.h>
void swap(int p1, int p2)	/*$ERROR1$*/
{
	int	*t;					/*$ERROR2$*/
	t = *p1;
	*p1 = *p2;
	*p2 = t;
}
void main()
{
	int x, y;
	scanf("%d,%d", &x, &y);
	swap(x, y);				/*$ERROR3$*/
	printf("x=%d,y=%d\n", x, y);
}

【正确程序】

#include<stdio.h>
void swap(int *p1, int *p2)	//p1,p2为指向整数的指针,所以要在前加上*符号
{
	int	t;					//这里定义一个整型变量t,而不是指针变量
	t = *p1;
	*p1 = *p2;
	*p2 = t;
}
void main()
{
	int x, y;
	scanf("%d,%d", &x, &y);
	swap(&x, &y);				//传入x和y的地址,调用swap函数进行数值交换
	printf("x=%d,y=%d\n", x, y);
}

3.程序设计(用指针编写程序并上机验证)

(1)用变量的指针作为函数调用的实参,降序输出3个整数。

代码示例:

#include <stdio.h>

// 函数:降序排列三个整数
void fun(int* a, int* b, int* c){
    // 比较并交换第一个整数和第二个整数的位置
    if (*a < *b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    // 比较并交换第一个整数和第三个整数的位置
    if (*a < *c) {
        int temp = *a;
        *a = *c;
        *c = temp;
    }
    // 比较并交换第二个整数和第三个整数的位置
    if (*b < *c) {
        int temp = *b;
        *b = *c;
        *c = temp;
    }
}

int main(){
    int num1, num2, num3;
    printf("请输入三个整数:");
    scanf("%d%d%d", &num1, &num2, &num3);

    // 调用函数,传递三个整数的地址
    fun(&num1, &num2, &num3);
    //输出排列后的结果
    printf("降序后的顺序为:%d %d %d\n", num1, num2, num3);
    return 0;
}

(2)将数组a中的n个整数按相反顺序存放。

代码示例:

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

// 函数:将数组中的元素按相反顺序存放
void fun(int* arr, int n)
{
    int start = 0; // 定义起始索引
    int end = n - 1; // 定义结束索引

    while (start < end) {
        // 交换起始索引和结束索引处的元素
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;

        start++; // 更新起始索引
        end--; // 更新结束索引
    }
}

int main()
{
    int n, i;
    printf("输入数组中元素的个数:");
    scanf("%d", &n);

    int* arr = (int*)malloc(n * sizeof(int)); // 动态分配数组内存
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    printf("输入%d个整数:\n ", n);
    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    // 调用函数,将数组元素按相反顺序存放
    fun(arr, n);

    printf("倒序后的数组: ");
    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n"); 
    free(arr); // 释放动态分配的内存
    return 0;
}

(3)从n个数中找出其中的最大值和最小值(用指针实现)。

代码示例:

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

// 函数:找出最大值和最小值
void find_max_min(int* arr, int n, int* max, int* min)
{
    // 初始化最大值和最小值为数组的第一个元素
    *max = *min = arr[0];

    // 遍历数组,更新最大值和最小值
    for (int i = 1; i < n; i++) {
        if (arr[i] > *max)
            *max = arr[i]; // 更新最大值
        if (arr[i] < *min)
            *min = arr[i]; // 更新最小值
    }
}

int main()
{
    int n, i;
    printf("输入数组中元素的个数:");
    scanf("%d", &n);

    int* arr = (int*)malloc(n * sizeof(int)); // 动态分配数组内存
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    printf("输入%d个整数:\n ", n);
    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    int max, min;
    find_max_min(arr, n, &max, &min); // 通过指针传递最大值和最小值的地址

    printf("最大值为: %d\n", max);
    printf("最小值为: %d\n", min);

    return 0;
}

(4)编写函数实现在字符数组w中插入字符x。函数原型为void fun(char *w,char *x,int *n);

说明:①假设w数组中的数已按由小到大的顺序存放。②n指向存储单元中数组元素的个数。③插入后数组中的数仍有序。

//该题调试代码时出现未能解决的问题,这里先做标记。


(5)编写函数求某字符串的长度,运行时输入字符串。

代码示例:

#include <stdio.h>

// 函数:求字符串的长度
int stringLength(char *str)
{
    int length = 0;

    // 遍历字符串,直到遇到字符串结束符'\0'
    while (*str != '\0') {
        length++;
        str++;
    }

    return length;
}

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

    printf("输入一个字符串:");
    scanf("%s", str);

	length = stringLength(str); // 调用函数求字符串长度

    printf("字符串长度为:%d\n", length);

    return 0;
}

(6)用函数调用方式,实现字符串的复制。

代码示例:

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

void stringCopy(char *source, char *target) {
    while (*source != '\0') { // 遍历源字符串,直到遇到字符串结束符'\0'
        *target = *source; // 将源字符串的字符复制到目标字符串
        source++; // 源字符串指针向后移动一个位置
        target++; // 目标字符串指针向后移动一个位置
    }
    *target = '\0'; // 在目标字符串末尾添加字符串结束符'\0'
}

int main() {
    char sourceString[] = "HelloWorld!"; // 源字符串
    char targetString[20]; // 目标字符串

    stringCopy(sourceString, targetString); // 调用字符串复制函数

    printf("Source String: %s\n", sourceString);
    printf("Copied String: %s\n", targetString);

    return 0;
}

(7)编写函数将字符串s中的子字符串s1全部替换为子字符串s2。

代码示例:

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

void stringReplace(char* s, const char* s1, const char* s2) {
    int s1_len = strlen(s1); // 获取s1的长度
    int s2_len = strlen(s2); // 获取s2的长度
    int s_len = strlen(s); // 获取s的长度
    int i, j, k;

    // 创建一个临时缓冲区,用于存储替换后的字符串
    char* temp = (char*)malloc(sizeof(char) * (s_len + 1));
    if (temp == NULL) {
        printf("内存分配失败\n");
        return;
    }

    i = j = k = 0;

    while (i < s_len) {
        // 如果当前位置开始的子字符串与s1相等,则进行替换
        if (strncmp(&s[i], s1, s1_len) == 0) {
            // 将s2复制到临时缓冲区
            strncpy(&temp[j], s2, s2_len);
            i += s1_len; // 跳过s1的长度
            j += s2_len; // 更新临时缓冲区的索引
        }
        else {
            // 将s中的字符复制到临时缓冲区
            temp[j] = s[i];
            i++;
            j++;
        }
    }

    temp[j] = '\0'; // 在临时缓冲区末尾添加字符串结束符

    // 将临时缓冲区中的字符串复制回s
    strcpy(s, temp);

    free(temp); // 释放临时缓冲区的内存
}

int main() {
    char s[] = "Hello, World! Hello, Universe!";    //定义一个字符串
    const char s1[] = "Hello";      //定义子字符串1
    const char s2[] = "Hi";         //定义子字符串2

    printf("替换前的字符串:%s\n", s);

    stringReplace(s, s1, s2); // 调用字符串替换函数

    printf("替换后的字符串: %s\n", s);

    return 0;
}

(8)将输入的字符串逆序输出。

代码示例:

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

void reverseString(char *s) {
    int len = strlen(s); // 获取字符串的长度
    int i, j;
    char temp;

    // 使用双指针法逆序交换字符
    for (i = 0, j = len - 1; i < j; i++, j--) {
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    }
}

int main() {
    char s[100];

    printf("输入一行字符串:");
    fgets(s, sizeof(s), stdin);

    // 移除换行符
    if (s[strlen(s) - 1] == '\n') {
        s[strlen(s) - 1] = '\0';
    }

    printf("初始字符串:%s\n", s);

    reverseString(s); // 调用字符串逆序函数

    printf("逆序后的字符串:%s\n", s);

    return 0;
}

(9)将一个指针所指向的字符串中的大写字母复制到另一个指针所指向的字符数组中。

代码示例:

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

//函数:复制大写字母到新字符串中
void copyUpperCase(char* str, char* result) {
    while (*str != '\0') {
        if (isupper(*str)) {
            *result = *str;
            result++;
        }
        str++;
    }
    *result = '\0'; // 在结果字符串末尾添加字符串结束符
}

int main() {
    char* str = "Hello World";
    char result[100];

    //调用复制大写字母函数
    copyUpperCase(str, result);

    printf("结果为:%s\n", result);

    return 0;
}

(10)输入5个国名并按字母顺序排列后输出。

代码示例:

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

void sortStrings(char arr[][100], int n) {
    //这里要使用到二维数组
    int i, j;
    char temp[100];

    // 使用冒泡排序算法对字符串数组进行排序
    for (i = 0; i < n - 1; i++) {
        for (j = 0; j < n - i - 1; j++) {
            if (strcmp(arr[j], arr[j + 1]) > 0) {
                strcpy(temp, arr[j]);
                strcpy(arr[j], arr[j + 1]);
                strcpy(arr[j + 1], temp);
            }
        }
    }
}

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

    printf("输入五个国家名:\n");

    for (i = 0; i < 5; i++) {
        fgets(arr[i], sizeof(arr[i]), stdin);

        // 移除换行符
        if (arr[i][strlen(arr[i]) - 1] == '\n'){
            arr[i][strlen(arr[i]) - 1] = '\0';
        }
    }

    n = sizeof(arr) / sizeof(arr[0]); // 获取字符串数组的长度

    sortStrings(arr, n); // 调用排序函数

    printf("\n排序后的国家名为:\n");
    for (i = 0; i < n; i++) {
        printf("%s\t", arr[i]);
    }

    return 0;
}

*注:输入一个国家名后按回车再输入下一个(不是通过空格间隔)


关于分析的思路会在后续更新,感谢各位阅读。有疑问可以在评论区留言或私信。

文章来源:https://blog.csdn.net/qq_45580875/article/details/135210538
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。