C语言经典编程题
题目01:在一个已知的字符串中查找最长单词,假定字符串中只含字母和空格,空格用来分隔不同的单词。
int main() { // 用数组定义一个字符串 char array[50] = "zha junju zhamengjun z mengjun"; char *str = array; // 定义指针变量str,指向数组array int len = 0; // 定义变量len,用于计数 int max = 0; // 定义变量max,存放最长单词的长度 char *p = 0; // 定义指针变量p,指向最长单词的首字符 // 判断指针当前指向的字符是不是'\0' while(*str != '\0') { if(*str != ' ') // 判断字符是不是空格 { len++; // 计数加1 // 判断最大长度跟len长度的大小 if(max < len){ max = len; // 如果max小于len,将len赋值给max p = str - len + 1; // 将单词的首字符的地址赋值给指针变量p } str++; // 让指针str指向下一个字符 } else { len = 0; // 如果当前的字符为空格,将len初始化为0,重新计数 str++; //让指针str指向下一个字符 } } // 给最大单词后面添加一个字符串结束标记'\0' *(p + max) = '\0'; printf("最长的单词是%s\n", p); // 在屏幕上输出最长的单词 return 0; }
心得体会:
(1)首先定义一个记录单词长度的变量len和存放最长单词的长度的整形变量max,并初始化max为0;
(2)通过while循环,遍历整个字符串,当遍历到的字符非空格时,变量len依次加1,若len的长度大于max,就将len赋值给max,同时用指针变量p记录单词的首字符地址。并且每判断依次,让指针指向下一个字符。
(3)当遍历到的字符是空格时就将len的长度赋值为0,重新计数,并且让指针str指向下一个字符。
(4)通过给最大单词后面一个字符赋值为‘\0’,以便输出最长单词。
题目02:编写一个int string_len(char *s),返回字符串s的字符长度(不包括\0)。
int string_len(char *s); // 声明函数string_len(char *s) int main() { char *str = "zhamengjun哈哈"; // 利用指针定义一个字符串 // 定义一个变量length,存储函数string_len返回的字符串的字符长度 int length = string_len(str); // 在屏幕上输出打印字符串的字符长度 printf("字符串%s的长度为%d\n", str, length); return 0; } int string_len(char *s) // 定义函数string_len(char *s) { int count = 0; // 记录字符的个数 // 判断指针当前指向的字符是不是'\0', while(*s != '\0') { count++; // 字符个数增加1 s++; // 让指针s指向下一个字符 } return count; // 返回字符串的字符长度 }
心得体会:
(1)定义一个整形变量count记录字符的长度,并初始化初始长度为0;
(2)利用while循环来遍历字符串,直到遇到字符串结束标记‘\0'为止;
(3)每循环一次,计数变量count加1,让指针指向下一个字符;
(4)调用函数,输出结果。
题目03:编程实现将任意的十进制整数转换成任意R进制数(R在2-16之间)。
int main() { int i = 0; // 定义整型变量i计数 int num = 0; // 定义整型变量num,存储十进制整数 int R = 0; // 定义整型变量R,存储要转换的进制数 int arr[100]; // 定义数组arr,存储转换结果 char charOf[] = "012346789ABCDEF"; // 定义字符数组charOf,处理结果为ABCDEF的问题 printf("请输入一个十进制整数\n"); scanf("%d", &num); printf("请输入要转的进制数(在2~16)之间\n"); scanf("%d", &R); printf("%d转%d进制的结果是:", num , R); // 取余法,实现十进制对其它进制的转换 while (num != 0) { arr[i] = num % R; // 将每一次的余数存储在整型数组中 num = num / R; // 得到商num,作除数,继续参与运算 i++; // 计数加1 } while (i > 0) { i--; // 这需先减一次,因为之前i++多加了一个下标 // 将整型数组arr对应的字符数组charOf的值倒序输出 char c = charOf[arr[i]]; printf("%c", c); } printf("\n"); }
心得体会:
(1)定义一个数组arr,将每次十进制取余其它进制的的值保存在数组arr的每一个元素当中,从数组arr[0]开始;
(2)通过while循环,将每一次十进制除以其它进制的商赋值给num,以便作为下一个循环的除数,知道num为0为止;
(3)定义一个数组charOf,并初始化为“012346789ABCDEF”,将整形数组arr对应的字符数组charOf的值倒序输出
(4)要注意计数i的值到了哪一位
题目04:小明从2006年1月1日开始,每三天结识一个美女两天结识一个帅哥,编程实现当输入2006年1月1日之后的任意一天,输出小明那天是结识美女还是帅哥
#include <stdio.h> // 用宏定义参考的年月日 #define Year 2006 #define Month 1 #define Day 1 int main() { int year, month, day; // 定义3个整型变量分别存储用户输入的年、月、日 // 从键盘输入符合条件的日期 do { printf("请输入一个在2006年1月1日之后的日期,格式为:yyyy-m-dd\n"); scanf("%d-%d-%d", &year, &month, &day); } while ((year < Year || month < Month || day <= Day) || (month > 12 || month < 1) || (day > 31 || day < 1 )); int sumDaysOfYear = 0; // 定义整形变量存储相隔年数的总天数 // 利用循环求出相隔年数的总天数 for (int y = Year; y < year; y++) { // 判断是平年还是闰年 if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) { sumDaysOfYear += 366; // 闰年一年366天 } else { sumDaysOfYear += 365; // 平年一年365天 } } int sumDaysOfMonth = 0; // 定义整型变量存储相隔月份的总天数 // 定义一个表示平年各个月份的整型数组 int pingYear[] = {31,28,31,30,31,30,31,31,30,31,30,31}; // 定义一个表示闰年各分月份的整型数组 int yunYear[] = {31,29,31,30,31,30,31,31,30,31,30,31}; // 利用循环求出相隔月份的总天数 for (int m = Month; m < month; m++) { if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { sumDaysOfMonth += yunYear[month - 1]; } else { sumDaysOfMonth += pingYear[month - 1]; } } int days = day - Day; // 定义整型变量days,存储一个月内相隔的天数 int sumDays = 0; // 定义整型变量sumDays,存储两个时间点相隔的总天数 // 得到两个时间点相隔的总天数 sumDays = sumDaysOfYear + sumDaysOfMonth + days; printf("两个时间点相隔%d天\n", sumDays); // 根据相隔的天数,判断小明遇到的人 if((sumDays % 2 == 0) && (sumDays % 3 == 0)) { printf("小明既结识了帅哥又结识了美女!\n"); } else if(sumDays % 2 == 0) { printf("小明结识了帅哥!\n"); } else if (sumDays % 3 == 0) { printf("小明结识了美女!\n"); } else { printf("小明没有结识帅哥和美女\n"); } }
(1)利用for循环遍历,if条件来判断是平年还是闰年,求出相隔年数的累加的天数
(2)同理,利用第一步的方法,求出相隔月数的累加的天数,只是要注意每月的天数,根据平年和闰年的不同分别保存在两个不同的数组中,以便利于累加
(3)将输入的日减1,计算出当月相隔的天数,最后求出两个日期相隔的总天数。
(4)根据总天数取余2和3,判断出小明当天结识的是美女还是帅哥。
题目05:提示用户输入一个正整数n,利用while循环计算并输出:1-2+3-4+5-6+7…+n的和。
int main() { // 1.定义变量存储用户输入的整数 int n = 0; // 2.判断n是否为正整数 while (n <= 0) { // 2.1 提示输入 printf("输入一个正整数:\n"); // 2.2 让用户输入 scanf("%d", &n); } // 3.计算阶乘 int sum = 0; // 存储计算结果 int current = 0; // 当前要累加的数值 while (current < n) { current++; // 如果是偶数,就减 if (current % 2 == 0) { sum -= current; } else { // 如果是奇数,就加 sum += current; } } // 4.输出结果 printf("%d\n", sum); return 0; }
心得体会:
(1)确保从键盘上输入的是一个整数(用while来判断);
(2)用while循环来遍历从1到n的值;
(3)通过奇偶性判断所要累加数值的正负性,奇数就累加,偶数就累减。
题目06:提示用户输入一个正整数n,计算并输出n的阶乘结果:1*2*3*…*n。
int main() { // 1.定义变量存储用户输入的整数 int n = 0; // 2.判断n是否为正整数 while (n <= 0) { // 2.1 提示输入 printf("输入一个正整数:\n"); // 2.2 让用户输入 scanf("%d", &n); } // 3.计算阶乘 int result = 1; // 存储计算结果 int current = 1; // 当前的乘数 while (current <= n) { result *= current; // 累乘每次的乘数 current++; // 乘完一次就++ } // 4.输出阶乘结果 printf("%d! = %d\n", n, result); return 0; }
心得体会:
(1)可以利用for循环或者while循环进行遍历,利用累乘即可求出值。
(2)还可以利用递归来做,更简单。
题目07:编写一个函数,判断某个字符串是否为回文。回文就是从左边开始读 和 从右边开始读 都是一样的,比如"abcba"
int main() { printf("%d\n", isHuiwen("a")); return 0; } /* 返回1代表是回文 返回0代表不是回文 */ int isHuiwen(char *str) { // 1.定义一个指向变量left指向字符串的首字符 char *left = str; // 2.定义一个指向变量right指向字符串的末字符 char *right = str + strlen(str) - 1; while (left < right) { // 如果左边和右边的字符不一样 if (*left++ != *right--) { return 0; } } return 1; }
心得体会:
(1)重点要知道得到字符串的首字符和末字符的地址,取出字符串两头的值来判断是否相等、
(2)保证while条件,只能循环到中间就可以了,利用(left < right)
题目08:编写一个函数void strlink(char s[], char t[]),将字符串t连接到字符串s的尾部。
int main() { char s1[20] = "michael "; char s2[] = "jackson"; strlink(s1, s2); printf("%s\n", s1); return 0; } void strlink(char s[], char t[]) { int i = 0; // 判断s[i]是否为字符串的尾部 while ( s[i] != '\0' ) { i++; } int j = 0; // 拷贝t的内容到s的后面 while ( (s[i] = t[j]) != '\0' ) { i++; j++; } }
心得体会:
(1)通过while循环遍历,得到第一个字符串结束标记‘\0'的位置。
(2)利用第二个while循环,从字符串s结束位置开始,将字符串t依次赋值到s结束位置后面。
题目09:提示用户输入一个正整数n,求出并输出下列结果:1! + 2! + 3! + 4! + ... + n! 要求:用至少两种方式实现(函数名自拟,函数个数不限)
int pieAdd(int n); int main() { // 1.定义变量存储用户输入的整数 int n = 0; // 2.判断n是否为正整数 while (n <= 0) { // 2.1 提示输入 printf("输入一个正整数:\n"); // 2.2 让用户输入 scanf("%d", &n); } // 3.计算结果 int result = pieAdd(n); printf("结果是%d\n", result); return 0; } // 非递归的方式 int pieAdd(int n) { // 1.定义变量保存总和 int sum = 0; // 2.需要累加n次,每次累加的都是一个阶乘值 for (int i = 1; i<=n; i++) { // 3.计算阶乘i! // 3.1 定义变量保存阶乘的结果 int multi = 1; for (int j = 1; j<=i; j++) { multi *= j; } // 4.累加每次的阶乘结果 sum += multi; } // 5.返回和 return sum; } /* // 递归的方式 int sum(int n) // 定义一个sum函数,用于求出每一个阶乘的和。 { if(n == 1) // 定义一个结束条件 return 1; return sum(n - 1) + count(n); // 求出每一个阶乘的累加和 } // 定义和求出一个累加和 int count(int n) { if(n == 1) return 1; return count(n - 1) * n; }
心得体会:
(1)非递归的方式是采用循环累加的方式求出结果的,它是通过将累加和累乘结果求值的。
(2)递归的方式是通过递归函数count计算每一个阶乘的乘积,然后通过另一个递归函数返回值的累加,最后求出结果
(2)递归的方式求值的时候一定要注意定义一个结束条件。
题目10:设计一个函数:将一维整型数组中的元素逆序存放。比如本来是1,3,4,2,逆序存放就变成了:2,4,3,1
void reverse(int array[], int len); int main() { int ages[4] = {1, 3, 4, 2}; // 定义一个数组,并初始化 reverse(ages, 4); for (int i = 0; i<4; i++) // 循环遍历数组,并输出 { printf("%d\n", ages[i]); } return 0; } void reverse(int array[], int len) { // 左边元素的下标(默认是最左边) int left = 0; // 右边元素的下标(默认是最右边) int right = len - 1; // 如果左边元素的下标 < 右边元素的下标 while (left < right) { // 利用中间变量交换两个元素的值 int temp = array[left]; array[left] = array[right]; array[right] = temp; // 交换一次后,左边元素下标增加,右边元素下标减小 left++; right--; } }
心得体会:
(1)首先要明白一点,为什么不能通过sizeof(array) / sizeof(int) 来求出数组元素的个数?因为当数组作为参数传递的时候,函数的参数array实际上当做变量来存储传来的数组首元素的地址。而每一个指针变量占用8个字节。
(2)分别拿出数组首元素和数组尾元素,然后利用中间变量交换两个元素的值。
(3)利用while循环,遍历数组元素,并使left< right保证循环到中间即可,否则每个元素又进行一次交换,结果值没有改变。
(4)函数reverse不需要返回值,因为改变了形参数组也就改变了外面的实参数组,因为数组是按址传递的。