C常见陷阱,scanf不执行,以及指针类型应用传递。

1.最近写了个结构体,一开始是这样的:

typedef struct fsll

{

  int  data_field;

  struct fsll *next;

}FSLL;

很普通的一个链表结构体,工作需要数据域改成char类型。

typedef struct fsll

{

  char data_field;

  struct fsll *next;

}FSLL;

...

for(...)

{

printf("请输入数据域内容:")

scanf("%c",&p->data_field);

}

发现scanf每隔一句就会被跳过一次。执行结果就是链表中的数据域是这样的:( )->(A)->( )->(C)->....

其实原因就是windows下,键入回车键产生了两个字符:013 回车与010换行。编辑器把013回车作为判断输入结束的标志,而010  也就是\n留在了输入流的首端。第二次循环中。scanf的真正功能是从输入流中读取相应数量的字符,%d不会匹配\n,所以一般的数字链表不会产生这种问题。但%c,%s这种,可以从输入流中读取\n,也就造成了第二次scanf从键盘赋值得到了一个\n(输出\n什么也不显示),效果看起来就像是scanf间歇性被跳过。解决办法很简单,就是每次用scanf获取键盘的字符类型时,在语句前面调用一次getchar();消耗掉\n,以便scanf可以获取正确的值。关于getchar的妙用还有很多,以后有机会慢慢讲。

for(...)

{

printf("请输入数据域内容:")

getchar();

scanf("%c",&p->next);

}

2.把建立线性表封装成函数,实现在主函数中调用中,碰到了问题。由于纯C语言并不支持引用传递,所以像这种写法是会报错的:

void create_linked_list(FSLL *&head);

但如果想让参数在主函数与自定义函数之间传递(真正改变head的值),需要使用地址传递的方式,而用地址传递一个指针变量的写法也是真的很难看:

void create_linked_list(FSLL **head);

没错,这就是把指针变量的地址传进来,直接改地址对应的值,实现对实际参数的改变(真底层);

调用的时候是这样:

FSLL *head;

create_linked_list(&head);

以上就结束了本片博客

typedef struct fsll

{

  int  data_field;

  struct fsll *next;

}FSLL;

原文地址:https://www.cnblogs.com/hanrui0617/p/9657562.html

时间: 2024-10-25 01:00:10

C常见陷阱,scanf不执行,以及指针类型应用传递。的相关文章

Linux共享内存使用常见陷阱与分析 - 51CTO.COM http://os.51cto.com/art/201311/418977_all.htmIPC---共享内存

共享内存就是允许两个或多个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据时,不需要在客户进程和服务器进程之间幅值,因此是最快的一种IPC.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 注意:共享内存并未提供同步机制,也就是说,

Go开发常见陷阱

Go作为一种简便灵巧的语言,深受开发者的喜爱.但对于初学者来说,要想轻松驾驭它,还得做好细节学习工作. 初学者应该注意的地方: 大括号不能独立成行. 未使用变量错误——对于全局变量和函数参数变量,是可以定义后不使用的.但是对于函数内部变量来说,如果进行定义后不进行使用,编译器会提示错误. 导入包未调用错误——导入包后,如果不进行调用,例如函数,接口,结构及变量等对象,那么会出现编译错误.这里建议使用空白表示符“_”来避免类似错误. 变量简写只适用于函数内部. 重新定义变量要使用简写声明——你不能

void及void指针类型

1.概述 许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并 详述void及void指针类型的使用方法与技巧. 2.void的含义 void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据. void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错,提示“illegal use of ty

C# 指针学习笔记之指针类型

大学的时候学过C++.C,最近工作也不是很忙,就想起看看C#中的指针,看看.回忆一下啊,指针的用法,以下学习笔记摘自msdn:指针类型 在不安全的上下文中,类型可以是指针类型以及值类型或引用类型.指针类型声明具有下列形式之一: type* identifier; void* identifier; //allowed but not recommended 下列类型都可以是指针类型: sbyte.byte.short.ushort.int.uint.long.ulong.char.float.d

void类型和void *指针类型(网上摘抄总结)【转】

http://www.blogjava.net/fhtdy2004/archive/2009/07/09/286004.html 现在在学linux编程过程中遇到很多void *指针类型,由于c很早学的有些细节不甚了解,就查了查,在C++中很少用void *指针类型的?没注意过 1.概述 许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并 详述void及void指针类型的使用方法与技巧. 2.void的含义

深入探索C++对象模型--指针类型 & 多态机制

指针的类型 不同类型的指针,从内存需求的观点来说,没有什么不同!他们三个都需要足够的内存来繁殖一个机器地址,"指向不同类型之各指针"之间的差异,既不在其指针表示法不同,也不再其内容(代表一个地址)不同,而是在其所寻址出来的对象类型不同.也就是说,"指针类型"会导致编译器如何解释某个特定地址中的内存内容及其大小 1.  一个指向地址1000的整数地址,在32位机器上,将涵盖地址空间1000~1003 2.  那么,一个指向地址1000而类型为void*的指针,将涵盖怎

类成员变量中存在引用,const,和指针类型时需要注意的事项

背景知识 编译器默认生成函数的规则如下: 1.定义一个类时,如果自己没有声明,那么编译器会自动帮助生成一个拷贝构造函数(copy construction),赋值操作符(copy assignment),析构函数(deconstruction). 2.如果没有声明任何构造函数(包括拷贝构造函数),编译器会帮助声明一个默认构造函数. 构造函数(包括编译器生成的默认构造函数)的执行包括两个阶段: 1.初始化阶段 2.构造函数体内代码执行构造的阶段 构造函数执行的两个阶段非常重要,在初始化阶段,如果类

不同平台下int类型、指针类型的数据大小

不同平台下int类型.指针类型的数据大小 对于int类型数据和指针类型数据的大小,是非常基础的问题. 在一个具体的平台上,确定他们最好的办法就是使用sizeof(type)对其进行判断,返回当前数据类型的大小. 在不同的平台下,int类型和指针类型的数据类型大小时怎样的呢?如果要给出一个统一的答案,自然不可能集齐每个平台,一个个地去试,我们必须从底层进行分析. 数据总线和地址总线 计算机内的数据总线是CPU与外设进行数据交换的通路,而地址总线则是CPU用于寻址的通路. 数据总线的位数决定了CPU

用typedef定义函数指针类型(转)

typedef可以用于定义函数指针类型: [语法]typedef <返回类型> (*<函数类型名>)(参数表)typedef <返回类型> (<类名>::*<函数类型名>)(参数表) [用途]1.可以用来定义该函数类型的函数指针,就不用每次使用函数指针都要写一次函数原型了:2.有了类型名,就可以使用在容器里面,譬如map<int, 类型名>,用于实现灵活的函数调用. [示例] 例1:typedef void (*PF)(int x);