C语言中利用scanf语句输入多个值的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言中利用scanf语句输入多个值的问题相关的知识,希望对你有一定的参考价值。
今天利用共同体变量写了一个小程序要求:有若干人员的数据,其中有学生和教师。学生的数据包括姓名、号码、性别、职业、班级。教师数据包括姓名、号码、性别、职业、职务。要求用同一个表格来处理。
编译通过后运行程序,发现输出有问题,通过调试发现问题出现在scanf语句中,原本的scanf语句为scanf("%d %s %c %c",&person[i].num,&person[i].name,&person[i].sex,&person[i].job);调试过程发现此处输入101空格hu空格m空格s空格后,&person[i].job的值被,&person[i].sex覆盖也为m。1.试着在%d %s %c %c中间都加一个空格,输出结果回复正常。2.又想在%d %s %c %c中间加个逗号,输出结果依旧有问题。但写一个简单的scanf函数时1和2两种方法均能输出正常的结果。我想是不是由于使用了结构体变量或者共同体变量才会导致这样的问题,如果是在使用结构体或共同体时对输入输出格式有什么特殊的要求吗?请大家帮我讲一下。
源代码奉上(已经改正过):
#include<stdio.h>
struct student
int num;
char name[20];
char sex;
char job;
union
int clas;
char position[20];
category;
person[2];
int main()
int i;
for(i=0;i<2;i++)
printf("please enter the date of person:\n");
scanf("%d %s %c %c",&person[i].num,&person[i].name,&person[i].sex,&person[i].job);
if(person[i].job=='s')
printf("请输入该学生的班级:\n");
scanf("%d",&person[i].category.clas);
else if(person[i].job=='t')
printf("请输入该老师的职位:\n");
scanf("%s",&person[i].category.position);
else
printf("输入的job类型有误");
printf("\n");
for(i=0;i<2;i++)
if(person[i].job=='s')
printf("该学生的信息如下:%6d%10s%4c%4c%10d\n",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.clas);
else
printf("该教师的信息如下:%6d%10s%4c%4c%10s\n",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.position);
return 0;
1、有一个很严重的错误,输入字符数组的两个
scanf("%d %s %c %c",&person[i].num,&person[i].name,&person[i].sex,&person[i].job);
scanf("%s",&person[i].category.position);
2、把这两行中字符数组输入时前面的&符号去掉,对字符数组输入本身就是地址,不要加&,改成这样
scanf("%d %s %c %c",&person[i].num,person[i].name,&person[i].sex,&person[i].job);
scanf("%s",person[i].category.position);
3、其他的也没有什么错误,记着输入时候,那几个值之间用一个空格隔开,用scanf()函数输入的时候,本质是,你给scanf一个地址,这个函数会根据你输入的地址把,输入缓冲区中的数据放在指定地址处
4、像int ,char,double,long,float这些基本类型,再分配空间的时候,只是给他们一个空间,所以用scanf()输入的时候,要加&取地址符号,才能给他们赋值
5、然而char *,char [],这些本身是一块区域的首地址,本身就是地址,所以用scanf时,不用加&因此,输入里面不需要加的只有,person[i].name,person[i].category.position两个,其他的都是基本类型,因此都需要加
扩展资料:
优缺点
1、简洁紧凑、灵活方便
C语言一共只有32个关键字,9种控制语句,程序书写形式自由,区分大小写。把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。
C语言的 Hello World 程序
2、运算符丰富
C语言的运算符包含的范围很广泛,共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C语言的运算类型极其丰富,表达式类型多样化。灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。
3、数据类型丰富
C语言的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据结构的运算。并引入了指针概念,使程序效率更高。
4、表达方式灵活实用
C语言提供多种运算符和表达式值的方法,对问题的表达可通过多种途径获得,其程序设计更主动、灵活。它语法限制不太严格,程序设计自由度大,如对整型量与字符型数据及逻辑型数据可以通用等。
5、允许直接访问物理地址,对硬件进行操作
由于C语言允许直接访问物理地址,可以直接对硬件进行操作,因此它既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位(bit)、字节和地址进行操作,而这三者是计算机最基本的工作单元,可用来写系统软件。
6、生成目标代码质量高,程序执行效率高
C语言描述问题比汇编语言迅速,工作量小、可读性好,易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编程序生成的目标代码效率低10%~20%。
7、可移植性好
C语言在不同机器上的C编译程序,86%的代码是公共的,所以C语言的编译程序便于移植。在一个环境上用C语言编写的程序,不改动或稍加改动,就可移植到另一个完全不同的环境中运行。
8、表达力强
C语言有丰富的数据结构和运算符。包含了各种数据结构,如整型、数组类型、指针类型和联合类型等,用来实现各种数据结构的运算。C语言的运算符有34种,范围很宽,灵活使用各种运算符可以实现难度极大的运算。
C语言能直接访问硬件的物理地址,能进行位(bit)操作。兼有高级语言和低级语言的许多优点。它既可用来编写系统软件,又可用来开发应用软件,已成为一种通用程序设计语言。另外C语言具有强大的图形功能,支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。
参考技术A 有一个很严重的错误,你输入字符数组的两个scanf("%d %s %c %c",&person[i].num,&person[i].name,&person[i].sex,&person[i].job);
scanf("%s",&person[i].category.position);
把这两行中字符数组输入时前面的&符号去掉,对字符数组输入本身就是地址,不要加&
改成这样
scanf("%d %s %c %c",&person[i].num,person[i].name,&person[i].sex,&person[i].job);
scanf("%s",person[i].category.position);
其他的也没有什么错误
记着输入时候,那几个值之间用一个空格隔开追问
person[i].num是结构体数组的成员,对成员进行赋值应该要加&吧?还有按照我这样写但从输出结果上看是正确的,不知道是否存在内在的隐患?我刚开始学习C语言,希望您能帮我升入讲解一下。
追答用scanf()函数输入的时候,本质是,你给scanf一个地址,这个函数会根据你输入的地址把
输入缓冲区中的数据放在指定地址处
象int ,char,double,long,float这些基本类型,再分配空间的时候,只是给他们一个空间
所以用scanf()输入的时候,要加&取地址符号,才能给他们赋值
然而char *,char [],这些本身是一块区域的首地址,本身就是地址,所以用scanf时,不用加&
因此,你输入里面不需要加的只有,person[i].name,person[i].category.position两个,其他的都是基本类型,因此都需要加
我明白了,像我原来写得可能在运行的时候没有问题,可是在内存中存储的person[i].category.position数据只是输入的字符串的首字符对吧?这个调试的过程中可以看到(今天刚学的调试程序)。
追答呵呵呵,是这样的
追问呵呵,谢谢您的帮助,可以交个朋友吗?282685900
本回答被提问者采纳C语言返回多个值的方法
参考技术A导语:编写有多个返回值的函数是所有C语言教材里均没有提到的知识点,但在实际教学与应用的过程中我们都有可能会遇到这样的问题。以下是引导学生采用的三种不同方法编写多个返回值的C语言函数,一起来学习下吧:
方法1:利用全局变量
分析:全局变量作为C语言的一个知识点,虽然我们都了解它的特点,但在实际教学过程中应用得并不是很多。由于全局变量的作用域是从定义变量开始直到程序结束,而对于编写有多个返回值的C语言函数,我们可以考虑把要返回的多个值定义成全局变量。当函数被调用时,全局变量被更改,我们再把更改后的全局变量值应用于主调函数中。函数被调用后被更改后的全局变量值即为函数的数个返回值。下面以一个实例演示该方法的应用。
实例1:编写函数求3个数中的最大值与最小值。
方法:把最大值、最小值分别定义成2个全局变量max、min,在用户自定义函数中把求出来的最大值与最小值分别赋给全局变量max、min。函数调用完毕后全局变量的max、min值即保存了函数要求返回的值。程序参考代码如下:
#include "stdio.h"
#include "conio.h"
int max,min;/*定义两个全局变量用于保存函数返回值*/
void max_min(int a,int b,int c) /*定义求最大最小值的函数*/
max=min=a; /*初始化最大最小值*/
if(max if(max if(min>b)min=b;
if(min>c)min=c;
main()
int x,y,z;
printf(" 请输入3个整数: ");
scanf("%d,%d,%d",&x,&y,&z);
max_min(x,y,z) ;/*调用求最大值与最小值的函数*/
printf("三个数中的最大值为:%d;最小值为:%d",max,min);/*输出最大值与最小值*/
getch();
调试结果如下:
请输入3个整数:
5,-6,2
三个数中的最大值为:5;最小值为:-6
注意:该方法虽然可以实现有多个返回值的函数,但由于全局变量不能保证值的正确性(因为其作用域是全局,所以程序范围内都可以修改它的值,如果出现错误将非常难以发现),并且全局变量增加了程序间模块的耦合,所以该方法要慎用。
方法2:传递数组指针
分析:在教学过程中,我们知道C语言函数参数的传递方式有值传递与地址传递。当进行值传递时,主调函数把实参的值复制给形参,形参获得从主调函数传递过来的值运行函数。在值传递过程中被调函数参数值的更改不能导致实参值的更改。而如果是地址传递,由于传递过程中从实参传递过来的是地址,所以被调函数中形参值的更改会直接导致实参值的更改。因此,我们可以考虑把多个返回值作为数组元素定义成一个数组的形式,并使该数组的地址作为函数的形式参数,以传址方式传递数组参数。函数被调用后,形参数组元素改变导致实参改变,我们再从改变后的实参数组元素中获得函数的多个返回值。以下实例演示该方法的应用。
实例2:编写函数求一维整形数组的最大值与最小值,并把最大值与最小值返回给主调函数。
方法:以指针方式传递该一维数组的地址,然后把数组的最大值与数组的\'第一个元素交换,把数组的最小值与最后一个元素交换。函数被调用完毕后,实参数组中的第一元素为数组的最大值,实参数组中最后一个元素为数组的最小值,从而实现返回数组的最大值与最小值的功能。程序参考代码如下:
#include "stdio.h"
#include "conio.h"
void max_min(int *ptr,int n) /*定义求数组最大值最小值的函数,传递数组指针*/
int i,j,k;/*j保存最大值所在位置,k保存最小值所在位置*/
int *temp;/*用于交换位置*/
*temp=*ptr;
for(i=0;i
if(*ptr<*(ptr+i))/*最大值与第一个元素进行交换*/
k=i;
*temp=*ptr;
*ptr=*(ptr+k);
*(ptr+k)=*temp ;
if(*(ptr+n-1)>*(ptr+i))/*最小值与最后一个元素进行交换*/
j=i;
*temp =*(ptr+n-1);
*(ptr+n-1)=*(ptr+j);
*(ptr+j)= *temp ;
/*调用最大最小值函数*/
main()
int A[6],i;
for(i=0;i<6;i++)
scanf("%d",&A[i]);
max_min(A,6);
printf("max=%d, min=%d ",A[0],A[5]);
getch();
调试结果如下:
请输入6个整形数,以空格隔开:
5 8 9 32 -6 4
max=32,min=-6
注意:该方法适用于多个返回值的数据类型一致的情况。当返回值数据类型不一致时,不适用该方法。
方法3:传递结构体指针
分析:结构体作为教学中的一个难点,教材对它介绍的内容并不多,应用的实例更是少之又少,所以学生对于结构体普遍掌握情况不理想。其实,编写返回多个值的C语言函数,也可以考虑采用结构体的方式去实现。通过方法2,我们知道如果返回的数个数值的数据类型不一致,可以通过定义全局变量实现有多个返回值的C语言函数,也可以考虑把要求返回的数个值定义成一个结构体,然后同样以传递结构体指针方式把结构体的指针传递给形参结构体指针,那么函数中对形参结构体的修改即是对实参结构体的修改,函数被调用后获取的实参结构体成员即为函数的多个返回值,下面以实例演示该方法的应用。
实例3:编写一个用户自定义函数,允许用户录入学生的基本信息(包括学号、姓名、所属班级、总评成绩),并返回这些基本信息给主调函数。
方法:把学生基本信息定义成一个结构体,在用户自定义函数中传递该结构体的指针,则自定义函数中对结构体成员的录入操作即是对实参结构体成员的录入操作,从而实现多个返回值。参考代码如下:
#include "stdio.h"
#include "conio.h"
struct inf/*定义学生结构体,分别包含成员学号、姓名、班别、总评成绩*/
char xh[12];
char name[20];
char class[15];
int chj;
;
main(void)
struct inf a1; /*定义学生结构体类型变量*/
void xxxx(struct inf *ptr);
printf("请输入学号,姓名,班别,总评成绩,以空格隔开: ") ;
xxxx(&a1);/*调用函数,以学生结构体类型变量地址作为实参*/
printf("学号:%s,姓名: %s,班别:%s,总评成绩:%d",a1.xh, a1.name,a1.class,a1.chj);
getch();
void xxxx(struct inf *ptr)/*该函数实现对结构体成员数据的录入操作*/
char xh1[12],name1[20],class1[15];
int chj1;
scanf("%s%s%s%d",xh1,name1,class1,&chj1);
strcpy(ptr->xh,xh1);
strcpy(ptr->name,name1);
strcpy(ptr->class,class1);
ptr->chj=chj1;
调试结果如下:
请输入学号,姓名,班别,总评成绩,以空格隔开:
200102LiLi200185
学号:200102,姓名: LiLi,班别:2001,总评成绩:85
注意:当函数要求返回的多个值是相互联系的或者返回的多个值数据类型不一致时可以采用该方法。
总结
对于以上这三种方法,如果想要返回的数个值数据类型一致,可以考虑采用方法2;而对于不同数据类型的返回值,如果各个数值之间是相互联系的,则方法3较为合适;方法1虽然在很多情况下都可以实现多个返回值的C语言函数,但毕竟全局变量应用过程中有很多危险,要慎重使用。
以上是关于C语言中利用scanf语句输入多个值的问题的主要内容,如果未能解决你的问题,请参考以下文章