您的位置:首页 > 编程语言 > C语言/C++

c语言==字符串的键入,遍历,输出(6)

2016-07-14 14:18 274 查看

atoi函数

c语言中,atoi函数将字符串转变为数字,若遇到字母,就会停止输出

#include <stdio.h>
#define Max_size 1024
#include <string.h>

void atoi(char *a)
{
int temp = 0;
int i = 0;
int flag = 1;

if(a[i] == '-')
{
flag = -1;
}

while(a[i] != 0)
{
if(a[i] > '0' && a[i] < '9')
{
temp = a[i] - '0' + temp * 10;
i++;
}
else
break;

}

printf("%d\n" , temp * flag);
}

int main()
{
char a[Max_size];

printf("请输入字符串\n");
scanf("%s" , a);

atoi(a);

return 0;
}


这个程序完成了从字符串变为数字的功能

思想算法

首先要得到一串字符串,所以要创建一个字符数组用来存放。然后依次将这个数组里的字符遍历得到,通过一些方法,将得到的那些数转化为十进制。

tips

1、要输入一串字符串,就要通过字符数组来存放

2、字符数组里的0相当于’\0’

3、在定义数组的时候,可以运用宏定义去实现给他分配多少空间

4、在atoi函数中,形参为字符数组,则要加上*,即取数组首地址

5、一串字符串也很有可能是负的,所有要先定义他的一个标志位flag,然后判断他的首位是否为负,为负的话就令flag为-1,然后在最后的结果的基础上乘以flag。

6、在字符数组没有读到空之前,都要一直向后读数,因为不知道有多少次,所以用while,判断条件为a【i】是否等于0(参见tip2),比用strlen方便的多

7、也可以不用数组i来进行判断,用*加数组名,来代表首地址,并读出里面的内容。然后数组名++就代表依次向后移位。例如

if(*a == '-')
{
flag = -1;
a++;
}

while(*a != 0)
{
a++;
}


8、atoi这个函数默认的输入数字才有效,输入字母自动退出,而输出前面的数。所以要对字符数组的内容进行判断是否是数字

9、得到数字之后,要将他转化为十进制。因为他是先得到的高位数,所以可以让她连着低位数一起乘10,有多少位乘以多少10

问:什么叫格式化输出与输入

答:在输出与输入时,会有格式的限定。如果不按照程序里规定的格式输入,则会出现未知数。

#include <stdio.h>

int main()
{
int i;

printf("请输入一个整数\n");
scanf("sm = %d" , &i);
printf("%d\n" , i);

return 0;
}


这个程序在输入的时候就应该输入 sm = 3,必须按照他给你的格式进行输入,否则就会出现未知数,而程序也会乖乖的按照既定的格式进行输出。

#include <stdio.h>

int main()
{
int i;
int num;
int c_num;
float f_num;
double d_num;
int a[3];
char src[3];

printf("请输入整型数\n");
scanf("%d" , &num);

printf("num = %d\n" , num);

getchar();
printf("请输入字符型数\n");
scanf("%c" , &c_num);

printf("c_num = %c\n" , c_num);

printf("请输入浮点型数\n");
scanf("%f" , &f_num);

printf("f_num = %f\n" , f_num);

printf("请输入长浮点型数\n");
scanf("%lf" , &d_num);

printf("d_num = %lf\n" , d_num);

printf("请输入整型数组数\n");
for(i = 0; i < 3; i++)
{
scanf("%d" , &a[i]);
}

printf("数组为:\t");
for(i = 0; i < 3; i++)
{
printf("%d\t" , a[i]);
}
printf("\n");

printf("请输入字符串\n");
scanf("%s" , src);

printf("字符串为:%s\n" , src);

return 0;
}


这个程序包括了许多典型数据类型的输入和输出,其中有一个很特殊,就是字符型数的输入。

他会自动捕获在键盘上get到的字符类型。在输入完整型数之后,自然的会敲一个回车键,如果不做任何操作,字符型数就会默认回车是键入的字符,所以,在两者之间要加入一个getchar()操作。去回收那个回车键。并且让程序能够停下来等待字符型数的键入。

问: 键入字符串有什么方法?

答:一共有三种方法

1、scanf

2、gets

3、getchar

首先

scanf的形式是scanf(“%s” , a);但是他遇到空格就会停止读入,只输出空格前的东西。

百度了一下,发现有一个博主说是先让程序sleep,然后还分了几个字符串输出的

scanf()函数不能正确接受有空格的字符串?如: I love you!

#include <stdio.h>
int main()
{
char str[80];

scanf("%s",str);
printf("%s",str);
return 0;
}


输入:I live you!

输出:I

scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。

① 遇空格、“回车”、“跳格”键。

② 遇宽度结束。

③ 遇非法输入。

所以,上述程序并不能达到预期目的,scanf()扫描到”I”后面的空格就认为对str的赋值结束,并忽略后面的”love you!”.这里要注意是”love you!”还在键盘缓冲区(关于这个问题,网上我所见的说法都是如此,但是,我经过调试发现,其实这时缓冲区字符串首尾指针已经相等了,也就是说缓冲区清空了,scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中)。我们改动一下上面的程序来验证一下:

#include <stdio.h>
int main()
{
char str[80];
char str1[80];
char str2[80];

scanf("%s",str);/*此处输入:I love you!  */
printf("%s",str);
sleep(5);/*这里等待5秒,告诉你程序运行到什么地方*/
scanf("%s",str1);/*这两句无需你再输入,是对键盘盘缓冲区再扫描   */
scanf("%s",str2);/*这两句无需你再输入,是对键盘盘缓冲区再扫描    */
printf("/n%s",str1);
printf("/n%s",str2);
return 0;
}


输入:I love you!

输出:I

love

you!

好了,原因知道了,那么scanf()函数能不能完成这个任务?回答是:能!别忘了scanf()函数还有一个 %[] 格式控制符

然后

gets的格式是gets(a);他可以得到一个句子,即输入的两个字符串之间有空格也没有关系。但是值得注意的是,如果上下类型不一致,需要加上getchar(),而scanf就不需要。另外,gets这个函数十分危险,因为他就算越界了,他也可以正常输出。

例如:

假设数组msg[40]是取40个字符,输入helloworld能够在屏幕上正常回显输出。但若是把40改为2,输入helloworld屏幕上也能正常回显输出,感觉此时数组应该越界了。

问题:

1、越界了能正常输出?数组msg[2]不会把字符串截断吗?

2、能正常输出的话,那么字符数组msg[40]定义的40就可以定义成任何数了,字符数组里的数限制不了字符数组的长度。我见过一些程序一般是把数组设置的足够大,只能用这种方法防止越界?有没有其他方法如果越界了的话能给与提示。

3、在网上看到gets函数很危险,不推荐使用。推荐fgets函数,但fgets函数是从文件输入的字符串。我现在想实现从键盘输入字符串存到数组里的功能,但又想避免越界。有没有好的方法?

最后,

getchar的格式是getchar();一个字符一个字符的读,虽然有点慢,但是能够防止溢出。

这种一个个输字符的函数,还可以输入密码,密码用*替代。

#include <stdio.h>
#define Max_size 1024

int main()
{
int i = 0;
char ch;
char a[Max_size];

while((ch = getchar()) != '\n')
{
printf("*");
}

return 0;
}


这个程序输出的就是各种*代替密码的显示

tips:

1、while(1) 代表的是,函数一直不会停止;

2、exit(1)代表的是,退出这个函数;

3、数组名代表的是数组首元素的地址,a+i代表的是a[0],a[1],a[2]

输出的时候,*(a+i)就可以取内容了

danger:数组名是一个常量,不可以自加,如a++,只可以写a+i

但是如果用一个p指针指向数组,那么p是可以自增的。

another danger:如果在输入的时候。一直用的p++,那么输出的时候,必须先把p指向a[0],因为输完了的时候p在最后。

4、打印字符串,用puts(),打印字符型数,用putchar();

打印p指针,printf(“p = %p\n” , &num );

打印无符号整型 %u

printf是行缓冲区,需要有\n才能输出

但是也有输出的特例,比如

1、程序结束了,清除缓冲区的时候会输出

2、当紧跟着printf之后又有一个scanf的时候,由于他们用的是同一个行缓冲区,所以会输出出来。

但是当这个程序一直不停止,如while(1)的时候,printf就会不出来

警告:返回一个局部变量的地址的处理方法

有时会在一个函数里面定义一个局部变量。并且将它作为返回值,这时就会出现警告,因为返回的是一个局部变量的地址。所以一般会在这个变量前面加上static。

将字符串逆序输出

int i;
char temp;
for(i = 0; i < len / 2; i++)
{
temp = a[i];
a[i] = a[len-i-1];
a[len-i-1] = temp;
}


关于i++及++i

i++:先用再自增

++i :先自增再用

例如:

int i = 2
num = (i++)+(i++)+(i++)+(i++);
//num = 2 + 2 + 2 + 2 = 8   i = 6;
//因为i++是先用再自增,所以他会一直运用到结束符(分号)再停止。

num = (++i) + (++i) + (++i) + (++i);
//num = 4 + 4 + 5 + 6 = 19   i = 6
//前面两个是4的原因:运算操作符要有两个才可以做,所以先+1,+1变成4再加。

i = i * ((i++)+(++i));
//先算括号,又是一个运算符,所以要把后面的++i也算完了才能确定前面的i++,即2赋过去,遇到i++先不自加,然后++i的时候+1,变成3,这时候两个都变成3了,然后还有一个i没有乘,所以还是乘以3,最后遇到分号的时候完成i++,i = 18之后再加1变成19

i = (i++) + (++i) +(i++) + (++i);
//先把2赋过去,不自增,但是由于运算符,要等第二个数,++i自增一个,变成3,这时候3 + 3, 然后再加3,不自增,遇到++i,变成4 加上4,遇到分号再把刚才两个自增加上去
即i = 3+3+3+4+2 = 15;

//还有作为函数实参的情况
//函数是从右边开始传参的,逗号,分号,函数括号都是结束标志。
//++i被替换成变量名i,i++直接被替换成数值。

show(++i,++i,i++,++i,i++);
//先从右边开始读,i++直接变成2,遇到逗号,i = 3,然后++i,先变成i,这时候i = 4,然后i++,是4,遇到逗号,i=5,然后++i,先变成i,i = 6,然后++i,再变成i,i = 7,这时候把所有的i都用7来替换,即7 7 4 7  2

//show(i++,++i,i,i++,++i);
//5    i     i     3         i
//i=6  i=5  i=4   i=4       i=3
//所以结果是5 6 6 3 6


数组和指针

数组名是一个常量,用来保存首元素的地址。

由于数组名是一个常量。所以不可以将一个值赋给数组名,试图将内容保存到数组里。

而指针是一个变量,可以将一个值赋给指针名。

char temp[MAX_SIZE];
temp = my_strcpy(dest,src);
//这个方法是错的,因为这个函数他返回的是数组首地址(或字符串首地址),不可以赋给一个常量(数组名)

char * temp;
temp = my_strcpy(dest,src);
//此方法是对的,因为返回的是一个地址,所以要把他存在指针里,所以定义一个temp指针,然后将他赋给这个变量(指针名)
//由此可见,在定义my_strcpy这个函数的时候,他的返回类型肯定是一个地址类型,即指针类型。如下
char * my_strlen(char * dest, char * src)
//其次,这个想要输出这个temp内容的时候,格式如下
printf("%s" , temp);
//因为temp保存到了首地址,可以直接输出了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 c语言 遍历