算法提高 9-3摩尔斯电码--memset--scanf

  算法提高 9-3摩尔斯电码  
#include<stdio.h>
#include<string.h>
char str[1005]={'\0'},tmp[1005]={'\0'},c;
int i,j,k;
char alpha[27][5]=
{"*-","-***","-*-*","-**","*","**-*","--*","****","**",
"*---","-*-","*-**","--","-*","---","*--*","--*-","*-*",
"***","-","**-","***-","*--","-**-","-*--","--**"
};//字母表

void compare(char *s)
{
	for(k=0;;k++)
	{
		if(!strcmp(s,alpha[k]))
		{
			c='a'+k;//遇到对的‘人’就给它加上‘a’
			printf("  %c   ",c);
			break;
		}
	}
}
int main()
{
	while(~scanf("%s",str))//这个循环针对整行
	{
		i=0;
		while(1)//这个循环针对摩斯密码的独立单位(字符)
		{
			j=0;
			while(str[i]!='|'&&str[i]!='\0')
			{
				tmp[j]=str[i];
				j++;
				i++;
			}
i++;//因为停止的地方是间隔符或者结束符,要想继续就要给i +1,后来发现这个与scanf("%s")混合产生了意外的bug,因为如果之前输入长字符串,再输入短字符串,本意是到了结尾在结束,为了方便与'|'一起处理,就采用了i++(一开始是想,反正结尾后面也是'\0',i++ 什么的不影响吧)(惨痛的教训:答:实际上第二次s的情况是*'\0'**'\0' puts没有把它显现出来是因为s[1]='\0' 于是就产生了两个字符,真是废物利用哈。。。)
         compare(tmp);
			for(k=0;k<j;k++) tmp[k]='\0';
			/*memset(tmp,0,1005*sizeof(char));*/
			if(str[i]=='\0') break;
		}
		printf("\n");
		//for(k=0;k<i;k++) str[k]='\0';
		memset(str,'\0',sizeof(str));
	}
	return 0;
}
然后学到了两个知识点:
menset和scanf("%s",str)\
 memset
为重置函数,第一个参数是需要重置的数组名,第二个是指定的元素要重置的新值,第三个是要修改的元素范围——从头开始算的n个内存单位,用n*sizeof(char)来表示(也可以是int)(暂时不对(不知为何))—— memset函数按字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。详细解释:
因为第一个程序的数组a是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的,所以你输出没有问题。而第二个程序数组a是整型的,使用 memset还是按字节赋值,这样赋值完以后,每个数组元素的值实际上是0x01010101即十进制的16843009
如果用memset(a,1,20),就是对a指向的内存的20个字节进行赋值,每个都用数1去填充,转为二进制后,1就是00000001,占一个字节。一个int元素是4字节,合一起是0000 0001,0000 0001,0000 0001,0000 0001,转化成十六进制就是0x01010101,就等于16843009,就完成了对一个int元素的赋值。
说明:如果我们想要将某个数组清零,我们通常会使用memset(a,0,sizeof(a))这样的代码来实现(方便而高效),但是当我们想将某个数组全部赋值为无穷大时(例如解决图论问题时邻接矩阵的初始化),就不能使用memset函数而得自己写循环了(写这些不重要的代码真的很痛苦),我们知道这是因为memset是按字节操作的,它能够对数组清零是因为0的每个字节都是0,现在好了,如果我们将无穷大设为0x3f3f3f3f(即#define INF 0x3f3f3f3f),那么奇迹就发生了,0x3f3f3f3f的每个字节都是0x3f!所以要把一段内存全部置为无穷大,我们只需要memset(a,0x3f,sizeof(a))。


memset可以方便的清空一个结构类型的变量或 数组
如:
1
2
3
4
5
6
struct  sample_struct
{
     char  csName[16];
     int  iSeq;
     int  iType;
};
对于变量
1
struct  sample_struct stTest;
一般情况下,清空stTest的方法:
1
2
3
stTest.csName[0]={ '\0' };
stTest.iSeq=0;
stTest.iType=0;
用memset就非常方便:
1
memset (&stTest,0, sizeof (sample_struct));//是sizeof(sample_struct),不是sizeof(struct sample_struct)都可以
如果是数组:
1
structsample_struct TEST[10];
1
memset (TEST,0, sizeof (struct sample_struct)*10);
另外:
如果结构体中有数组的话还是需要对数组单独进行初始化处
理的。
@百度百科


例如:
#include<stdio.h>
#include<string.h>
void rece(char *s)//在函数的接口中可以用 char*s 但当在主函数里*s代表指针指向的内容是只读的,就不能进行修改
{
	memset(s,'b',2*sizeof(char));
}
int main()
{
	char a[777]="nihaoma";
	memset(a,'r',3*sizeof(char));
	puts(a);
	rece(a);
	puts(a);
	return 0;
}
拓展:
memset(void *s, int ch, size_t n);中key实际范围应该在0~~255,因为该函数只能取ch的后八位赋值给你所输入的范围的每个字节,比如int a[5]赋值memset(a,-1,sizeof(int )*5)与memset(a,511,sizeof(int )*5) 所赋值的结果是一样的都为-1;因为-1的二进制码为(11111111 11111111 11111111 11111111)而511的二进制码为(00000000 00000000 00000001 11111111)后八位都为(11111111),所以数组中每个字节,如a[0]含四个字节都被赋值为(11111111),其结果为a[0](11111111 11111111 11111111 11111111),及a[0]=-1,因此无论ch多大只有后八位二进制有效,而八位 二进制 [2]    的范围(0~255)YKQ改。而对字符数组操作时则取后八位赋值给字符数组,其八位值作为 ASCII [3]    码。
scanf这个坑
#include<stdio.h>
int main()
{
		char s[1005]={'\0'};
		while(~scanf("%s",s))
		{
			puts(s);
			/*为什么明明只输出一个“* ”号,
			但是却显示s[4]的值存在(显然是第一次遗留下来的)? */
			if(s[4]=='\0')
			 	printf("yes\n");
			else 
			printf("no\n");	
			printf("%c\n",s[4]);
		}
	return 0;
}
答:实际上第二次s的情况是*'\0'**'\0' puts没有把它显现出来是因为s[1]='\0'
对了,在查找scanf的时候,看到了别人写的有意思的坑和知识点

#include<stdio.h> 
int main() 

char ch1,ch2; 
printf("Input for ch1:n"); 
scanf("%c",&ch1); 
printf("ch1=%cn",ch1); 
printf("Input for ch2:n"); 
scanf("%c",&ch2); 
printf("ch2=%cn",ch2); 
}

表面上看这段程序是没有错的,也可以运行,但运行过程中到 第二个scanf输入值给ch2时,程序并不会停止下来等待你输入,而是直接运行到最后一个printf !

为什么?当时百思不得其解。。。

今天上网查了下才知道,原来scanf是从标准输入缓冲区中读取输入的数据,而%c的字符输入格式会接收回车字符,在输入第一个scanf时输入字符后按回车结束,输入缓冲中保存了这个回车符,遇到第二个scanf时,它自动把这个回车符赋给了ch2 。而如果第二个scanf的输入格式不是%c时,由于格式不匹配,这个回车符会被自动忽略,所以只有在连续输入两个%c的格式时才会出现这样的问题!



问题四   如何处理scanf()函数误输入造成程序死锁或出错?
#include <stdio.h>
int main()
{
int a,b,c; /*计算a+b*/
scanf("%d,%d",&a,&b);
c=a+b;
printf("%d+%d=%d",a,b,c);
}
如上程序,如果正确输入a,b的值,那么没什么问题,但是,你不能保证使用者每一次都能正确输入,一旦输入了错误的类型,你的程序不是死锁,就是得到一个错误的结果,呵呵,这可能所有人都遇到过的问题吧?
解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,它就返回几。但这里还要注意另一个问题,如果输入了非法数据,键盘缓冲区就可能还个有残余信息问题。
正确的例程:
#include <stdio.h>
int main()
{
int a,b,c; /*计算a+b*/
while(scanf("%d,%d",&a,&b)!=2)fflush(stdin); /*很有趣的代码*/
c=a+b;
printf("%d+%d=%d",a,b,c);
}

#include <stdio.h>
int main()
{
    int i;
    char j;
    for(i = 0;i < 10;i++)
    {
        scanf(" %c",&j);/*注意这里%前有个空格*/
        printf("%c\n",j);// scanf在工作的时候会省略空格,但是在输入回车后又会被空格控制符(超级重要)吸收  
    }
}

在用"%c"输入时,空格和“转义字符”均作为有效字符。
例:
scanf("%c%c%c",&c1,&c2,&c3); 
输入:a□b□c↙ 
结果:a→c1,□→c2,b→c3 (其余被丢弃)
原来scanf是从标准输入缓冲区中读取输入的数据, 而%c的字符输入格式会接收回车字符,在输入第一个scanf时输入字符后按回车结束,输入缓冲中保存了这个回车符,遇到第二个scanf时,它自动把这个回车符赋给了ch2  。而如果第二个scanf的输入格式不是%c时,由于格式不匹配,这个回车符会被自动忽略,所以只有在连续输入两个%c的格式时才会出现这样的问题!



scanf("%[^/n]",string);scanf用来接收带字符的字符串


 %*                指定类型的数据但不保存
比如:
百分号(%)与格式符之间的星号(*)表示读指定类型的数据但不保存。因此,
scanf( "%d %*c %d", &x, &y );
 
对 10/20 的读入操作中,10 放入变量 x,20 放入 y。  --意义好大的,对数据的处理会方便好多     

@

vanishfan



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值