第三章 数组和字符串

习题3-2  单词的长度(word)
输入若干个单词,输出它们的平均长度。单词只包含大写字母和小写字母,用一个或多个空格隔开。

分析:本题核心在于如何把一个个单词区别出来,从题中信息可知,单词之间由空格隔开,因此使用scanf函数读入字符串刚好能把单词区分出来

代码

#include "stdafx.h"
#include "string.h"
#define MAX 1024//单词最大长度姑且记为1024-1

int _tmain(int argc, _TCHAR* argv[])
{
	char buf[MAX];
	int cnt=0,len=0,tlen=0;
	while(scanf("%s",buf)==1){
	    len=strlen(buf);
	//	printf("len=%d\n",len);
		tlen+=len;
		cnt++;
	}
	printf("%d %d %.2lf\n",tlen,cnt,(double)tlen/cnt);
	return 0;
}


习题3-3  乘积的末3位(product)
输入若干个整数(可以是正整数、负数或者零),输出它们的乘积的末3位。这些整数中会混入一些由大写字母组成的字符串,你的程序应当忽略它们。提示:试试看,在执行scanf("%d")时输入一个字符串会怎样?

分析:本题核心为乘积的末三位。本题存在小陷阱,就是参与运算的整数之乘积有可能超过整数的表示范围,而我们知道末三位只与参加运算的每个整数的末三位有关,因此,我们先对输入的整数做处理(包括去除其中的大写字母),然后对每个整数取末三位参加运算,运算的结果也只取末三位。这样,此题的算法框架如下:
while(cin>>a){
      处理a,
      取a的末三位,
      product=product*a%1000;
}

代码:
#include "stdafx.h"
#include "string.h"

int parseStrToInt(char *buf)
{
    int a;//存储解析出来的整数
	int len,base;
	int i,j;
	len=strlen(buf);
	j=0;
	for(i=0;i<len;i++){
	    if(!(buf[i]>='A' && buf[i]<='Z')){
			    buf[j++]=buf[i];
	    } 
	}
	buf[j]='\0';
	len=strlen(buf);
	a=0;
	for(i=0;i<len;i++){
		base=1;
		for(j=0;j<len-i-1;j++){
			base*=10;
		}
		a+=base*(buf[i]-'0'+0);//将相应字符转化为整数的方法:buf[i]-'0'+0
	}
	//printf("a=%d\n",a);
	return a;
}

int _tmain(int argc, _TCHAR* argv[])
{
	char buf[12];
        int a,product=1;
	while(scanf("%s",buf)==1){
            a=parseStrToInt(buf);
	    a%=1000;
	    product=(product*a)%1000;
	}
	printf("%d\n",product);
	return 0;
}


习题3-4  计算器(calculator)
编写程序,读入一行恰好包含一个加号、减号或乘号的表达式,输出它的值。这个运算符保证是二元运算符,且两个运算数均为不超过100的非负整数。运算数和运算符可以紧挨着,也可以用一个或多个空格、TAB隔开。行首末为均可以有空格。提示:选择合适的输入方法可以将问题简化。

分析:本题的核心是输入。题中已明确提出应该选择合适的输入方式,我们知道当使用scanf函数输入整数时,遇非整数则停止接受。因此我们使用scanf接受两个整数,对运算符做单独处理

代码

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
	int x,y;
	double result;
	char op;
	scanf("%d",&x);
	while(scanf("%c",&op)==1){
	  if((op=='+') || (op=='-') || (op=='*') || (op=='/'))
		  break;
	}
	scanf("%d",&y);
	switch(op){
	  case '+': result=x+y;break;
	  case '-': result=x-y;break;
	  case '/': result=(double)x/y;break;//题中表明x,y均为非负整数
	  case '*': result=x*y;break;
	}
	printf(op=='/' ? "%lf\n":"%.0lf\n",result);
	return 0;
}


习题3-5  旋转(rotate)
输入一个n*n字符矩阵,把它左转90度后输出。

分析:本题核心是交换,即把矩阵的行列进行交换,但是注意交换的时候每行每列的开始为i,i,也就是说每行从第i行的第i列开始交换。算法也很简单,1.获得矩阵(我这里从文件中读取矩阵)。2.旋转。3.打印

代码

#include "stdafx.h"
#include "stdio.h"
#define MAX 10//假设每行最多10个字符

void print(char buf[][MAX],int size)
{//输出
	int i,j;
	int flag=0;
    for(i=0;i<size;i++){
		for(j=0;j<size;j++){
			printf(flag++ ? " %c":"%c",buf[i][j]);
		}
		flag=0;
		printf("\n");
	}
}

int input(char (*buf)[MAX],const char *fileName)
{//若成功返回每行字符的个数,失败返回0
	char c;
	int i=0,j=0,cnt=0;//cnt表示每行有多少个字符
    FILE *fin=fopen(fileName,"rb");//data.in文件每行最多10个字符,最多10行,行数与每行字符数相等
	if(fin){
		while(fscanf(fin,"%c",&c)==1){
			if(c!='\n' && c!=' '){
			    buf[i][j++]=c;
			}
			if(c=='\n'){
			    i++;
				j=0;
			}
		}
		cnt=i+1;
		fclose(fin);
		return cnt;
	}else{

	    return 0;
	}
}

void rotate(char (*buf)[MAX],int size)
{//旋转
    int i,j;
	char tempC;
	for(i=0;i<size;i++){
		for(j=i;j<size;j++){
		    tempC=buf[j][i];
			buf[j][i]=buf[i][j];
			buf[i][j]=tempC;
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	char buf[MAX][MAX];
    char c,tempC;
	int i=0,j=0,cnt=0;//cnt表示每行有多少个字符
	cnt=input(buf,"data.in");
	if(cnt){
		print(buf,cnt);
		printf("------------------------\n");
		rotate(buf,cnt);
		print(buf,cnt);
	}else{
	    printf("请准备好data.in文件!\n");
	}
	return 0;
}


习题3-6  进制转换1(base1)
输入基数b(2<=b<=10)和正整数n(十进制),输出n的b进制表示。

分析:除k取余法

代码

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
	int b,n,x;
	int i=0;
	int buf[sizeof(int)*8];//整数最多的bit数
	scanf("%d%d",&b,&n);
	while(n!=0){
	   x=n%b;
	   buf[i++]=x;
	   n/=b;
	}
	while((--i)>=0){//逆序输出
		printf("%d",buf[i]);
	}
	printf("\n");
	return 0;
}


习题3-7  进制转换2(base2)
输入基数b(2<=b<=10)和正整数n(b进制),输出n的十进制表示。

分析:算法很简单,就是二进制转十进制的算法。本题核心在于如何拆解正整数n,本人使用的方法把正整数当做字符串处理,使用scanf("%s")存入buf字符数组中,字符数组的大小当为sizeof(n)*8+1(如果b=2即二进制时,若整数为4个字节,则buf为32+1即‘\0’).

代码:

#include "stdafx.h"
#include <string.h>
 

#define MAX sizeof(int)*8+1//最长位数 +1是因为末尾应有'\0'

int getBase(int m,int b)
{//参数m表示乘方的幂,b表示进制
    int i,base=1;
	for(i=0;i<m;i++){
	    base*=b;
	}
	printf("base=%d\n",base);
	return base;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int b;
	int value=0,len,base;
    int i;
	char buf[MAX];//最长位数,超出长度不做处理
	scanf("%d%s",&b,buf);
	printf("buf=%s\n",buf);
	len=strlen(buf);
	for(i=0;i<len;i++){
	   base=getBase(len-1-i,b);
	   value+=(buf[i]-'0'+0)*base;
	}
	printf("%d\n",value);
	return 0;
}

//2 11111111111111111111111111111110


习题3-8 手机键盘(keyboard)
输入一个由小写字母组成的英文单词,输出用手机的默认英文输入法的敲键序列。例如要打出pig这个单词,需要按1次p,3次i,(稍作停顿后)1次g,记为p1i3g1(显然,书中这部分描述存在明显的错误,应以这里的描述为准)。

分析:本题算法框架很简单,输出每个字符极其对应的位置。本题核心在于如何找到各个字母需要的按键次数,所以本题的关键在如何组织手机键盘,我的做法是用一个数组记录各个字母需要按键的次数:int key_times[26]={1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};key_times下标为26个英文字母的序号,如a为0,b为1,c为2,其值对应需要按键的次数。

代码

#include "stdafx.h"
#include "string.h"

#define MAX 1024+1//姑且认为最长单词长度为1024
 
int key_times[26]={1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};//key_times下标为26个英文字母的序号,如a为0,b为1,c为2,其值对应需要按键的次数

int _tmain(int argc, _TCHAR* argv[])
{
	int i,pos;
	char buf[MAX];
	scanf("%s",buf);
	for(i=0;i<strlen(buf);i++){
	   pos=buf[i]-'a'+0;
	   printf("%c%d",buf[i],key_times[pos]);
	}
	printf("\n");
	return 0;
}




你可能感兴趣的:(c,算法,字符串,数组)