V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
drlalll
V2EX  ›  C

C 语言 数组 指针 函数问题,还请不吝赐教

  •  
  •   drlalll · 2017-02-27 22:06:09 +08:00 · 2349 次点击
    这是一个创建于 2106 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Q :编写一个函数可以将 A 数组和 B 数组的每个元素一一相加赋予 C 数组。


    //c primer plus 第十章课后习题 10.13.9 p218
    #include<stdio.h>
    #define num 4
    void sum(int n,int n1,int n2,int ar[],int br[],int cr[]);	//函数声明 , ar 和 br 的每一个元素相加存储到 cr 的每个对应元素中 
    void p(int n,int ar[]);	//函数声明,打印一个数组的每个元素 
    int main(void)
    {
    	int ar[num] = {1,2,3,4};
    	int br[num] = {2,3,4,5};
    	int cr[num];
    	p(num,ar);
    	putchar("\n");
    	p(num,br);
    	putchar("\n");
    	sum(num,num,num,ar,br,cr);
    	p(num,cr);
     } 
     void sum(int n,int n1,int n2,int ar[],int br[],int cr[])	//函数原型 , ar 和 br 的每一个元素相加存储到 cr 的每个对应元素中 
     {
     	int a;
     	for(a = 0;a < n;a++)
     	{
     		cr[a] = ar[a] + br[a];
    	}
     }
     void p(int n,int ar[])	//函数原型,打印一个数组的每个元素 
     {
     	int a;
     	for(a = 0;a < n;a++)
     	{
     		printf("%d",ar[a]);
    	}
     }
    

    ###此函数可以实现 3 个一维数组都有相同数量元素下的运算,请问如果 ar[]或者 br[]元素数不同时要如何进行运算?假设 ar[4] = {...},br[5] = {...} 那么当 ar[4] + br[4]时 ar[4]越界为不确定值,那么此时应该理解为 0 + br[4]吗?函数如何写那?

    16 条回复    2017-02-28 10:08:31 +08:00
    drlalll
        1
    drlalll  
    OP
       2017-02-27 22:08:25 +08:00
    还请对 C 语言有研究的同学指点指点!谢谢!!
    drlalll
        2
    drlalll  
    OP
       2017-02-27 22:45:16 +08:00
    请问一下是 什么原因导致大家不太想回答我的问题 ?是我的 标题写的不够标准 还是 内容太长读起来太费力 或者说 代码写的不标准 亦或者 提问中含有低级错误和常识性错误 ?因为还没入门所以可能有些错误我自己意识不到希望大家能提点提点,我在以后的发表的主题中会尽量避免这些问题,谢谢!!
    franklinyu
        3
    franklinyu  
       2017-02-27 22:49:42 +08:00
    你期望什麼結果?我覺得「不足補 0 」、「多餘的扔掉」和「報錯」都是合理的
    franklinyu
        4
    franklinyu  
       2017-02-27 22:52:05 +08:00
    題外話,三個函數的定義之間隔個空行吧,好看一點。另外定義的宏最好用大寫,像「 NUM 」這樣。
    franklinyu
        5
    franklinyu  
       2017-02-27 23:00:57 +08:00
    另外註釋寫在行末的話整個代碼會很寬,建議寫在函數聲明的前面。在函數定義那裡就沒必要再註釋一次了。

    我個人喜歡的結構是這樣的:

    // 這個文件做了這些和那些……
    <空行>
    #include <foo_lib.h>
    #define BAR_NUMBER 1
    <空行>
    // 執行某任務
    void do_foo(int bar_count);
    // 測試輸入字符串滿足某條件
    int test_bar(int name_len, char[] len);
    <空行>
    int main()
    {
    // 函數主體
    return 0;
    }
    <空行>
    void do_foo(int bar_count)
    {
    // 函數主體
    }
    <空行>
    int test_bar(int name_len, char[] len)
    {
    // 函數主體
    return TRUE;
    }
    visionsmile
        6
    visionsmile  
       2017-02-27 23:57:12 +08:00
    数组下标越界是 undefine behavior.
    >An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5])

    因为是 UB ,你没办法预测会有什么结果。就算这么写结果正确(取决于你的环境)那也是不可移植的。
    visionsmile
        7
    visionsmile  
       2017-02-27 23:59:09 +08:00
    就这个题而言,我觉得一般逻辑上应该是位数不足就补零吧...
    wevsty
        8
    wevsty  
       2017-02-28 00:26:19 +08:00
    对于 C 来说,任何未指定的空间里所存放的东西都是未知的。
    不能理所当然的认为,未经过初始化的空间值都是 0 。即使有些情况下可能值确实是 0 ,也不能理所当然的这样认为。
    数组这个东西在传递的时候是传递的首地址,函数内没办法 100%准确的确定数组有多长。
    典型例子是 C 风格的字符数组。
    char sz[] = "test"
    char sz1[2] = {'t','e'}
    当 strdup 这样的函数对 sz 进行拷贝的时候,是以 test 后面的 0 值作为结尾标志终止拷贝的。 C 当中约定字符串以 0 结尾,通过字符串常量编译器会自动给字符串末尾加上 0 ,所以 sizeof(sz)得到的结果是 5 而不是 4 。
    sz1 则不同, sz1 的末尾并没有以 0 结尾,如果对 sz1 使用 strdup ,或者 strcpy 这样的函数就会出现明显的问题。 strcpy 会试图拷贝 sz1 后面的一些空间直到某一个这些空间中出现 0 值为止,至于 sz1 后面的空间什么时候会遇见 0 ,这种事情是没办法确定的。
    所以数组的处理过程中,要不然就得约定一个数组末尾的标记,要不然就必须清楚的知道数组的长度。
    msg7086
        9
    msg7086  
       2017-02-28 02:09:23 +08:00
    嗯基本就是 3 楼的做法。

    两个数组大小不同的情况下,怎么处理是「你」—— 楼主你来决定的。

    另外如果面试的时候遇到面试官出了这样的问题,那你要问面试官,让他来决定。(或者他会让你决定。)
    zhujinliang
        10
    zhujinliang  
       2017-02-28 04:46:02 +08:00 via iPhone
    num 大写
    n 、 n1 、 n2 写成 an 、 bn 、 cn 不更好么,如果是 an 、 bn 、 sn 、 ar 、 br 、 sr 更好
    Andiry
        11
    Andiry  
       2017-02-28 05:44:55 +08:00
    ar[4] = br[0],看看栈空间就知道了
    drlalll
        12
    drlalll  
    OP
       2017-02-28 08:04:54 +08:00
    @zhujinliang
    @Andiry
    @msg7086
    @wevsty
    @franklinyu
    明白了!谢谢大家!
    bp0
        13
    bp0  
       2017-02-28 08:25:49 +08:00 via Android
    如果是往 C 里面放,循环长度应该是 C 的长度。

    然后再循环内判断 A 和 B 是否超过自身的长度,没超取数,超的用 0 。最后相加赋值到 C 对应位置。

    为什么这么做,因为函数原型中并没有返回值。这时是无法正常返回一个错误的。所以使用 0 代替不存在的值,并完成需求。

    如果是面试,需要问面试官,长度不一致的时候如何处理。如果需要报错,则应该注意定义函数原型时需要有返回值。
    drlalll
        14
    drlalll  
    OP
       2017-02-28 08:39:01 +08:00
    @bp0
    这个不是面试题,是我看书时候的练习题。用 cr 的元素数做循环控制好像是最合理的,返回值是要返回一个 bool 值吗?还是我直接做判断当 n1 != n2 != n3 时直接打印 error ?
    谢谢提醒!
    129tyc
        15
    129tyc  
       2017-02-28 09:07:02 +08:00 via Android
    我觉得可以首先根据 n2 初始化 cr 数组,接着以 n,n1, n2 最小值为循环次数进行相加
    bp0
        16
    bp0  
       2017-02-28 10:08:31 +08:00 via Android   ❤️ 1
    这就要看习题上是否给原型了。如果给了,并且没有返回值。我觉得应该是使用 0 填充,不然给 3 个长度就没意义了。

    如果没给的话,我建议你想想这道题考察的是什么知识点。如果是我自己做题,我会按上面说的答。

    在面试的时候问面试官是一种面试策略,让面试官知道你考虑到这个问题而已。

    总结一下,怎么答都没错。只要检查长度,没有内存溢出就行。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2210 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 16:21 · PVG 00:21 · LAX 08:21 · JFK 11:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.