目录
3-1:日期格式转化(Date Format Convention)
5-2: 24⼩时制-12⼩时制转换(24-hour to 12-hour)
5-6:通用产品代码(UPC, Universal Production Code)
5-10:将百分制转换为等级制(Centesimal-grade to Letter-grade)
6-2:最大公约数(GCD, Greatest Common Divisor)
6-6:偶数平⽅(Square of Even Number)
7-12:表达式求值(Expression Evaluation)
13-01:最大最小单词简略版(The Biggest and Smallest Words)
前言
请仔细阅读题目,不保证以后icoding不会改变题目。
同时,希望大家可以自主完成icoding,而不是将其变为icopying,本文仅提供参考,更多的是希望思路受阻的同学可以得到启示。
一、实验一
2-4:计算税金(Tax)
题目:
编写⼀个程序,要求⽤户输⼊⼀个美元数量,然后显示出增加 5% 税率后的相应⾦额。
Enter an amount: 100.00
with tax added: $105.00
输⼊的⾦额为⼤于 0 的两位数浮点数。
#include<stdio.h>
int main()
{
float a;
scanf("%f",&a);
a=a+a*0.05;
printf("%.2f",a);
return 0;
}
2-7:计算账单(Bills)
题目:
编写⼀个程序,要求⽤户输出⼀个美元数量,然后显示出如何⽤最少20美元、10美元、5美元和1美元来付款。
Enter a dollar amount: 93
$20 bills: 4
$10 bills: 1
$5 bills: 0
$1 bills: 3
#include <stdio.h>
int main(void)
{
int money, a, b, c, d;
printf("Enter a dollar amount: ");
scanf("%d", &money);
a = money / 20;
b = (money - a *20) / 10;
c = (money - a * 20 - b * 10) / 5;
d = (money - a * 20 - b * 10 - c * 5) / 1;
printf("$20 bills: %d ", a );
printf("$10 bills: %d", b);
printf("$5 bills: %d", c);
printf("$1 bills: %d", d);
return 0;
}
2-8:还贷计算(Loan Balance)
题目:
编程计算第⼀、第⼆、第三个⽉还贷后剩余的贷款⾦额。
Enter amout of loan: 20000.00
Enter interest rate: 6.0
Enter monthly payment: 386.66
Balance remaining after first payment: $19713.34
Balance remaining after second payment: $19425.25
Balance remaining after third payment: $19135.71
提示:每个月的贷款余额减去还款金额后,还需要加上贷款余额与月利率的乘积。月利率的计算方法是把用户输入的利率转换成百分数再除以12。
#include <stdio.h>
int main(void)
{
float a, b, c, d, f, g, ll;
scanf("%f", &a);
scanf("%f", &b);
scanf("%f", &c);
ll = b / 1200;
d = (a - c) + a * ll;
f =(d - c )+ d * ll ;
g = (f - c) + f * ll;
printf("Balance remaining after first payment:%.2f\n", d);
printf("Balance remaining after second payment:%.2f\n", f);
printf("Balance remaining after third payment:%.2f\n", g);
return 0;
}
3-1:日期格式转化(Date Format Convention)
题目:
编写⼀个程序,以⽉/⽇/年(即 mm/dd/yy)的格式接受⽤户录⼊的⽇期信息,并以年⽉⽇(即yyyymmdd)的格式将其显示出来。
Enter a date (mm/dd/yyyy): 2/17/2011
You entered the date 20110217
#include <stdio.h>
int main()
{
int mm, dd, yyyy;
printf("Enter a date (mm/dd/yyyy): ");
scanf("%d/%d/%d", &mm, &dd, &yyyy);
printf("You entered the date %.4d%.2d%.2d", yyyy, mm, dd);
return 0;
}
3-6:分数加法(Fraction Addition)
题目:
修改如下程序( 3.2 节的 addfrac.c ),使⽤户可以同时输⼊两个分数,中间⽤加号隔开:
Enter two fractions separated by a plus sign: 5/6+3/4
The sum is 38/24
#include <stdio.h>
int main(void)
{
int num1, denom1, num2, denom2, result_num, result_denom;
printf("Enter two fractions separated by a plus sign:");
scanf("%d/%d+%d/%d", &num1, &denom1,&num2, &denom2);
result_num = num1*denom2 + num2*denom1;
result_denom = denom1*denom2;
printf("The sum is %d/%d\n", result_num, result_denom);
return 0;
}
二、实验二
5-2: 24⼩时制-12⼩时制转换(24-hour to 12-hour)
题目:
编写⼀个程序,要求⽤户输⼊ 24 ⼩时制的时间,将其转换为 12 ⼩时制的格式。
Enter a 24-hour time: 21:11
Equivalent 12-hour time: 9:11 PM
Enter a 24-hour time: 0:01
Equivalent 12-hour time: 12:01 AM
注意,不要把12:00显示为0:00。
#include<stdio.h>
int main()
{
int a,b,c;
scanf("%d:%d", &a, &b);
c = a - 12;
if (a>12)
printf("Equivalent 12-hour time: %d:%.2d PM\n", c, b);
if(a<12)
{
if(a==0)
printf("Equivalent 12-hour time: %d:%.2d AM\n", a+12, b);
else
printf("Equivalent 12-hour time: %d:%.2d AM\n", a, b);
}
if(a==12)
printf("Equivalent 12-hour time: %d:%.2d PM\n", a, b);
return 0;
}
5-4: 风速等级与描述(Wind Speed)
题目:
下⾯是⽤于测量⻛⼒的蒲福⻛⼒等级的简化版,编写⼀个程序,要求⽤户输⼊⻛速(海⾥/⼩时),然后显示相应的描述。
速率(海⾥/⼩时) | 描述 |
---|---|
⼩于 1 | Calm(⽆⻛) |
1~3 | Light air(轻⻛) |
4~27 | Breeze(微⻛) |
28~47 | Gale(⼤⻛) |
48~63 | Storm(暴⻛) |
⼤于63 | Hurricane(飓⻛) |
输出范例:Enter a wind speed: 1
Light air
Enter a wind speed: 27
Breeze
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
if(a<1)
printf("Calm\n");
if(a>=1)
{if(a<=3)
printf("Light air\n");
}
if(a>3)
{if(a<=27)
printf("Breeze");}
if(a>27)
{if(a<=47)
printf("Gale");
}
if(a>47)
{if(a<=63)
printf("Storm");
}
if(a>63)
printf("Hurricane");
return 0;
}
5-6:通用产品代码(UPC, Universal Production Code)
题目:
修改如下(4.1 节的upc.c)程序,使其可以检测 UPC 的有效性。在⽤户输⼊UPC后,程序将输出 VALID 或 NOT VALID 。
输出范例:
Enter the first (single) digit: 0
Enter first group of five digits: 13800
Enter second group of five digits: 15173
Enter the last (single) digit: 5
VALID
Enter the first (single) digit: 0
Enter first group of five digits: 51500
Enter second group of five digits: 24128
Enter the last (single) digit: 7
NOT VALID
#include <stdio.h>
int main(void)
{
int d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5, first_sum, second_sum, total;
printf("Enter the first (single) digit:");
scanf("%1d", &d);
printf("Enter the first group of five digits:");
scanf("%1d%1d%1d%1d%1d", &i1, &i2, &i3, &i4, &i5);
printf("Enter the second group of five digits:");
scanf("%1d%1d%1d%1d%1d", &j1, &j2, &j3, &j4, &j5);
int las;scanf("%d",&las);
first_sum = d + i2 + i4 + j1 + j3 + j5;
second_sum = i1 + i3 + i5 + j2 + j4;
total = 3*first_sum + second_sum;
int rus=9-((total-1)%10);
if(rus==las)printf("VALID");
else printf("NOT VALID");
return 0;
}
5-10:将百分制转换为等级制(Centesimal-grade to Letter-grade)
题目:
利⽤switch语句编写⼀个程序,把⽤数字表示的成绩转化为字⺟表示的等级。
使⽤下⾯的等级评定规则:A为90~100,B为80~89,C为70~79,D为60~69,F为0~59。如果成绩⾼于100或低于0显示出错信息。
输出范例:
Enter numerical grade: 84
Letter grade: B
Enter numerical grade: -1
Error, grade must be between 0 and 100.
提示:把成绩拆分成 2 个数字,然后使⽤ switch 语句判定⼗位上的数字。
#include<stdio.h>
int main()
{
int a, b;
scanf("%d",&a);
b = a / 10;
if(a<0)
printf("Error, grade must be between 0 and 100.\n");
else
{switch(b)
{case 0: case 1: case 2 : case 3 : case 4 : case 5:
printf("Letter grade: F\n");
break;
case 6 : printf("Letter grade: D\n");
break;
case 7 : printf("Letter grade: C\n");
break;
case 8 : printf("Letter grade: B\n");
break;
case 9 : case 10 :
printf("Letter grade: A\n");
default:
printf("Error, grade must be between 0 and 100.\n");
}
}
return 0;
}
6-2:最大公约数(GCD, Greatest Common Divisor)
题目:
编写程序,要求⽤户输⼊两个整数,然后计算这两个整数的最⼤公约数(GCD, Greatest Common Divisor)。
输出范例:
Enter two integers: 12 28
Greatest common divisor: 4
Enter two integers:1 9
Greatest common divisor:1
提示:求最⼤公约数的经典算法 Euclid 算法如下:
分别让变量 m 和 n 存储两个整数。如果 n 为 0,那么停⽌操作,m 中的值是 GCD ;否则计算 m 除以 n 的余数,把 n 保存到 m 中,并把余数保存到 n 中;重复上述操作,每次都先判断n是否为 0 。
#include<stdio.h>
int main()
{
int m,n,s;
scanf("%d%d",&m,&n);
if(m<n)
{
s=m;m=n;n=s;
}
while(n!=0)
{
s=n;
n=m%n;
m=s;
}
printf("%d",m);
return 0;
}
6-4:股经纪人的佣金(Brokerage)
题目:
在下列程序( 5.2 节的 broker.c )中添加循环,以便⽤户可以输⼊多笔交易并且程序可以计算每次的佣⾦。程序在⽤户输⼊的交易额为 0 时终⽌。
输出范例:
Enter value of trade: 30000
Commission:$166.00
Enter value of trade: 20000
Commission:$144.00
Enter value of trade: 0
#include <stdio.h>
int main(void)
{
float commission, value;
for(;;)
{printf("Enter value of trade: ");
scanf("%f", &value);
if(value ==0)break;
else
{if (value < 2500.00f)
commission = 30.00f + .017f * value;
else if (value < 6250.00f)
commission = 56.00f + .0066f * value;
else if (value < 20000.00f)
commission = 76.00f + .0034f * value;
else if (value < 50000.00f)
commission = 100.00f + .0022f * value;
else if (value < 500000.00f)
commission = 155.00f + .0011f * value;
else
commission = 255.00f + .0009f * value;
if (commission < 39.00f)
commission = 39.00f;
printf("Commission: $%.2f\n\n", commission);
} }
return 0;
}
6-6:偶数平⽅(Square of Even Number)
题目:
编写程序,提示⽤户输⼊⼀个数 n,然后显示出 1~n 的所有偶数的平⽅值。
输出范例:
Enter a number: 100
4
16
36
64
100
Enter a number: 50
4
16
36
#include<stdio.h>
int main()
{int n, a,b;
scanf("%d",&n);
for(a=2;a<=n;a =a+2)
{b = a*a;
printf("%d\n",b);
}
return 0;
}
6-8:日历(Calendar Month)
题目:
编写程序显示单⽉的⽇历。⽤户指定这个⽉的天数和该⽉起始⽇是星期⼏。
输出范例:
Enter number of days in month: 31
Enter starting day of the week(1=Sun, 7=Sat): 3
日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
#include<stdio.h>
int main()
{
int num,st;
scanf("%d%d",&num,&st);
printf("日 一 二 三 四 五 六\n");
for(int i=1;i<=st-1;i++)
printf(" ");
for(int i=1,j=st;i<=num;i++,j++)
{
if(i<10)
printf("%d ",i);
else
printf("%d ",i);
if(j==7)
{
j=0;printf("\n");
}
}
return 0;
}
三、实验三
7-4:翻译(Translation)
题目:
编写程序可以把字⺟格式的电话号码翻译成数值格式:
Enter phone number: CALLATT
2255288
如果没有电话在身边,参考这⾥给出的字⺟在键盘上的对应关系:(2=ABC,3=DEF,4=GHI,5=JKL,6=MNO,7=PQRS,8=TUV,9=WXYZ)原始电话号码中的⾮字⺟字符(例如数字或标点符号)保持不变:
Enter phone number: 1-800-COL-LECT1-800-265-5328
可以假设任何⽤户输⼊的字⺟都是⼤写字⺟。
输出范例:
Enter phone number: 1-DCKS-A2D-OLED
1-3257-223-6533
#include<stdio.h>
int main()
{
char a;
for(;a != '\n';)
{a = getchar();
switch(a)
{case 'A': case 'B': case 'C' :
a = 2; printf("2");break;
case 'D' : case 'E': case 'F':
a = 3;printf("3");break;
case 'G': case 'H': case 'I':
a = 4;printf("4");break;
case 'J': case 'K': case 'L':
a = 5;printf("5");break;
case 'M': case 'N': case 'O':
a = 6;printf("6");break;
case 'P': case 'Q': case 'R': case 'S':
a = 7;printf("7");break;
case 'T': case 'U': case 'V':
a = 8;printf("8");break;
case 'W': case 'X': case 'Y': case 'Z':
a = 9;printf("9");break;
default: printf("%c",a);
}
}
return 0;
}
7-12:表达式求值(Expression Evaluation)
题目:
编写程序对表达式求值。
Enter an expression: 1+2.5*3
Value of expression: 10.5
表达式中的操作数是浮点数,运算符是+、-、*和/。表达式从左向右求值(所有运算符的优先级都⼀样)。
输出范例:
Enter an expression: 2+3*4-5/2
Value of expression: 7.5
#include<stdio.h>
int main()
{
float a,b;
char c;
scanf("%f",&a);
for(;;)
{
c = getchar();
if(c == '\n')
break;
scanf("%f",&b);
switch(c)
{case '+':
a = a + b;break;
case '-':
a = a - b;break;
case '*':
a = a * b;break;
case '/':
a = a / b; break;
}
}
printf("Value of expression: %.1f",a);
return 0;
}
8-2:出现次数(Number Occurrences)
题目:
修改如下程序(8.1 节的 repdigit.c),使其打印⼀份列表,显示出每个数字在数中出现的次数。
输出范例:
Enter a number: 41271092
Digit: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
Occurrences: | 1 | 2 | 2 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
#include<stdio.h>
int main()
{
int a[10]={0};
char c;
int i=0;
printf("Digit: 0 1 2 3 4 5 6 7 8 9");
printf("Occurrences:");
for(;;)
{ c = getchar();
if (c == '\n')
break;
a[c -'0']++;}
for(;i <10;i ++)
printf("%d",a[i]);
return 0;
}
8-9:随机步法(Random Walk)
题目:
编写程序,⽣成⼀种贯穿10×10字符数组(初始时全为字符'.')的“随机步法”。程序必须随机地从⼀个元素“⾛到”另⼀个元素,每次都向上、向下、向左或向右移动⼀个元素位置。已访问过的元素按访问顺序⽤字⺟A到Z进⾏标记。
下⾯是⼀个输出示例:
A | . | . | . | . | . | . | . | . | . |
---|---|---|---|---|---|---|---|---|---|
B | C | D | . | . | . | . | . | . | . |
. | F | E | . | . | . | . | . | . | . |
H | G | . | . | . | . | . | . | . | . |
I | . | . | . | . | . | . | . | . | . |
J | . | . | . | . | . | . | . | Z | . |
K | . | . | R | S | T | U | V | Y | . |
L | M | P | Q | . | . | . | W | X | . |
. | N | O | . | . | . | . | . | . | . |
利⽤srand函数和rand函数(⻅程序deal.c)产⽣随机数,然后查看次数除以4的余数。余数⼀共有4种可能的值(0、1、2和3),指示下⼀次移动的4种可能⽅向。在执⾏移动之前,需要检查两项内容:⼀是不能⾛到数组外⾯,⼆是不能⾛到已有字⺟标记的位置。只要⼀个条件不满⾜,就得尝试换⼀个⽅向移动。如果4个⽅向都堵住了,程序就必须终⽌了。下⾯是提前结束的⼀个示例:
A | B | G | H | I | . | . | . | . | . |
---|---|---|---|---|---|---|---|---|---|
. | C | F | O | J | K | . | . | . | . |
. | D | E | N | M | L | . | . | . | . |
. | . | . | . | . | . | . | . | . | . |
. | . | . | . | . | . | . | . | . | . |
. | . | . | . | . | . | . | . | . | . |
. | . | . | . | . | . | . | . | . | . |
. | . | . | . | . | . | . | . | . | . |
. | . | . | . | . | . | . | . | . | . |
因为Y的4个⽅向都堵住了,所以没有地⽅可以放置下⼀步的Z了。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
char mapp[15][15];
for(int i=1;i<=10;i++)
for(int j=1;j<=10;j++)
mapp[i][j]='.';
srand((unsigned)time(NULL));
mapp[1][1]='A';
for(int x=1,y=1,t=1;t<=25;)
if(x+1<=10||x-1>=1||y+1<=10||y-1>=1)
if(mapp[x+1][y]=='.'||mapp[x-1][y]=='.'||mapp[x][y+1]=='.'||mapp[x][y-1]=='.')
{
// printf("%d %d\n",x,y);
int m=rand()%4;
int ox=x,oy=y;
switch(m)
{
case 0:
x++;break;
case 1:
x--;break;
case 2:
y++;break;
case 3:
y--;break;
}
if(x>=1&&x<=10&&y>=1&&y<=10&&mapp[x][y]=='.')
mapp[x][y]='A'+t++;
else {x=ox;y=oy;}
}
else break;
else break;
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
printf("%c ",mapp[i][j]);
printf("\n");
}
return 0;
}
8-15:加密(Encryption)
题目:
已知的最古⽼的⼀种加密技术是凯撒加密(得名于 Julius caesar)。该⽅法把⼀条消息中的每个字⺟⽤字⺟表中固定距离之后的那个字⺟来替代。(如果越过了字⺟Z,会绕回到字⺟表的起始位置。例如,如果每个字⺟都⽤字⺟表中两个位置之后的字⺟代替,那么Y就被替换为A,Z就被替换为B。)
编写程序⽤凯撒加密⽅法对消息进⾏加密。⽤户输⼊待加密的消息和移位计数(字⺟移动的位置数⽬):
Enter message to be encrypted: Go ahead, make my day.
Enter shift amount (1-25): 3
Encrypted message: Jr dkhdg, pdnh pb gdb.
注意,当⽤户输⼊26与移位计数的差值时,程序可以对消息进⾏解密:
Enter message to be encrypted: Jr dkhdg, pdnh pb gdb.
Enter shift amount (1-25): 23
Encrypted message: Go ahead, make my day
不是字⺟的那些字符不要改动。此外,加密时不要改变字⺟的⼤⼩写。
输出范例:
Enter message to be encrypted: Hello, world!
Enter shift amount (1-25): 3
Encrypted message: Khoor, zruog!
Enter message to be encrypted: Khoor, zruog!
Enter shift amount (1-25): 23
Encrypted message: Hello, world!
#include<stdio.h>
#include<string.h>
int main()
{
char c[1000];int wy,l;
gets(c);
l=strlen(c)-1;
scanf("%d",&wy);
for(int i=0;i<=l;i++)
{
if(c[i]>='a'&&c[i]<='z')
{
if(c[i]+wy<='z')
printf("%c",c[i]+wy);
else
printf("%c",c[i]+wy-26);
continue;
}
if(c[i]>='A'&&c[i]<='Z')
{
if(c[i]+wy<='Z')
printf("%c",c[i]+wy);
else
printf("%c",c[i]+wy-26);
continue;
}
printf("%c",c[i]);
}
return 0;
}
四、实验四
10-1:栈(Stack)
题目:
修改如下程序(10.2节的栈示例)使它存储字符而不是整数。
增加 main 函数,用来要求用户输入一串圆括号或花括号,然后指出它们之间的嵌套是否正确。
输出范例:
Enter parentheses and/or braces: ()({})({})
Parentheses/braces are nested properly
Enter parentheses and/or braces: ((}
Parentheses/braces are NOT nested properly
#include <stdbool.h> /* C99 only */
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 100
/* external variables */
char contents[STACK_SIZE];
int top = 0;
void stack_overflow(void)
{
printf("Stack overflow\n");
exit(EXIT_FAILURE);
}
void stack_underflow(void)
{
printf("Stack underflow\n");
exit(EXIT_FAILURE);
}
void make_empty(void)
{
top = 0;
}
bool is_empty(void)
{
return top == 0;
}
bool is_full(void)
{
return top == STACK_SIZE;
}
void push(char ch)
{
if (is_full())
stack_overflow();
else
contents[top++] = ch;
}
char pop(void)
{
if (is_empty())
stack_underflow();
else
return contents[--top];
return '\0'; /* prevents compiler warning due to stack_underflow() call */
}
int main(void)
{
char ch;
int correct = 1;
while(correct && (ch = getchar()) != '\n')
{if(ch == '(' || ch == '{')
push(ch);
else if(ch == ')')
correct = !is_empty() && pop() =='(';
else if(ch == '}')
correct = !is_empty() && pop() == '{';
}
if(correct && is_empty())
{printf("Parentheses/braces are nested properly\n");}
else printf("Parentheses/braces are NOT nested properly\n");
return 0;
}
12-01:逆序(Reversal)
题目:
编写程序读一条消息,然后逆序打印出这条消息。
输出范例:
Enter a message: Don't get mad, get even.
Reversal is: .neve teg ,dam teg t'noD
Enter a message: Hello, world!
Reversal is: !dlrow ,olleH
提示:⼀次读取消息中的⼀个字符(⽤getchar函数),并且把这些字符存储在数组中,当数组写满或者读到字符 '\n' 时停⽌读⼊。
#include<stdio.h>
int main()
{
int i =0;
char a[20000];
for(i=0;;)
{a[i]=getchar();
if(a[i]=='\n')
{i--;
break;}
i ++;
}
printf("Reversal is: ");
for(;i>=0;i--){
printf("%c",a[i]);
}
return 0;
}
13-01:最大最小单词简略版(The Biggest and Smallest Words)
题目:
编写程序找出一组单词中“最小”单词和“最大”单词。
用户输入单词后,程序根据字典顺序决定排在最前面和最后面的单词。
当用户输入4个字母的单词时,程序停止读入。假设所有单词都不超过20个字母。
输出范例1:
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
输出范例2:
Enter word: computer
Enter word: ink
Enter word: light
Enter word: bookrack
Enter word: book
Smallest word: book
Largest word: light
#include <stdio.h>
#include <string.h>
int main()
{
char current[21];
char max[21],min[21];
scanf("%s",current);
strcpy(max,current);
strcpy(min,current);
for(;;)
{
scanf("%s",current);
if(strlen(current)!= 4)
{
if(strcmp(current,max)>=0)
{
strcpy(max,current);
}
if(strcmp(current,min)<=0){
strcpy(min,current);
}
}
else
{if(strcmp(current,max)>=0)
{
strcpy(max,current);
}
if(strcmp(current,min)<=0){
strcpy(min,current);
}
break;}
}
printf("Smallest word: %s\n",min);
printf("Largest word: %s\n",max);
return 0;
}
五、实验五
16-3-01 main函数改造。
题目:
修改16.3节的invertory.c程序,使 inventory 和 num_parts 为 main 函数的局部变量。
本小题只需完成 main 函数的改造即可,相关结构及函数声明如下:
#define NAME_LEN 25
#define MAX_PARTS 100
struct part {
int number;
char name[NAME_LEN+1];
int on_hand;
};
int read_line(char str[], int n);
int find_part(int number, const struct part inv[], int np);
void insert(struct part inv[], int *np);
void search(const struct part inv[], int np);
void update(struct part inv[], int np);
void print(const struct part inv[], int np);
该部分声明已包含在 “lab51.h”中。
#include <stdio.h>
#include <stdlib.h>
#include "lab51.h" // 请不要删除本行头文件,否则检查不通过
int main(){
char code;
struct part inventory[MAX_PARTS];
int num_parts = 0;
for(;;){
printf("Enter operation code: ");
scanf("%c",&code);
while(getchar() != '\n')
;
switch(code){
case 'i': insert(inventory,num_parts);
break;
case 's': search(inventory,num_parts);
break;
case 'u': update(inventory,num_parts);
break;
case 'p': print(inventory,num_parts);
break;
case 'q': return 0;
break;
default: printf("Illegal code\n");
}
printf("\n");
}
}
16-3-02 insert 函数改造。
题目:
修改16.3节的invertory.c程序,使 inventory 和 num_parts 为 main 函数的局部变量。
本小题只需完成 insert 函数的改造即可,相关结构及函数声明如下:
#define NAME_LEN 25
#define MAX_PARTS 100
struct part {
int number;
char name[NAME_LEN+1];
int on_hand;
};
int read_line(char str[], int n);
int find_part(int number, const struct part inv[], int np);
void insert(struct part inv[], int *np);
void search(const struct part inv[], int np);
void update(struct part inv[], int np);
void print(const struct part inv[], int np);
该部分声明已包含在 “lab51.h”中。
#include <stdio.h>
#include <stdlib.h>
#include "lab51.h" // 请不要删除本行头文件,否则检查不通过
void insert(struct part inv[], int *np){
int part_number;
if(*np == MAX_PARTS){
printf("Database is full; can't add more parts.\n");
return;
}
printf("Enter part number: ");
scanf("%d",&part_number);
if(find_part(part_number,inv,*np) >= 0){
printf("Part already exists.\n");
return;
}
inv[*np].number = part_number;
printf("Enter part name: ");
read_line(inv[*np].name, NAME_LEN);
printf("Enter quantity on hand: ");
scanf("%d",&inv[*np].on_hand);
(*np) ++;
}
16-3-03 search 函数改造。
题目:
修改16.3节的invertory.c程序,使 inventory 和 num_parts 为 main 函数的局部变量。
本小题只需完成 search 函数的改造即可,相关结构及函数声明如下:
#define NAME_LEN 25
#define MAX_PARTS 100
struct part {
int number;
char name[NAME_LEN+1];
int on_hand;
};
int read_line(char str[], int n);
int find_part(int number, const struct part inv[], int np);
void insert(struct part inv[], int *np);
void search(const struct part inv[], int np);
void update(struct part inv[], int np);
void print(const struct part inv[], int np);
该部分声明已包含在 “lab51.h”中。
#include <stdio.h>
#include <stdlib.h>
#include "lab51.h" // 请不要删除本行头文件,否则检查不通过
void search(const struct part inv[], int np)
{
int i,number;
printf("Enter part number: ");
scanf("%d",&number);
i = find_part( number, inv, np);
if(i >=0){
printf("Part name: %s\n",inv[i].name);
printf("Quantity on hand: %d\n", inv[i].on_hand);
}else
printf("Part not found.\n");
}
16-3-04 update 函数改造。
题目:
修改16.3节的invertory.c程序,使 inventory 和 num_parts 为 main 函数的局部变量。
本小题只需完成 update 函数的改造即可,相关结构及函数声明如下:
#define NAME_LEN 25
#define MAX_PARTS 100
struct part {
int number;
char name[NAME_LEN+1];
int on_hand;
};
int read_line(char str[], int n);
int find_part(int number, const struct part inv[], int np);
void insert(struct part inv[], int *np);
void search(const struct part inv[], int np);
void update(struct part inv[], int np);
void print(const struct part inv[], int np);
该部分声明已包含在 “lab51.h”中。
#include <stdio.h>
#include <stdlib.h>
#include "lab51.h" // 请不要删除本行头文件,否则检查不通过
void update(struct part inv[], int np){
int i,number,change;
printf("Enter part number: ");
scanf("%d",&number);
i = find_part(number,inv,np);
if(i >= 0){
printf("Enter change in quantitiy on hand: ");
scanf("%d",&change);
inv[i].on_hand += change;
}else
printf("Part nont found.\n");
}
16-3-05 print 函数改造。
题目:
修改16.3节的invertory.c程序,使 inventory 和 num_parts 为 main 函数的局部变量。
本小题只需完成 print 函数的改造即可,相关结构及函数声明如下:
#define NAME_LEN 25
#define MAX_PARTS 100
struct part {
int number;
char name[NAME_LEN+1];
int on_hand;
};
int read_line(char str[], int n);
int find_part(int number, const struct part inv[], int np);
void insert(struct part inv[], int *np);
void search(const struct part inv[], int np);
void update(struct part inv[], int np);
void print(const struct part inv[], int np);
该部分声明已包含在 “lab51.h”中。
#include <stdio.h>
#include <stdlib.h>
#include "lab51.h" // 请不要删除本行头文件,否则检查不通过
void print(const struct part inv[], int np){
int i;
printf("Part Number Part Name "
"Quantity on Hand\n");
for(i = 0;i < np;i++)
printf("%7d %-25s%11d\n",inv[i].number,inv[i].name,inv[i].on_hand);
}
六、实验六
链表:01-软件界面控制
题目:
实现一个数字选项式的启动界面,程序输入数据为(1-8),参考界面如下:
1.显示所有商品的信息
2.修改某个商品的信息
3.插入某个商品的信息
4.删除某个商品的信息
5.查找某个商品的信息
6.商品存盘并退出系统
7.对商品价格进行排序
8.(慎用)删除所有内容
其他.不存盘并退出系统
程序当输入1-8时,执行相关功能,完成后再次显示菜单让用户选择。当输入其它数值时,程序不存盘并退出系统。
本小题只需实现 main 函数即可,相关结构及函数声明如下:
#define GOODS_FILE_NAME "goodsinfo.txt"
#define MAX_ID_LEN 30
#define MAX_NAME_LEN 30
#define MAX_PRICE_LEN 30
#define MAX_DISCOUNT_LEN 30
typedef struct {
char goods_id[MAX_ID_LEN];
char goods_name[MAX_NAME_LEN];
int goods_price;
char goods_discount[MAX_DISCOUNT_LEN];
int goods_amount;
int goods_remain;
} GoodsInfo;
typedef struct node
{
GoodsInfo data;
struct node *next;
} GoodsList;
GoodsInfo read_goods_info();
void init_list(GoodsList **pL);
void destory_list(GoodsList **pL);
void destory_list_and_file(GoodsList **pL);
int save_to_file(GoodsList *L);
void output_one_item(GoodsList *L);
void output_all_items(GoodsList *L);
bool insert_item(GoodsList *L, GoodsInfo item, int choice);
bool delete_item(GoodsList *L, char* goods_id);
GoodsList* search_item(GoodsList *L, char* goods_id);
bool change_item(GoodsList *L, char* goods_id, GoodsInfo new_info);
void bubble_sort(GoodsList *L);
int read_line(char str[], int n);
该部分声明已包含在 “lab52.h”中。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
int main()
{
GoodsList *list;
init_list(&list);
char idd[MAX_ID_LEN]={0};
int x=0;
for(;;)
{
printf("1.显示所有商品的信息\n");
printf("2.修改某个商品的信息\n");
printf("3.插入某个商品的信息\n");
printf("4.删除某个商品的信息\n");
printf("5.查找某个商品的信息\n");
printf("6.商品存盘并退出系统\n");
printf("7.对商品价格进行排序\n");
printf("8.(慎用)删除所有内容\n");
printf("其他.不存盘并退出系统\n");
int ope;
scanf("%d",&ope);
switch(ope)
{
case 1:
output_all_items(list);
break;
case 2:
printf("输入要修改的商品ID:\n");
read_line(idd,MAX_ID_LEN);
printf("输入商品参数:\n");
if(change_item(list,idd,read_goods_info()))
printf("修改成功!\n");
else
printf("修改失败!\n");
memset(idd,0,sizeof(0));
break;
case 3:
printf("0:插入到链表尾部\n");
printf("1:插入到链表头部\n");
printf("其它正整数:插入到该位置\n");
scanf("%d",&x);
printf("输入商品参数:\n");
if(insert_item(list,read_goods_info(),x))
printf("插入成功!\n");
else
printf("插入失败!\n");
break;
case 4:
printf("输入需要删除的商品ID:\n");
read_line(idd,MAX_ID_LEN);
if(delete_item(list,idd))
printf("删除成功!\n");
else
printf("删除失败!\n");
memset(idd,0,sizeof(0));
break;
case 5:
printf("输入需要删除的商品ID:\n");
read_line(idd,MAX_ID_LEN);
if(search_item(list,idd)==NULL)
printf("查找失败!\n");
else
{
printf("查找成功!\n");
output_one_item(search_item(list,idd));
}
break;
case 6:
save_to_file(list);
return 0;
break;
case 7:
bubble_sort(list);
break;
case 8:
destory_list_and_file(&list);
break;
default:
destory_list(&list);
return 0;
break;
}
printf("\n");
}
return 0;
}
void output_one_item(GoodsList *p){
printf("%s\t%s\t%d\t%s\t%d\t%d\n",p->data.goods_id,p->data.goods_name,p->data.goods_price,p->data.goods_discount,p->data.goods_amount,p->data.goods_remain);
}
链表:02-初始化
题目:
函数原型:void init_list(GoodsList **L)
其中 *L 为指向链表头结点的指针,L为指向链表头结点指针的地址,init_list首先创建链表的头结点,之后读取goodsinfo.txt(示例文件下载)中的商品信息,并初始化链表,函数执行后,需确保 *L 为指向链表头结点的指针。
init_list 实现商品信息链表的初始化,函数从已有的商品信息文件goodsinfo.txt(示例文件下载)中读入商品信息,并且分配内存保存至链表中。
为了方便在表头插入和删除结点的操作,经常在表头结点(存储第一个元素的结点)的前面增加一个结点,称之为头结点或表头附加结点。这样原来的表头指针由指向第一个元素的结点改为指向头结点,头结点的数据域为空,头结点的指针域指向第一个元素的结点。
#include<ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
void init_list(GoodsList** L)
{
//GoodsList* p;
int i = 0;
*L = (GoodsList*)malloc(sizeof(GoodsList));
if (*L == NULL) {
return;
}
GoodsList* hpead = *L;
GoodsInfo gi;
FILE* fp = fopen("goodsinfo.txt", "a+");
if (fp == NULL) {
perror("fopen()");
return;
}
while (fscanf(fp, "%s %s %d %s %d %d\n", gi.goods_id, gi.goods_name, &gi.goods_price, gi.goods_discount, &gi.goods_amount, &gi.goods_remain) != EOF) {
GoodsList* cur = (GoodsList*)malloc(sizeof(GoodsList));
if (cur == NULL) {
continue;
}
cur->data = gi;
hpead->next = cur;
hpead = hpead->next;
i++;
}
printf("目前有 %d个商品信息 ", i);
}
链表:03-插入
题目:
函数原型:bool insert_item(GoodsList *L, GoodsInfo goodsInfo, int choice),
L为指向链表头结点的指针,函数根据choise的值,将goodsInfo插入到链表的指定位置,如果成功插入,函数返回true,如果未插入,函数返回false。
分别实现头插法、尾插法,中间位置插入三种:
用户输入0,将商品信息插入到链表尾部;
用户输入1,将商品信息插入到链表头部;
用户输入其它正整数i,将商品信息插入到链表中间第i号位置, 例如:输入3,应该在第二个节点后插入新节点
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
bool insert_item(GoodsList *L, GoodsInfo item, int choice)//3插入
{
if(choice==0)
{
GoodsList* i=L;
for(;i->next!=NULL;i=i->next);
GoodsList* n;
n=(GoodsList*)malloc(sizeof(GoodsList));
n->data=item;
n->next=NULL;
i->next=n;
CurrentCnt++;
// output_all_items(L);
return 1;
}
if(choice==1)
{
GoodsList* i=L;
GoodsList* n;
n=(GoodsList*)malloc(sizeof(GoodsList));
n->data=item;
n->next=NULL;
GoodsList* tem=i->next;
i->next=n;
n->next=tem;
CurrentCnt++;
// output_all_items(L);
return 1;
}
if(choice<0||choice>CurrentCnt+1)return 0;
GoodsList* i=L;
for(int j=1;j<=choice-1;i=i->next,j++);
GoodsList* n;
n=(GoodsList*)malloc(sizeof(GoodsList));
n->data=item;
n->next=NULL;
GoodsList* tem=i->next;
i->next=n;
n->next=tem;
CurrentCnt++;
// output_all_items(L);
return 1;
}
链表:04-删除节点
题目:
函数原型:bool delete_item(GoodsList *L, char* goods_id)
其中L为指向链表头结点的指针,goods_id为要删除商品的ID;
如果成功删除,函数返回true,否则返回false。
delete_item 根据商品的ID来删除对应的商品信息,商品查找通过字符串比较的方式,查找到后释放对应指针指向的内存区域,完成删除。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
bool delete_item(GoodsList *L, char* goods_id)//4删除
{
for(GoodsList* i=L;i->next!=NULL;i=i->next)
{
GoodsList* n=i->next;
if(!strcmp(n->data.goods_id,goods_id))
{
i->next=n->next;
free(n);
n=NULL;
CurrentCnt--;
return 1;
}
}
return 0;
}
链表:05-查找
题目:
函数原型:GoodsList* search_item(GoodsList *L, char* goods_id)
其中L为指向链表头结点的指针,goods_id为要查找商品的ID;
如果找到该商品,函数返回该商品对应的结点指针,否则返回 NULL.
根据输入的商品 ID 来查找对应的商品信息,商品 ID 的判断用字符串比较的方式来实现,然后调用格式化显示查找到的商品信息.
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
GoodsList* search_item(GoodsList *L, char* n){
while(L!= NULL&&strcmp(L->data.goods_id,n))
L = L->next;
return L;
}
链表:06-修改
题目:
函数原型:bool change_item(GoodsList *L, char* goods_id, GoodsInfo new_info)
其中 L 为指向链表头结点的指针,goods_id 为要修改的商品 ID,new_info 为该商品的最新数据。函数成功修改后返回true,否则返回 false。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
bool change_item(GoodsList *L, char* goods_id, GoodsInfo new_info){
GoodsList *p=search_item(L,goods_id);
if(p!=NULL)
{
p->data= new_info;
return true;
}
return false;
}
链表:07-显示单个节点
题目:
函数原型:void output_one_item(GoodsList *p),函数显示结点为 p 的商品信息。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
void output_one_item(GoodsList *p){
printf("%s\t%s\t%d\t%s\t%d\t%d\n",p->data.goods_id,p->data.goods_name,p->data.goods_price,p->data.goods_discount,p->data.goods_amount,p->data.goods_remain);
}
链表:08-显示所有节点
题目:
函数原型:void output_all_items(GoodsList *L),
L为指针链表头结点的指针,output_all_items 调用 output_one_item 函数,将链表中所有的商品信息以格式化的方式打印输出到屏幕上。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
void output_all_items(GoodsList *L){
while(L->next!=NULL){
output_one_item(L->next);
L = L->next;
}
}
链表:09-释放链表
题目:
函数原型:void destory_list(GoodsList **L),
该函数释放包括头结点在内的所有结点,完成后指向链表头结点的指针为NULL。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
void destory_list(GoodsList **L){
GoodsList*prev=*L;
GoodsList*cur=prev->next;
while(prev!=NULL){
cur=prev->next;
free(prev);
prev=cur;
}
*L=NULL;
CurrentCnt=0;
L=NULL;
}
链表:10-释放链表并删除文件
题目:
函数原型:void destory_list_and_file(GoodsList **L),
该函数调用destory_list释放包括头结点在内的所有结点,将指向链表头结点的指针为NULL,最后删除存储商品信息的文件goodinfo.txt。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
void destory_list_and_file(GoodsList **L){
destory_list(L);
remove(GOODS_FILE_NAME);
*L=NULL;
L=NULL;
}
链表:11-保存文件
题目:
函数原型:int save_to_file(GoodsList *L)
将当前链表所有的商品信息保存到文件 goodsinfo.txt 中,其中L为指向链表头结点的指针,保存成功后,该函数返回商品的数量。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
int save_to_file(GoodsList* L) {
int number = 0;
if (L == NULL)
return 0;
GoodsList* p = L->next;
FILE* fp;
if ((fp = fopen("goodsinfo.txt", "w")) == NULL)
return 0;
while (p != NULL) {
fprintf(fp, "%s\t", p->data.goods_id);
fprintf(fp, "%s\t", p->data.goods_name);
fprintf(fp, "%d\t", p->data.goods_price);
fprintf(fp, "%s\t", p->data.goods_discount);
fprintf(fp, "%d\t", p->data.goods_amount);
fprintf(fp, "%d\n", p->data.goods_remain);
p = p->next;
number++;
}
fclose(fp);
return number;
}
链表:12-排序
题目:
函数原型:void bubble_sort(GoodsList *L)
L为指向链表头结点的指针,该函数利用冒泡排序算法,按价格从低到高对商品进行排序。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
void bubble_sort(GoodsList *L)//12排序
{
if(CurrentCnt==1||!CurrentCnt)return;
for(int j=1;j<CurrentCnt;j++)
for(GoodsList* i=L;i->next->next!=NULL;i=i->next)
{
GoodsList* a=i->next,*b=i->next->next;
if(a->data.goods_price>b->data.goods_price)
{
GoodsList* tem=b->next;
i->next=b;
b->next=a;
a->next=tem;
}
}
}
链表:13-读商品信息
题目:
函数原型:GoodsInfo read_goods_info()
该函数调用read_line及scanf等函数,按“商品ID、商品名称、商品价格、商品折扣、商品数量、商品剩余数量”的顺序让用户输入,并将这些信息保存到 GoodsInfo 结构体中,函数最后返回该结构体。
#include <stdio.h>
#include <stdlib.h>
#include "lab52.h" // 请不要删除本行头文件,否则检查不通过
extern int CurrentCnt; // 请不要删除本行的全局变量声明,否则检查不通过
GoodsInfo read_goods_info()//13读入数据
{
GoodsInfo a;
if(!read_line(a.goods_id,MAX_ID_LEN))
{
GoodsInfo fail;
fail.goods_price=-1;
return fail;
}
read_line(a.goods_name,MAX_NAME_LEN);
scanf("%d",&a.goods_price);
read_line(a.goods_discount,MAX_DISCOUNT_LEN);
scanf("%d%d",&a.goods_amount,&a.goods_remain);
return a;
}