精华内容
下载资源
问答
  • C语言自定义函数如何返回数组

    万次阅读 多人点赞 2017-11-03 21:27:27
    最近看到一些同学问题,有提到说:如何在一个函数中返回数组呢? 能否直接在自定义 函数,写成char *类型返回值,直接返回呢?,代码如下:       直接返回str数组名(注意不需要加&,还有好多同学犯这个...

    C语言自定义函数如何返回数组

     C语言研究中心  CTO  9个月前 (01-28)  4759次浏览  5个评论

    最近看到一些同学问题,有提到说:如何在一个函数中返回数组呢?

    能否直接在自定义 函数中,写成char *类型返回值,直接返回呢?,代码如下:

     

    C语言自定义函数如何返回数组(上)?

     

     

    直接返回str数组名(注意不需要加&,还有好多同学犯这个错)

    但事实上,运行结果并非正常,我们尝试在调用函数中输出,可以看到结果并非是原来内容(当然你的电脑输出可能还不是这个样子)

    如下:

     

     

    C语言自定义函数如何返回数组(上)?

     

     

    原因大家可以从str的属性入手,str本身是一个自定义函数中的局部变量,是一个数组有一百个字节,它的生命周期当然也随着它所在的函数一起,正所谓“一招天子一朝臣”,随着fun函数调用的结束,其中的各种局部变量也将被系统收回,理所当然的str数组这一百个字节也将被收回,所以”Hello www.dotcpp.com”这串字符串也就灰飞烟灭了!自然你在main函数里再输出肯定已经不是原来的内容了!

     

    怎么样,可以理解吧!

    不过,还没有结束,依然有同学继续问,可为什么我换成下面这种写法就可以了呢?

    如下图:

     

     

    C语言自定义函数如何返回数组(上)?

     

     

     

    答曰:这种写法情况下,str虽也属于是局部变量,但不是一个数组,而是一个指针,只有四个字节,存的是在常量区的字符串” Hello www.dotcpp.com”,但请注意,这个字符串在常量区,而不属于fun函数里的部分,全程序都可读,所以return之后依旧存在,返回的是str里的值,也就是字符串“Hello www.dotcpp.com”的首地址,是一个数,其实相当于把这个字符串的地址在str手里通过返回值转交到p里。

    也可以打个比方:之前只有fun函数知道这个字符串,但现在已经马上不行了,临终前,交代:“我快不行了,赶紧把‘Hello www.dotcpp.com’的藏宝地址(字符串首地址)转交到main函数里!”

    然后就return 快马加鞭的返回到main函数手里了!随后消失…

    而后,main函数获得之后,你们也就知道了…

     

     

    这样讲,大家能理解吗?

     

    后期C语言逆向分析部分,也会有涉及到此处的原理,大家可以再深入学习理解。

    同时,下篇我们将为大家讲解如何实现自定义函数的数组传递问题!


    通过上一篇的讲解,相信大家已经明白直接的return数组的问题以及原因了,今天我们将详细为大家讲解在函数中返回数组的常见办法。

     

    此类问题,应用场景往往为了解决函数间相互通信,比如某个函数内处理的完的结果数据需要交接给另一个函数的情况,那么一般来说,总结有以下三种:

    1. 直接使用全局变量:这种方法最方便,但此方法打破了函数间的通信及封装的思想,所以不推荐使用,不在今天讨论范围之内。
    2. 通过堆区动态开辟内存解决:C语言中,我们通常用malloc来在堆区动态开辟内存,利用堆区“现用现开辟,用完手动收回”特点,实现灵活管理。是实际开发中的常用办法,也是我们今天的主要内容。
    3. 由调用方传入数组指针:此种方法不需要函数返回地址,而是在调用时直接 传入数组地址,委托被调用方进行操作,由于此局部变量属于调用方本身,故即便被调用方结束内存释放,也不会被影响到该数组。

     

    下面逐个实验,对于第二种方法,由于动态开辟内存在堆区,堆区不想上一讲中局部变量在栈区存储,系统根据它的生命周期自动收回,而是手动开辟,手动释放,这样就可以完全规避问题,例子与效果见下图:

    需要注意的是:记得用完free掉,防止内存泄露!

     

    C语言自定义函数如何返回数组(下)?

     

     

    第三种方法:虽然没有在函数中返回数组,但也可以解决数组通信问题,主要思路就是调用方中定义数组,然后将地址传入,由于该内存属于调用方,而非被调用方,故被调用方在调用结束后释放掉内存也无所谓。例子程序及效果如下:

     

    C语言自定义函数如何返回数组(下)?

     

     

    关于数组使用传递的总结,大体如上,大家有任何问题和疑问还可以联系我们!

     

     

    C语言研究中心(www.dotcpp.com)



    C语言网, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C语言自定义函数如何返回数组(上)?

    展开全文
  • 定义一个函数一定要有main吗,main函数有什么作用,void有什么作用 #include int main() { void swap(int *px, int *py) { int temp, x, y; printf("请输入x,y\n"); scanf("%d, %d\n",&x, &y); px = &x;...
  • (1)给定如下面形式的字符串:“ad,app,ai,apk”,"bed book bool bat byte"...把数字储存成字符串储存的就是数字字符,例如可以将213以‘2’、‘1’、‘3’、‘\0’的形式储存在一个字符串数组。而以...

    (1)给定如下面形式的字符串:“ad,app,ai,apk”,"bed book bool bat byte",它们由一组由固定字符隔开的字符串组合而成。

    如何将长字符串分割,即去掉其中的空格或逗号,使能够取出其中单个的字符串?

    (2)数字既能以字符串形式储存,也能以数值形式储存。把数字储存成字符串储存的就是数字字符,例如可以将213以‘2’、‘1’、‘3’、‘\0’的形式储存在一个字符串数组中。而以数值形式储存213,储存的是int类型的值。

    假设程序需要使用数值命令形参,但是命令形参被读取为字符串。因此,要使用数值必须先把字符串转换为数字。

    实例:这个txt文档中所有的SEED行是32个16进制数“0XAA”形式的文本,中间都以‘,’隔开,读取文件时数字以字符串形式储存,现需要取出SEED行所有的16进制数字的数值。


    下面的程序实现了将所有数值取出,并将这些数重新以16进制形式写入一个新的txt文档中,新的文档格式如下

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define SEEDNUM 10
    typedef struct {
    	char **str;     //the PChar of string array  
    	size_t num;     //the number of string  
    }IString;
    int Split(char *src, char *delim, IString* istr);
    
    int main(int argc, char *argv[])
    {
        FILE * sfp = NULL;
        FILE * ofp = NULL;
        sfp = fopen("10seed1122test.txt", "r");
    	ofp = fopen("10output1122.txt", "w");
    	
        if (NULL == sfp) /* 如果失败了 */
    	{
    		printf("错误!seed文件打开失败!");
    		exit(EXIT_FAILURE); /* 中止程序 */
    	}
    	if (NULL == ofp) /* 如果失败了 */
    	{
    		printf("错误!output文件打开失败!");
    		exit(EXIT_FAILURE); /* 中止程序 */
    	}
    	
    	int i;
    	long value[32];
    	char * end;
    	unsigned char tem_buf[1024];
    	unsigned char dest_buf[1024];
    	
    	for ( i = 0; i < SEEDNUM * 2; i++)
    
    	{
    		unsigned char output[32];
    		fgets(tem_buf, 1024, sfp);
    		if (i % 2)
    		{
    			strncpy(dest_buf, tem_buf + 5, 161);
    
    			IString istr;
    			Split(dest_buf, ",", &istr);
    			
    			int j;
    			unsigned char tem[32];
    			for (j = 0; j < 32; j++)
    			{
    				char dest[2];
    				strncpy(dest, istr.str[j] + 2, 2);
    				value[j] = strtol(dest, &end, 16);
    				fprintf(ofp,"%02X",value[j]);
    	
    			}
    			fprintf(ofp, "\n");
    		}
    	}
        return 0;
    }
    
    int Split(char *src, char *delim, IString* istr)//split buf  
    {
    	int i;
    	char *str = NULL, *p = NULL;
    
    	(*istr).num = 1;
    	str = (char*)calloc(strlen(src) + 1, sizeof(char));
    	if (str == NULL) return 0;
    	(*istr).str = (char**)calloc(1, sizeof(char *));
    	if ((*istr).str == NULL) return 0;
    	strcpy(str, src);
    
    	p = strtok(str, delim);
    	(*istr).str[0] = (char*)calloc(strlen(p) + 1, sizeof(char));
    	if ((*istr).str[0] == NULL) return 0;
    	strcpy((*istr).str[0], p);
    	for (i = 1; p = strtok(NULL, delim); i++)
    	{
    		(*istr).num++;
    		(*istr).str = (char**)realloc((*istr).str, (i + 1)*sizeof(char *));
    		if ((*istr).str == NULL) return 0;
    		(*istr).str[i] = (char*)calloc(strlen(p) + 1, sizeof(char));
    		if ((*istr).str[0] == NULL) return 0;
    		strcpy((*istr).str[i], p);
    	}
    	free(str);
    	str = p = NULL;
    
    	return 1;
    }

    此外,使用string.h库里的strtok函数也能用于分割字符串,strtok函数的用法有点不寻常,参考以下程序,可以达到与上面程序相同的效果。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define SEEDNUM 10
    int main (void)
    {
    	const char * delim = ",";
    
    	FILE * sfp = NULL;
        FILE * ofp = NULL;
        sfp = fopen("10seed1122test.txt", "r");
    	ofp = fopen("strtok10output1122.txt", "w");
    	
    	if (NULL == sfp) /* 如果失败了 */
    	{
    		printf("错误!seed文件打开失败!");
    		exit(EXIT_FAILURE); /* 中止程序 */
    	}
    	if (NULL == ofp) /* 如果失败了 */
    	{
    		printf("错误!output文件打开失败!");
    		exit(EXIT_FAILURE); /* 中止程序 */
    	}
    	
    	int i;
    	for (i=0;i<SEEDNUM*2;i++)
    	{
    		char *pt;
    		char tem_buf[512];
    		fgets (tem_buf,512,sfp);
    		if (i%2)
    		{
    			pt = strtok(tem_buf+5,delim);
    			int j;
    			for(j=0; j<32 && pt; j++)
    			{
    				long value[32];
    				char *temp;
    				char *end;
    				temp = pt+2;
    				value[j] = strtol(temp, &end, 16);
    				fprintf(ofp,"%02X",value[j]);
    				pt = strtok(NULL,delim);
    			}
    			fprintf(ofp,"\n");
    		}
    	}
    	
    	return 0;
    }






    展开全文
  • 2、问题:如何判断一个函数(不是自己写的,有可能是第三方库的函数)是否会抛出异常,以及抛出那些异常?学习了异常处理,我们调用一个函数的时候,就应该知道这个函数会不会抛出异常,如果...

    作者:子宇24

    链接:https://www.cnblogs.com/dishengAndziyu/p/10920150.html

    1、本文介绍一个新的概念,它是一个重要的概念,并且是 C++ 中的一个高级主题;

    2、问题:

    • 如何判断一个函数(不是自己写的,有可能是第三方库中的函数)是否会抛出异常,以及抛出那些异常?

      学习了异常处理,我们在调用一个函数的时候,就应该知道这个函数会不会抛出异常,如果会,抛那些:

    • 如果是第三方库的函数,只有函数声明,没有函数实现,则也不知道会不会抛出异常; 

    • 查看函数文档也是不错的方法,但是如果手头文档和真实的库的版本不匹配,有可能查到的东西就是不准确的;

    3、异常规格说明:

    • C++ 提供语法用于声明函数所抛出的异常;

    • 异常声明作为函数声明的修饰符,写在参数列表后面:

      /* 可能抛出任何异常 */

              void func1();

              /* 只能抛出的异常类型:char 和 int */

              void func2() throw(charint);

              /* 不抛出任何异常 */

              void func3() throw();

    4、异常规格说明的意义:

    • 提示函数调用者必须做好异常处理的准备;

      如果想知道调用的函数会抛出哪些类型的异常时,只用打开头文件看看这个函数是怎么声明的就可以了;

    • 提示函数的维护者不要抛出其它异常;

    • 异常规格说明是函数接口的一部分;

      用于说明这个函数如何正确的使用;

    5、如果抛出的异常不在声明列表中,会发生什么?

    6、下面的代码输出什么?

    d1e3914a847fddd7b7b2c31e14bad244.png

    7、异常规格之外的异常编程实验:

    #include 

    using namespace std;

    void func() throw(int){
        cout <"func()";
        cout <endl;

        throw 'c';
    }

    int main(){
        try 
        {
            func();
        } 
        catch(int
        {
            cout <"catch(int)";
            cout <endl;
        } 
        catch(char
        {
            cout <"catch(char)";
            cout <endl;
        }

        return 0;
    }
    • BCC 显示:

      func()

      Abnormal program termination

    • g++ 显示:

      terminate called after throwing an instance of 'char'

      已放弃

    • VC 2010 显示:

      func()

      catch(char)

    8、unexpected() 函数说明:

    • 函数抛出的异常不在规格说明中,全局 unexpected() 被调用;

    • 默认的 unexpected() 函数会调用全局的 terminate() 函数;

      这是 BCC 和 g++ 编译器的行为;

    • 可以自定义函数替换默认的 unexpected() 函数实现;

      VC 2010 编译器的也不遵循行为;

    • 注意:不是所有的 C++ 编译器都支持这个标准行为;

      在异常处理这个技术点上面,编译器实现是有差异的,如果我们未来的项目中确实的要用到函数的异常规格说明时,我们最好的写一个小的测试程序,看看当前项目里面所使用的 C++ 编译器在这一个技术点的行为是怎样的,有没有遵循标准的 C++ 规范;

    9、unexpected() 函数的替换:

    • 自定义一个无返回值无参数的函数:

      能够再次抛出异常:

      当异常符合触发函数的异常规格说明时,恢复程序执行;

      见 本文10 中程序 throw 1;

      否则,调用全局 terminate() 函数结束程序;

    • 调用 set_unexpected() 设置自定义的异常函数:

      参数类型为 void(*)();

      返回值为默认的 unexpected() 函数入口地址;

    10、自定义 unexpected() 函数编程实验:

    #include 
    #include 
    #include 

    using namespace std;

    void my_unexpected(){
        cout <"void my_unexpected()" <endl;
        // exit(1);  // 退出;
        throw 1;
    }

    void func() throw(int){
        cout <"func()";
        cout <endl;

        throw 'c';
    }

    int main(){
        set_unexpected(my_unexpected);

        try 
        {
            func();
        } 
        catch(int
        {
            cout <"catch(int)";
            cout <endl;
        } 
        catch(char
        {
            cout <"catch(char)";
            cout <endl;
        }

        return 0;
    }
    • exit(1) 结果:

      g++ 编译器:

      func()

      void my_unexpected()

      BCC 编译器:

      func()

       void my_unexpected()

      VC 2010 编译器:

      func()

      catch(char)  // 未有遵循标准 C++ 规范;

    • throw 1 结果:

      g++ 编译器:

      func()

      void my_unexpected()

      catch(int)  //与触发函数 func() 的异常规格符合,于是程序恢复执行;

      BCC 编译器:

      func()

      void my_unexpected()

      catch(int)

      VC 2010 编译器:

      func()

      catch(char)  // 未有遵循标准 C++ 规范,直接捕获,然后处理;

    • 如果以后项目开发,会使用函数异常说明这个技术点,最好在项目开发前写一些小程序测试下当前使用的 C++ 编译器有没有很好的遵循 C++ 的规范;

    11、小结:

    • C++ 中的函数可以声明异常规则说明;

    • 异常规格说明可以看作接口的一部分;

    • 函数抛出的异常不在规格说明中,unexpected() 被调用;

    • unexpected() 中能够再次抛出异常;

      异常能够匹配,恢复程序的执行;

      否则,调用 terminate() 结束程序;

      un_expected() 函数是正确处理异常的最后机会,如果没有抓住,terminate() 函数会被调用,当前程序以异常告终;

    此文为作者学习唐佐林老师的学习笔记,仅为交流共享之用。


    ●编号525,输入编号直达本文

    ●输入m获取文章

    C语言与C++编程

    095db29bb99a9b9614531ec8fce7c73d.png

    分享C/C++技术文章

    展开全文
  • 如果自定义一个函数,没有任何返回值,而形参是一个指针传入这个函数,这个函数,无论如何改变指针所指的方向,函数结束后对外部数据没有变化,唯独通过指针,来间接改变函数以外的变量的值(例如令*p = 一个新...

    如果自定义一个函数,没有任何返回值,而形参是一个指针传入这个函数,在这个函数中,无论如何改变指针所指的方向,函数结束后对外部数据没有变化,唯独通过指针,来间接改变函数以外的变量的值(例如令*p = 一个新的值)。那么此时此刻,在内存中p的地址里的数据已经改变,而函数结束后,该函数对外部做出的贡献就是把原来p的地址里的数据改变了,其他都没变,包括p指针所指的地址。

    #include<stdio.h>
    void change1(int *y)
    {
    	int c = 1000;
    	y = &c;
    
    };
    
    void change2(int *y)
    {
            int c = 20;
            *y = c;//通过指针间接修改原来y所指的值
    };
    
    void main()
    {
    	int a = 3;
    	int *b = &a;
    	printf("%d\n",a);
    	printf("%d\n",*b);
    	printf("%d\n",b);
    	change1(b);
    	printf("%d\n",a);
    	printf("%d\n",b);
    	printf("%d\n",*b);
            change2(b);
            printf("%d\n",a);
    	printf("%d\n",b);
    	printf("%d\n",*b);
    }
    

    输出结果

    3
    3
    1703740
    3
    1703740
    3
    20
    1703740
    20
    Press any key to continue
    

    无论经过多少外部函数,指针b的地址在main()中始终没变,而在change2函数中通过b指针把a的值修改了

    展开全文
  • C语言自定义函数返回数组的方法(图文详解)最近看到一些同学问题,有提到说:如何在一个函数中返回数组呢?能否直接在自定义 函数,写成char *类型返回值,直接返回呢?,代码如下:直接返回str数组名(注意不需要加...
  • 如何自定义C语言.h头文件?

    万次阅读 多人点赞 2018-05-04 13:38:47
    项目实践,如果一个.c文件程序过长,可以把文件函数单独放在一个头文件,然后.c包含该头文件即可。这两天,根据所看的书《C语言的科学与艺术》和网上的资料,发现实际上有两种写法。 写法1:.h...
  • 今天的这篇文章是我刷算法题的时候遇到的,最简单的方法是直接调用java里面的Sqrt函数,不过有时候题目会要求我们不能使用库函数,所以这里我们自己定义Sqrt方法。最常见的思路有两种,第种是二分法,第二种...
  • //ps指针指向字符串下一个字符 } digit[i] = '\0'; //为了能用%s输出,digit末尾要加一个结束字符'\0' printf("%s\n", digit); ```) `` ``` **如果要传递m,n,o,q多个整形数据呢? ** 以下是我...
  • C语言sort函数如何使用

    万次阅读 多人点赞 2017-06-23 13:14:24
    c语言中没有预置的sort函数,如果在c语言中,要调用sort函数,就需要自定义一个用于排序的函数,或者使用c语言自有的qsort函数,其头文件为stdlib.h。 1、自定义排序功能 如下,为整数型从小到大排序
  • 如果在C语言中,遇到有调用sort函数,就是自定义一个函数,功能一般用于排序。 C语言有自有的qsort函数。 功 能: 使用快速排序例程进行排序 头文件:stdlib.h 原型: void qsort(void *base,int n...
  • C语言函数

    2020-11-10 19:04:41
    文章目录一、函数的概念1、函数的概念2、函数的分类二、自定义函数的声明三、自定义...每个C程序都至少有一个函数,即main主函数 ,如果程序的任务比较简单,全部的代码都写main函数,但是,实际开发,程序的任
  • 第8章函数 主要内容: 1函数的定义 函数的调用(包括嵌套调用和...使用函数的优点 1)实现模块化设计:将一个大任务分解成一个个的 小任务,然后每个任务分别用函数实现 2)实现编写一次,多次调用,避免不同的程 序重复编
  • C语言复习---函数

    2019-07-24 18:59:48
    本节主要包括以下内容...每个 C 程序都至少有一个函数,即主函数main(),所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数如何划分代码到不同的函数是由您来决定的,但逻辑上,划...
  • Anjuta建立了一个C++的Gtkmm工程,然后添加了两个自定义C语言源文件。结果编译链接时出错──“undefined reference xxxxxx”,Anjuta不知道如何链接它。开始以为是工程属性没设好,结果却是声明的问题。其实...
  • C/C++语言自定义函数如何返回数组?

    千次阅读 2018-08-29 11:24:59
    此类问题,应用场景往往为了解决函数间相互通信,比如某个函数内处理的完的结果数据需要交接给另一个函数的情况,那么一般来说,总结有以下三种: 直接使用全局变量:这种方法最方便,但此方法打破了函数间的通信及...
  • 上一节介绍了函数的概念和定义方式。我们知道了存在两类函数:库函数和自定义函数。其中库函数是系统声明和定义...在C语言中一个较大的程序往往需要由一个主函数和若干个函数构成。由主函数调用其他函数。其他函数...
  • 控制软件是用Python编写的,自定义硬件的接口是用C语言编写的,因为它是一个更快的C实现.我现在需要从我的Python开始调用我的C函数,并且最近一直在学习如何在Cython包装C.除了将Python列表传递给C函数之外,我已经...
  • 一般来说,我们编制的C语言源...其三,如果两个程序中都要用到同一个自定义函数,此函数须从一文件移动到另一文件,这种移动容易出错。为了解决这一矛盾,一个大的程序往往被分成几个部分,存放不同的DOS文件各。
  • C语言

    2021-01-31 14:55:32
    DEV-C++新建一个空白工程 步骤二 空白工程添加主函数文件以及头文件以及C文件 步骤三 头文件自定义函数声明,C文件自定义函数定义,最后主函数文件调用 注释: 1.模块化编程就是...
  • time.h文件,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下: #define CLOCKS_PER_SEC ((clock_t)1000) //CLOCKS_PER_SEC为系统自定义的 PCB进程控制块里有一个clock_t ...
  • 深度学习C语言之指针指针分析单重指针多重指针复杂指针函数指针新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格...
  • C语言自定义函数(图文详解)_后端开发每个C程序都至少有一个函数,即主函数main(),实际开发,程序的任务往往比较复杂,如果全部的代码都写main()函数,main()函数将非常庞大臃肿,结构复杂,代码重复。...
  • C 语言实验报告四 实验目的 掌握 C 语言中函数和模块 掌握怎样定义函数如何调用或使用函数如何声明函数 掌握函数的参数了解在函数调用时参数是如何传递的 使用函数的过程怎样确定函数的参数 如何使用局部变量...
  • 实用标准文案 语言实验报告四 实验目的 掌握 C 语言中函数和模块 掌握怎样定义函数如何调用或使用函数如何声明函数 掌握函数的参数了解在函数调用时参数是如何传递的 使用函数的过程怎样确定函数的参数 如何...
  • sort函数

    2017-02-10 15:03:55
    如果在C语言中,遇到有调用sort函数,就是自定义一个函数,功能一般用于排序。 一、可以编写自己的sort函数。 如下函数为将整型数组从小到大排序。 1 2 3 4 5 6 7 8 9 ...

空空如也

空空如也

1 2 3 4 5
收藏数 81
精华内容 32
关键字:

如何在c语言中自定义一个函数

c语言 订阅