利用代码发送的动态退化或同步化接口封装

利用dot Net技术中反射及代码发送的

动态退化或同步化接口封装

 

1         技术背景

在“动态”这个词到处用的时代,怎样能够让程序真正的动态起来。

Java的结构中我们看到了一个java.lang.reflect包,开始让程序能够了解程序的结构。然后作为Java的好徒弟dot Net框架中System.Reflection命名空间看到了 AssemblyBuilderModuleBuilderTypeBuilder及其它*Builder,而程序能够构造程序结构。我们进入了真正的动态运用的时代。

    回想一下,这是多么令人震惊的功能啊!让我们运行动态生成的代码吧。如果你运行的不是原本硬盘上载入的代码,那是多大的飞跃啊!

1.1         反射

反射是dot Net框架中的面向对象技术中的一个极为重要的部分。它由System.Type类和System.Reflection命名空间及其子空间中的所有类完成。在所有类的根类Object的实例方法GetType()可以得到描述实例的类信息的Type类实例。

反射的功能使得程序可以了解自身结构的手段,除此还可以提供动态构造程序集(Assembly),模块(Module),类(Type)结构的途径,使得原本僵死的程序有了活力。反射使得程序可以访问程序结构,构造程序结构。反射(reflection也称retrospection)的还可翻译为“自省”或“反省” 。

1.2         代码发送

代码发送就是运行时向方法构造器发送操作码和参数,使得最终实现动态生成类。然后就可以使用需要的代码结构进行操作。

反射发送是一种“发送”操作码的强大技术。虽然今天的编译器速度很快,内存和处理器的速度也足够,但是在必须的时候能够触及这么核心底层的部分,确实是一件令人欣慰的事情。

2         退化与同步化理论

2.1         退化

由面向对象的继承性多态性使得编程模型呈现出一个扩展的发散的结构,在许多接口的应用中将会只用到部分的功能(这里一般指方法(Method),dot Net中还包括属性(Property)和事件(Event))。那么对于其他的部分只好在实现时放出异常或不作任何操作。如此便出现了退化,也就是一部分功能的退化。举例来讲:

l         Sysetm.Collections.IListC#语言声明:

        public interface IList : ICollection, IEnumerable

        {

            int Add(object value);

            void Clear();

            bool Contains(object value);

            int IndexOf(object value);

            void Insert(int index, object value);

            void Remove(object value);

            void RemoveAt(int index);

            bool IsFixedSize { get; }

            bool IsReadOnly { get; }

            object this[int index] { get; set; }

        }

要实现上面的IList接口的只读(Read Only)封装是,要求在一个只读的派生类中退化Add, Clear, Insert, Remove, RemoveAt, this[]{set;}这些方法或属性,并且IsReadOnly返回常量true。 然而如此只是文档的规则不能保证一个返回IsReadOnly true的实例必然做好了ReadOnly退化。

这样的退化仅仅是文档内的约定,而更应该程序约束。在后面的动态封装中就介绍了标准的退化封装的手段。

2.2         同步化

实现同步化封装一般对要封装的类或接口的所有方法重写,重写模版如下:

        public override ReturnType A_Method()

        {

            lock (this._syncRoot)

                return this._target.A_Method();

        }

在直接调用前后,要进行同步化操作进入对象和退出对象。这样实现的类就成为原有类或接口的同步化封装。由于在多线程的应用中经常用到同步化封装,这里不赘述其应用了。

3         dot Net 框架中的退化与同步化封装实现

ReadOnlyList类是Sysetm.Collections.ArrayList类的私有嵌套类,是对IList接口的ReadOnly退化封装。

SyncList类是Sysetm.Collections.ArrayList类的私有嵌套类,是对IList接口的同步化封装。

通过的两个静态方法可以获得相应的封装实例,下面是相关的部分C#声明:

l         ArrayList类的摘要声明:

       public class ArrayList : IList, ICollection, IEnumerable, ICloneable

        {

            ……

            private class ReadOnlyList : IList

            {……}

            private class SyncIList : IList

            {……}

            public static IList ReadOnly(IList list)

            {

                if (list == null)

                    throw new ArgumentNullException("list");

                return new ArrayList. ReadOnlyList(list);

            }

            public static IList Synchronized(IList list)

            {

                if (list == null)

                    throw new ArgumentNullException("list");

                return new ArrayList.SyncIList(list);

            }

        }

l         ReadOnlyList类的摘要声明:

       private class ReadOnlyList : IList

        {

            internal ReadOnlyList(IList l)

            {

                this._list = l;

            }

            private IList _list;

//退化方法实现

            public virtual int Add(object obj)

            {

                throw new NotSupportedException(Environment.GetResourceString("NotSupported"));

            }

            ……

//非退化方法实现

            public virtual bool Contains(object obj)

            {

                return this._list.Contains(obj);

            }

            ……

            public virtual bool IsReadOnly

            {

                get

                {

                    return true;

                }

            }

            ……

        }

    退化的方法例如Add,放出异常。非退化的方法例如Contains,直接调用。只有IsReadOnly特殊处理返回true

l         SyncList类的摘要声明:

private class SyncIList : IList

{

      internal SyncIList(IList list)

{

      this._list = list;

      this._root = list.SyncRoot;

}

      private IList _list;

      private object _root;

      public virtual int Add(object value)

{

      lock (this._root)

            return this._list.Add(value);

}

……

      public virtual bool IsSynchronized

{

      get

      {

            return true;

      }

}

……

      public virtual object SyncRoot

{

      get

      {

            return this._root;

      }

}

}

    同步化处理所有方法例如Add。只有IsSynchronized特殊处理返回trueSyncRoot特殊处理返回初始化时输入的异步根。

4         动态封装模型

4.1         原有模式的弊端

由上面dot Net框架里的实现方法可以看到,针对需要封装的接口要写出对应的类实现。也就是说每次要按照退化或同步化的模式编写代码。可以看到代码的信息量如此之小,可以说,编写这样的代码是程序员的悲哀。

程序员的第一原则,所有重复的操作要让程序去做。如果程序员手动去做这件事不仅是折磨程序员,而且是摧毁了程序的严谨结构。这样,差错容易出现,程序可读性降低,代码冗余繁杂。

于是按照上面的模式而生成的类应该由程序实现,有人会用文本处理自动生成代码,但这不是我们的最终目的。我们要的只是一个继承对应接口的类结构,而且对具体的类名称不敏感,但我们需要他全局唯一,从而在下次引用方便。所以如果靠生成代码,那么他就不能作为通用的标准在标准库中创建实例。

客观的讲,任何地方声明的接口,都应有其唯一对应的封装实现。而不是由不同的程序员去一次次的编写不同的实现,这样也不能给出标准封装检查。

4.2         理想的封装模型

l         全局封装器Boxer类的C#语言封装部分声明:

public sealed class Boxer

{

public static object Degenerate(object target, Type interfaceType, IDegenerateProvider dp);

public static object Degenerate(object target, Type interfaceType, Type degenerateAttributeType);

public static object Synchronize(object target, Type interfaceType);

public static object Synchronize(object target, Type interfaceType, object syncRoot);

      ……

}

    我们可以通过前两个的静态方法获得任意接口的指定退化方式的退化实例。也可通过后两个静态方法获得任意接口的异步封装。

l         IDegenerateProvider接口的C#语言完整声明:

public interface IDegenerateProvider

{

      DegenerateTargets NeedDegenerate(EventInfo evn);

      bool NeedDegenerate(MethodInfo method);

      DegenerateTargets NeedDegenerate(PropertyInfo property);

}

    提供判断是否退化的判断方法的接口。退化需要提供这样的供应器实例。

l         Boxer类的C#语言封装检查部分声明:

public sealed class Boxer

{

      public static bool IsDegenerated(object target, IDegenerateProvider dp);

      public static bool IsDegenerated(object target, Type degenerateAttributeType);

      public static bool IsDegenerated(object target, Type interfaceType, IDegenerateProvider dp);

      public static bool IsDegenerated(object target, Type interfaceType, Type degenerateAttributeType);

      public static bool IsSynchronized(object target);

      public static bool IsSynchronized(object target, object syncRoot);

      public static bool IsSynchronized(object target, Type interfaceType);

      public static bool IsSynchronized(object target, Type interfaceType, object syncRoot);

    ……

}

l         DegenerateAttribute属性类和DegenerateTargets枚举类的C#语言完整声明:

public abstract class DegenerateAttribute : Attribute

{

      protected DegenerateAttribute(): this(DegenerateTargets.All){}

      protected DegenerateAttribute(DegenerateTargets targets)

      {

            this._targets = targets;

      }

      public DegenerateTargets Targets { get{ return this._targets;} }

      private readonly DegenerateTargets _targets;

      public static IDegenerateProvider GetDegenerateProvider(Type attributeType);

      internal class DegenerateProvider : IDegenerateProvider

      {

            public DegenerateProvider(Type attributeType);

      ……

      }

}

[Serializable, Flags]

public enum DegenerateTargets

{

      Method    = 0x01,

      Getter        = 0x02,

      Setter        = 0x04

      Adder         = 0x08,

      Remover   = 0x10,

 

      Event         = Adder | Remover ,

      Property = Getter | Setter,

      All       = Method | Event | Property,

      None      = 0,

}

    DegenerateAttribute为所有退化自定义属性提供抽象基类,其派生类用于指定退化的方法(Method)或属性(Property)的具体读写器或事件(Event)的具体AdderRemover。给出他的类信息可由其静态函数和嵌套类可以得到相应的IDegenerateProvider的实例。

l         理想的适应ReadOnly退化包装的Sysetm.Collections.IListC#语言完整声明,ReadOnly退化属性类:ReadOnlyDegenerateAttributeC#语言完整声明:

public interface IList : ICollection, IEnumerable

{

      [ReadOnlyDegenerate]

      int Add(object value);

      [ReadOnlyDegenerate]

      void Clear();

      bool Contains(object value);

      int IndexOf(object value);

      [ReadOnlyDegenerate]

      void Insert(int index, object value);

      [ReadOnlyDegenerate]

      void Remove(object value);

      [ReadOnlyDegenerate]

      void RemoveAt(int index);

      [ReadOnlyDegenerate (DegenerateTagets.Setter)]

      object this[int index] { get; set; }

}

[Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)]

public sealed class ReadOnlyDegenerateAttribute : DegenerateAttribute

{

      public ReadOnlyAttribute();

      public ReadOnlyAttribute(DegenerateTargets targets);

}

4.3         模型的优势

如果仅仅对某个接口人工代码实现指定退化的类。那么这个接口的继承接口的退化工作将会是由许多重复的,这样的人工代码实现将是无效率的。那么这个退化的信息应该标识到接口声明里,那么这样的信息不仅是给这个接口与这个退化的,还将提供给继承接口去完成这样的退化。

所有的接口都客观存在其退化和同步化接口封装,那么这样的封装类不应该由程序员来实现,而应该有程序动态生成。

5         如何发送代码实现动态封装类

在退化供应器的指导下我们退化的工作知道那些功能因该退化那些应该调用,而同步化的封装是出人意料的简单,每个方法的实现都有同种模式来实现。因为本文重在提供动态封装的模式。而发送代码的工作牵扯到微软中间语言(MSIL),而这只是技术实现,当然我们在其它支持反射及代码发送的平台下一样可以实现它。而且应该的是标准库中所应该提供的部分。

下面是同步化接口封装的C#语言实现的关键部分:

private static void ImplementMethodSyncInvoke(TypeBuilder tb, MethodInfo mi, FieldBuilder fb, FieldBuilder rfb)

{

      Type[] typeArray1 = Boxer.ParamsTypes(mi.GetParameters());

      MethodBuilder builder1 = tb.DefineMethod(mi.Name, Boxer. InterfaceMethodAttributes, mi.ReturnType, typeArray1);

      ILGenerator generator1 = builder1.GetILGenerator();

      generator1.DeclareLocal(typeof(object));

//为返回值申请本地内存空间

      if (mi.ReturnType != typeof(void))

            generator1.DeclareLocal(mi.ReturnType);

//载入同步根实例

      generator1.Emit(OpCodes.Ldarg_0);

      generator1.Emit(OpCodes.Ldfld, rfb);

      generator1.Emit(OpCodes.Dup);

      generator1.Emit(OpCodes.Stloc_0);

//进入同步化区

      generator1.Emit(OpCodes.Call, Boxer.ThreadEnterMethod);

//为保证不会因为调用过程的异常造成程序跳出,而形成死锁,需要try{}finally{}处理退出同步化区

//try{

      generator1.BeginExceptionBlock();

      generator1.Emit(OpCodes.Ldarg_0);

//为调用载入对象

      generator1.Emit(OpCodes.Ldfld, fb);

//载入所有参数

      int num1 = typeArray1.Length;

      if (num1 > 0)

      {

            generator1.Emit(OpCodes.Ldarg_1);

            if (num1 > 1)

            {

                  generator1.Emit(OpCodes.Ldarg_2);

                  if (num1 > 2)

                  {

                        generator1.Emit(OpCodes.Ldarg_3);

                        for (int num2 = 4; num2 <= num1; num2++)

                              generator1.Emit(OpCodes.Ldarg_S, (byte) num2);

                  }

            }

      }

//调用

      generator1.Emit(OpCodes.Callvirt, mi);

//存储返回值

      if (mi.ReturnType != typeof(void))

            generator1.Emit(OpCodes.Stloc_1);

//}

//finally{

      generator1.BeginFinallyBlock();

      generator1.Emit(OpCodes.Ldloc_0);

      generator1.Emit(OpCodes.Call, Boxer.ThreadExitMethod);

//}

      generator1.EndExceptionBlock();

//载入返回值

      if (mi.ReturnType != typeof(void))

            generator1.Emit(OpCodes.Ldloc_1);

      generator1.Emit(OpCodes.Ret);

      tb.DefineMethodOverride(builder1, mi);

}

private static void ImplementInterface(TypeBuilder tb, Type interfaceType, FieldBuilder fb, FieldBuilder rfb)

{

//实现Methods

      MethodInfo[] infoArray1 = interfaceType.GetMethods();

      for (int num1 = 0; num1 < infoArray1.Length; num1++)

      {

            MethodInfo info1 = infoArray1[num1];

            Boxer.ImplementMethodSyncInvoke(tb, info1, fb, rfb);

      }

//实现Properties

      PropertyInfo[] infoArray2 = interfaceType.GetProperties();

      for (int num2 = 0; num2 < infoArray2.Length; num2++)

      {

            PropertyInfo info2 = infoArray2[num2];

            MethodInfo info3 = info2.GetGetMethod(true);

            if (info3 != null)

                  Boxer.ImplementMethodSyncInvoke(tb, info3, fb, rfb);

            info3 = info2.GetSetMethod(true);

            if (info3 != null)

                  Boxer.ImplementMethodSyncInvoke(tb, info3, fb, rfb);

      }

//实现Events

      EventInfo[] infoArray3 = interfaceType.GetEvents();

      for (int num3 = 0; num3 < infoArray3.Length; num3++)

      {

            EventInfo info4 = infoArray3[num3];

            MethodInfo info5 = info4.GetAddMethod(true);

            if (info5 != null)

                  Boxer.ImplementMethodSyncInvoke(tb, info5, fb, rfb);

            info5 = info4.GetRemoveMethod(true);

            if (info5 != null)

                  Boxer.ImplementMethodSyncInvoke(tb, info5, fb, rfb);

      }

}

internal static object InternalSynchronize(object target, Type interfaceType, object syncRoot)

{

      object obj1;

      lock (Boxer.SynchronizedTable)

      {

         //找出已经生成的对于动态类的构造函数

            ConstructorInfo info1 = (ConstructorInfo) Boxer.SynchronizedTable[interfaceType];

            if (info1 == null)

            {

                  Type[] typeArray1 = new Type[2] { interfaceType, typeof(object) } ;

                  TypeBuilder builder1 = Boxer.BoxerModuleBuilder.DefineType("BoxedClasses.Synchronized" + (++Boxer.SynchronizedCount), TypeAttributes.Public);

                  builder1.SetCustomAttribute(new CustomAttributeBuilder(Boxer.SynchronizedAttribute.Constructor, new object[0]));

                  builder1.AddInterfaceImplementation(interfaceType);

//构造字段target

                  FieldBuilder builder2 = builder1.DefineField(Boxer.FindName(interfaceType, "_target"), interfaceType, Boxer.FieldAttribute);

//构造字段syncroot

                  FieldBuilder builder3 = builder1.DefineField(Boxer.FindName(interfaceType, "_syncroot"), typeof(object), Boxer.FieldAttribute);

//构造唯一的构造方法

                  ConstructorBuilder builder4 = builder1.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, typeArray1);

                  ILGenerator generator1 = builder4.GetILGenerator();

                  generator1.Emit(OpCodes.Ldarg_0);

                  generator1.Emit(OpCodes.Call, Boxer.ObjectConstructor);

                  generator1.Emit(OpCodes.Ldarg_0);

                  generator1.Emit(OpCodes.Ldarg_1);

                  generator1.Emit(OpCodes.Stfld, builder2);

                  generator1.Emit(OpCodes.Ldarg_0);

                  generator1.Emit(OpCodes.Ldarg_2);

                  generator1.Emit(OpCodes.Stfld, builder3);

                  generator1.Emit(OpCodes.Ret);

                  Boxer.ImplementInterface(builder1, interfaceType, builder2, builder3);

                  Type[] typeArray3 = interfaceType.GetInterfaces();

                  for (int num1 = 0; num1 < typeArray3.Length; num1++)

                  {

                        Type type1 = typeArray3[num1];

                        Boxer.ImplementInterface(builder1, type1, builder2, builder3);

                  }

//将此实例加入全局表,以便后用

                  Boxer.SynchronizedTable.Add(interfaceType, (info1 = builder1.CreateType().GetConstructor(typeArray1)));

            }

            object[] objArray1 = new object[2] { target, syncRoot } ;

            obj1 = info1.Invoke(objArray1);

      }

      return obj1;

}

6         新的语法规范

.NET 2.0 基础类库对范型的应用来看,这里的退化和同步化当然也可以作出新的语法规范方便程序员调用。下面以C#语言为例介绍新的语法规范。

6.1         同步化

我们可以通过关键字synchronizeon来得到对应的同步化的类实例,通过issynchronized得到同步化检查,例如:

IList list;

object syncRoot;

……

//[] 为可选部分

IList  slist = list synchronize IList [on syncRoot ];

//内部实现=(IList)Boxer.Synchronize(list[, syncRoot]);

bool issync = slist issynchronized IList [on syncRoot];

//内部实现=Boxer.IsSynchronized(slist [, syncRoot]);

6.2         退化

我们可以通过关键字degenerate on可获得退化类实例,通过isdegenerated得到同步化检查,例如:

IList list;

IDegenerateProvider degenerateProvider;

……

IList dlist = list degenerate IList on typeof(ReadOnlyDegenerateAttribute);

       //内部实现= (IList)Boxer.Degenerate(list, typeof(ReadOnlyDegenerateAttribute));

IList dlist1 = list degenerate IList on degenerateProvider;

       ///内部实现= (IList)Boxer.Degenerate(list, degenerateProvider);

Bool isdeg = dlist isdegenerated IList on typeof(ReadOnlyDegenerateAttribute);

       //内部实现=(IList)Boxer.IsDegenerated(list, typeof(ReadOnlyDegenerateAttribute));

6.3         无退化接口封装

我们可以通过关键字box可获得接口封装实例,通过isboxed得到同步化检查,例如:

IList list = new ArrayList();

……

IList blist = list box IList;

       //内部实现= (IList)Boxer.Degenerate(list, typeof(NonDegenerateAttribute));

Bool isb = blist isboxed IList;

       //内部实现=(IList)Boxer.IsDegenerated(list, typeof(NonDegenerateAttribute));

 

<think>嗯,用户想要在初始化表的基础上统计并输出表中元素的个数的完整C语言代码。首先,我需要明确“初始化表”具体指的是什么。通常在C语言中,这可能涉及到数组者某种数据结构,比如链表、动态数组等。但用户没有特别说明,所以可能是指一个普通的数组。 接下来,统计元素个数。如果是静态数组,比如int arr[10],那么可以用sizeof(arr)/sizeof(arr[0])来计算元素个数。但如果数组是动态分配的,者作为函数参数传递(这时会退化为指针),这种方法就不适用了。所以需要确认用户的需求场景。 用户提到“初始化表”,可能意味着这个表已经被填充了数据,但可能不是填满的。比如,声明了一个固定大小的数组,但只初始化了部分元素,这时候需要统计实际有效的元素个数。这种情况下,可能需要一个结束标记,比如字符串的'\0',者用一个特定的值作为结束标志,者维护一个单独的变量记录当前元素数量。 假设用户的情况是有一个数组,并且已经初始化了一些元素,需要统计实际存储的元素数量。例如,定义一个结构体作为表,包含数据数组和长度变量。者用户可能希望自己遍历数组直到遇到某个终止符,比如0-1。 另外,用户可能希望得到一个完整的代码示例,所以需要包含必要的头文件、main函数,以及具体的统计逻辑。可能需要考虑不同的情况,比如静态数组、动态数组,者用结构体管理的情况。 比如,如果是一个结构体中的动态数组,可能有一个成员记录当前元素个数。这时候统计直接访问该成员即可。但用户的问题是在初始化表的基础上统计,所以可能需要遍历数组直到结束标记,者使用结构体中的长度信息。 可能的代码结构:定义一个数组,初始化部分元素,然后统计个数。例如: int arr[] = {1,2,3,4,5,0}; // 假设0是结束标记 int count = 0; while(arr[count] != 0) { count++; } 但这样需要预先确定结束标记。者使用结构体: typedef struct { int data[MAX_SIZE]; int length; } Table; 然后初始化时设置length为实际元素个数,这样直接输出length即可。 者,用户可能希望统计数组中被初始化为非零的元素个数,但这种情况不太常见,因为数组初始化后未指定的元素可能为0,但如果是静态初始化部分元素,其余自动补零,这时候统计非零元素的个数可能是一个需求。 需要进一步分析用户可能的真实需求。如果用户没有明确说明数据结构,可能需要做出合理的假设,并在回答中说明不同的情况。 可能的步骤: 1. 定义数组并初始化部分元素。 2. 计算数组总长度(适用于静态数组)。 3. 者遍历数组直到结束标记,统计有效元素。 4. 输出统计结果。 例如,静态数组的例子: #include <stdio.h> int main() { int arr[] = {1, 2, 3, 4, 5}; // 初始化表 int count = sizeof(arr) / sizeof(arr[0]); printf("元素个数:%d\n", count); return 0; } 这种情况下,统计的是数组的总长度,但假设所有元素都被有效初始化。但如果是部分初始化,比如int arr[10] = {1,2,3}; 这时候sizeof方法得到的是10,但用户可能想要3个有效元素。这时候需要不同的处理方式,比如使用一个特定的结束符,者在结构体中维护长度。 所以需要明确用户的情况。可能用户的问题更偏向于如何管理一个动态的表,比如线性表,并统计其元素数量。例如: typedef struct { int *data; int length; int capacity; } ArrayList; void initArrayList(ArrayList *list, int capacity) { list->data = (int *)malloc(capacity * sizeof(int)); list->length = 0; list->capacity = capacity; } 然后,当添加元素时,length增加。统计的时候直接输出length。 这种情况下,完整的代码可能包括初始化表,添加元素,然后输出length。 但用户的问题可能更基础,可能只需要一个数组的例子,统计元素个数。者用户可能混淆了“初始化”和实际存储的元素数量。 综上,可能需要给出两种情况的示例:静态数组的总长度,以及动态表中有效元素的统计。但用户的问题可能更倾向于前者,所以先给出静态数组的例子,然后说明如果是动态情况如何处理。 最终,可能给出一个使用结构体管理表,包含初始化函数和统计输出的完整代码。</think>以下是一个在C语言中初始化数组并统计元素个数的完整示例代码: ```c #include <stdio.h> #define MAX_SIZE 100 // 表的最大容量 // 定义线性表结构 typedef struct { int data[MAX_SIZE]; // 存储元素的数组 int length; // 当前元素个数 } SeqList; // 初始化表 void InitList(SeqList *L) { L->length = 0; // 初始时元素个数为0 // 可选:预置初始数据(根据需求修改) int init_values[] = {2, 4, 6, 8, 10}; int init_length = sizeof(init_values)/sizeof(int); for (int i = 0; i < init_length; i++) { L->data[i] = init_values[i]; } L->length = init_length; } int main() { SeqList myList; // 1. 初始化表 InitList(&myList); // 2. 直接获取已存储的元素个数 printf("表中元素个数为:%d\n", myList.length); // 3. 验证输出(可选) printf("元素内容:"); for (int i = 0; i < myList.length; i++) { printf("%d ", myList.data[i]); } return 0; } ``` 代码解析: 1. **结构定义**:通过`SeqList`结构封装数组和长度计数器,符合数据封装思想 2. **初始化函数**: - `InitList()`函数负责初始化数据结构 - 包含预置的初始化数据(可根据需求修改`init_values`数组) - 自动计算初始元素数量并更新length字段 3. **元素统计**: - 直接访问`length`字段即可获取当前元素数量 - 时间复杂度为$O(1)$,无需遍历 4. **扩展性**: - 支持动态插入/删除操作(需配套实现相关函数) - 通过维护length字段确保数据一致性 注意事项: 1. 此实现使用静态数组,适合已知最大容量的场景 2. 如需动态扩容,可改用动态内存分配(malloc/realloc) 3. 预置的初始化数据可根据实际需求修改删除 4. 插入/删除元素时需同步更新length字段 执行结果: ``` 表中元素个数为:5 元素内容:2 4 6 8 10 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值