当前位置 : 主页 > 编程语言 > 其它开发 >

C语言:输入一个长度未定的整形数组[C_001]

来源:互联网 收集:自由互联 发布时间:2022-05-30
概要 在C语言中,往往常用到字符串、数组等,对于一个字符串,其输入很简单,一个语句即可完成,而对于整型数组,我们常遇到的情况都是已知数组长度,即元素的个数之后,用一

 

 概要

在C语言中,往往常用到字符串、数组等,对于一个字符串,其输入很简单,一个语句即可完成,而对于整型数组,我们常遇到的情况都是已知数组长度,即元素的个数之后,用一个for循环完成输入。

然而,如果事先不知道需要输入元素的个数,要求从键盘输入多少个整数便记录多少个,回车之后即完成输入,对于这个问题,看似简单,但对于初学者来说,似乎一时还真没有思路。

 

长度未定的整型数组 1、关于scanf()

sacnf() 是C语言标准库中的输入函数,功能是从标准输入 stdin 读取格式化输入,其一般形式为:

scanf(格式控制,地址列表)

格式控制部分是一个字符串,其中格式声明以 '%' 开始,以一个格式字符结束,中间可以插入附加字符,表示属性。除此之外,还可以含有其他的字符(空格字符、转义字符中的字符和非空格的普通字符),但需要注意的是,如果格式控制字符串中除了格式声明,还含有其他的普通字符,那么在输入时应该在对应位置输入相同字符,不能改写也不能漏写,因为系统是逐个对照检查的。

此外,之所以把空格字符和转义字符中的字符(如Enter、Tab)单独列出来,是基于其特殊之处:

(1).在使用 '%f' 、'%d' 作为格式声明进行数值的输入时,转义字符和空格是作为无效字符,仅仅是作为一个数值与另一个数值中间分隔的作用,或者说是作为一个数值的输入结束标志。

说着都是苍白的,“No photo you say a J8”。

示例1:在格式控制中,格式声明之间没有普通字符的

scanf("%d%d", &A, &B);

对于这种情形,必须在 一个数值输入完成后加一个结束标志作为分隔,可以是空格、回车、Tab。

输入1:520[空格]250↵

输入2:520[Tab]250↵

输入3:530↵250↵

输入4:520[空格][Tab]↵↵250↵

对于上述4组不同的输入方式,结果如下:

表1-不同输入下结果对比

 可见,在进行数值输入时,如果格式控制字符串中没有其他普通字符,空格、回车和Tab等仅仅在格式声明之间起分隔作用,个数不限。

同理可以推测,在格式控制字符串中如果格式声明间除普通字符外,含有的空格、回车或Tab等可以忽略,也可以随便输多少个,也即对于这三个,只作为分隔作用。

 示例2:在格式字符串中,格式声明之间含有普通字符

scanf("%d/WNDMD/ /WRSNDM/%d", &A, &B);

该语句的格式控制字符串中一共有两个格式声明,中间有两段普通字符串,中间隔了一个空格。 

由上文已知,在进行数值的输入时,空格、回车以及Tab的作用都是一样的,作为分隔,而且数目不限,所以,在以下测试中,就不再使用回车和Tab作为分隔,仅用空格就可以说明问题。此外,如果格式声明之间已经含有普通字符,那么就无需再加入分隔字符,也就是输入结束标志。

输入1:250/WNDMD/[空格]/WRSNDM/3600↵

输入2:250/WNDMD//WRSNDM/3600↵

输入3:250/WNDMD//WRSNDM/[空格]3600↵

输入4:250[空格]/WNDMD//WRSNDM/3600↵

 结果如下:

表2-不同输入下结果对比

 可见,图1-3都是正常的,图4出现了问题,图1即为一一对应输入,图2是去掉了两个普通字符串之间的空格,图3是在输入完普通字符后再加入了空格,即结束标志,其结果都是正确的,验证了上述结论。

而图4出现错误,是因为在输入第一个数值后系统本该直接开始检查 "/WDNMD/" 却出现了空格,所以第二个数值便不能正常输入。

可以推测,如果在格式控制字符串中第一个格式声明后加上一个空格,那么输入时,第一个数值后可以输入多个空格,也可以直接忽略掉,后面照上述输入1-3都行(因为格式控制字符串中,格式声明之间如果有普通字符,那么所有的结束标志都可以忽略)。

scanf("%d /WNDMD/ /WRSNDM/%d", &A, &B);

 输入1:250[空格][空格][空格]/WNDMD//WRSNDM/3600↵

输入2:250/WNDMD//WRSNDM/3600↵

 结果如下:

表3-不同输入下结果对比

 各种情况都列了出来,其他的不必多言。

(2).在使用 '%c' 作为格式声明进行字符输入时,空格字符和转义字符中的字符都作为有效字符。

示例3:对这样一个输入语句

char A, B;
scanf("%c%c", &A, &B);

对于如下输入:

输入1:NB↵

输入2:N[空格]↵

输入3:↵[空格]↵

结果如下:

表4-不同输入下结果对比

 结果明显和上文描述中的一致。

 

2、具体实施

在整型数组元素个数不确定的情况下,输入了多少个整数便放多少个到数组中。

scanf()说到底就是从stdin中格式化地读取数据,而数据在stdin中的存放形式也是字符串,所以实现的原理很简单,先取出第一个,判断是否为十进制数,是的话就从取出来的那个开始按整形的格式读,直到遇到结束标志,由上文已经知道,空格、回车、Tab以及普通字符都可以作为数值输入的结束字符,所以会自动读取到下一个非十进制数的位置;如果取出的那个字符不是十进制数,那么继续取下一个。

如此,代码如下:

int main(void) {
    //长度未定的整形数组输入
    int Num[1000],Loc;
    char Temp;

    Loc = 0;//Loc表示已经输入[读取]的整形数的个数
    while ((Temp = getchar()) != '\n') {//从stdin流中获取第一个字符
        if (isdigit(Temp)) {//判断该字符是否为十进制数
            ungetc(Temp, stdin);//若是十进制数,则将改字符退回输入流
            scanf("%d", &Num[Loc++]);//开始从该字符处开始读取int型数
        }
        //如果不是十进制数,直接跳过,开始读下一个[读一个少一个]
    }

    return 0;
}

注释很清楚,无需多言。

 

补充 1、长度确定的整型数组的输入
//确定长度的整形数组输入
int Num[N];//此处N是个具体的数,不能是变量,这样写只是为了更好地展示
for (int i = 0; i < N; i++) {
    scanf("%d", &Num[i]);//输入时可使用逗号或者空格隔开,以回车键结束输入
}

 

2、字符的输入
char C;
//method 1
scanf("%c", &C);

//method 2
C=getchar();

 

3、字符串的输入
char Str;
//method 1
scanf("%s",Str);

//method 2
gets(Str);

//method 3
int N;
gets_s(Str, N);

//method 4
int N;
fgets(Str, N, stdin);

上述函数中,gets()、gets_s()和fgets有必要单独拿出来讲一下区别和用法,鉴于已经存在关于这个的总结得很优秀的文章,就不再赘述。

可参考:

(1条消息) gets,fgets,gets_s的区别分析_如果我开挖掘机你还爱我吗的博客-CSDN博客_gets_s函数和gets区别

上一篇:网络爬虫_Scrapy框架入门
下一篇:没有了
网友评论