⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 list.c

📁 3D游戏场景编辑器
💻 C
📖 第 1 页 / 共 2 页
字号:

// Search for an item in the list.
// For each item in the list, the SearchFcn is called with the item's data,
// and lParam.
// lParam is a pointer to a user-defined data block.
// Returns GE_TRUE if the search is successful.  If GE_TRUE is returned,
// a pointer to the found item's data is returned in *ppData, and
// *pli is initialized to reference the found item.
// Returns GE_FALSE if the search is not successful.
geBoolean List_Search
	(
	  List *pList,
	  List_SearchCallback SearchFcn,
	  void *lParam,
	  void **ppData,
	  ListIterator *pli
	)
{
    void *pData;

    assert (pList != NULL);
    assert (SearchFcn != NULL);

    pData = List_GetFirst (pList, pli);
    while (pData != NULL)
    {
        if (SearchFcn (pData, lParam) != GE_FALSE)
        {
			*ppData = pData;
			return GE_TRUE;
        }
        pData = List_GetNext (pList, pli);
    }
    return GE_FALSE;
}



#ifdef LIST_TEST_CODE
#include <stdio.h>

#pragma warning (disable: 4100)
static void StringPrint (void *item, void *lParam)
{
	char *s;

	s = (char *)item;

	printf ("%s\n", s);
}
#pragma warning (default: 4100)

static geBoolean StringSearchFcn (void *p1, void *lParam)
{
	char *i1 = (char *)p1;
	char *i2 = (char *)lParam;

	return (strcmp (i1, i2) == 0) ? GE_TRUE : GE_FALSE;
}

static void StringDestroyFcn (void *p1)
{
	assert (p1 != NULL);
	free (p1);
}

/*
  The test code reads list commands from an input file and applies those
  commands to lists.  The commands are in a sort of mini scripting language.

  The commands take the form <command> <argument>, where <command> is
  a 1- or 2-letter command (see below), and the argument is a string.
  Commands are stored in the file one per line, with <command> being
  the first two characters, followed by a space, and then the argument
  which takes up the rest of the line.  Blank lines and lines that start 
  with a semicolon are considered comments and are ignored by the
  interpreter.

  For example:

  ;create a new list
  n
  ;append an item
  a Hello, world
  ;print the list from front to back
  pf
  ;destroy the list
  d

  The full list of commands is:

  c		Create a new list	no argument
  d		Destroy a list		no argument
  a		Append an item		argument is the item to append
  p		Prepend an item		argument is the item to prepend
  s		Search for an item	argument is the item to search for
  ib	Insert before		argument is the item to insert
  ia	Insert after		argument is the item to insert
  gf	Get First			no argument
  gn	Get Next			no argument
  gl	Get Last			no argument
  gp	Get Previous		no argument
  r		Remove				no argument
  pc	Print current		no argument
  pn	Print # items		no argument
  pl	Print list			no argument
  pb	Print list reversed no argument
  pr	Print				string to output

  The script interpreter maintains the concept of a "current item,"
  which is initialized by Search, GetFirst, or GetLast, and is
  updated by GetNext and GetPrevious.  This current item is an
  implied argument in Insert before, Insert after, GetNext, GetPrevious,
  and Remove.
*/

static geBoolean ParseCommand
	(
	  char const *InputLine,
	  int LineNo,
	  List **ppList,
	  ListIterator *pCurItem,
	  char **ppCurData
	)
{
	short intcmd;
	char *sarg;
	geBoolean rslt;

	if ((InputLine[0] == '\0') || (InputLine[0] == ';'))
	{
		// it's a comment line
		return GE_TRUE;
	}
	if ((InputLine[1] == ' ') || (InputLine[1] == '\0') || (InputLine[1] == '\n'))
	{
		intcmd = InputLine[0];
	}
	else if ((InputLine[2] == ' ') || (InputLine[2] == '\0') || (InputLine[2] == '\n'))
	{
		short temp;

		intcmd = *((short *)&InputLine[0]);
		// swap the bytes
		temp = (short)(intcmd & 0xff);
		intcmd = (short)((intcmd >> 8) | (temp << 8));
	}
	else
	{
		printf ("Parse error on line %d\n", LineNo);
		return GE_FALSE;
	}

	rslt = GE_TRUE;
	switch (intcmd)
	{
		case 'c' :
			if (*ppList != NULL)
			{
				puts ("Warning:  Deleting old list.");
				List_Destroy (ppList, StringDestroyFcn);
			}
			*ppList = List_Create ();
			if (*ppList == NULL)
			{
				puts ("Error creating list");
				rslt = GE_FALSE;
			}
			else
			{
				puts ("Created new list");
			}
			break;

		case 'd' :
			if (*ppList == NULL)
			{
				puts ("Warning:  Trying to destroy NULL list.");
			}
			else
			{
				puts ("Destroy list");
				List_Destroy (ppList, StringDestroyFcn);
			}
			break;

		case 'a' :
			sarg = strdup (&InputLine[2]);
			if (sarg == NULL)
			{
				puts ("Error: no argument for append");
				rslt = GE_FALSE;
			}
			else
			{
				if (List_Append (*ppList, sarg))
				{
					printf ("Append (%s)\n", sarg);
				}
				else
				{
					puts ("Error in append");
					rslt = GE_FALSE;
				}
			}
			break;

		case 'p' :
			sarg = strdup (&InputLine[2]);
			if (sarg == NULL)
			{
				puts ("Error: no argument for prepend");
				rslt = GE_FALSE;
			}
			else
			{
				if (List_Prepend (*ppList, sarg))
				{
					printf ("Prepend (%s)\n", sarg);
				}
				else
				{
					puts ("Error in Prepend");
					rslt = GE_FALSE;
				}
			}
			break;

		case 's' :
			sarg = strdup (&InputLine[2]);
			if (sarg == NULL)
			{
				puts ("Error:  no argument for search");
				rslt = GE_FALSE;
			}
			else
			{
				geBoolean SrchRslt;
				char *pData;

				SrchRslt = List_Search (*ppList, StringSearchFcn, sarg, (void **)&pData, pCurItem);
				if (SrchRslt)
				{
					printf ("Search:  Found (%s).  Data = (%s)\n", sarg, pData);
				}
				else
				{
					printf ("Search:  Unable to find (%s)\n", sarg);
				}
			}
			break;

		case 'ib' :
			sarg = strdup (&InputLine[3]);
			if (sarg == NULL)
			{
				puts ("Error:  no argument for insert before.");
				rslt = GE_FALSE;
			}
			else
			{
				if (List_InsertBefore (*ppList, *pCurItem, sarg) != LIST_INVALID_NODE)
				{
					printf ("Insert (%s) before (%s).\n", sarg, (*pCurItem)->Data);
				}
				else
				{
					printf ("InsertBefore:  error inserting (%s)\n", sarg);
					rslt = GE_FALSE;
				}
			}
			break;

		case 'ia' :
			sarg = strdup (&InputLine[3]);
			if (sarg == NULL)
			{
				puts ("Error:  no argument for insert after.");
				rslt = GE_FALSE;
			}
			else
			{
				if (List_InsertAfter (*ppList, *pCurItem, sarg))
				{
					printf ("Insert (%s) after (%s).\n", sarg, (*pCurItem)->Data);
				}
				else
				{
					printf ("InsertAfter:  error inserting (%s)\n", sarg);
					rslt = GE_FALSE;
				}
			}
			break;

		case 'gf' :
			puts ("Get First");
			*ppCurData = List_GetFirst (*ppList, pCurItem);
			break;

		case 'gn' :
			puts ("Get Next");
			*ppCurData = List_GetNext (*ppList, pCurItem);
			break;

		case 'gl' :
			puts ("Get Last");
			*ppCurData = List_GetLast (*ppList, pCurItem);
			break;

		case 'gp' :
			puts ("Get Previous");
			*ppCurData = List_GetPrev (*ppList, pCurItem);
			break;

		case 'r' :
			puts ("Remove");
			List_Remove (*ppList, *pCurItem, StringDestroyFcn);
			break;

		case 'pc' :
			if (*ppCurData == NULL)
			{
				puts ("No current item to print\n");
			}
			else
			{
				printf ("Print Current = (%s)\n", *ppCurData);
			}
			break;

		case 'pn' :
			printf ("NumItems = %d\n", List_GetNumItems (*ppList));
			break;

		case 'pl' :
			puts ("Print list");
			printf ("NumItems = %d\n", List_GetNumItems (*ppList));
			puts ("----------");
			List_ForEach (*ppList, StringPrint, NULL);
			puts ("----------");
			break;

		case 'pb' :
		{
			char *MyData;
			ListIterator li;

			puts ("Print list backwards");
			printf ("NumItems = %d\n", List_GetNumItems (*ppList));
			puts ("--------------------");
			MyData = List_GetLast (*ppList, &li);
			while (MyData != NULL)
			{
				printf ("%s\n", MyData);
				MyData = List_GetPrev (*ppList, &li);
			}
			puts ("--------------------");
			break;
		}
		case 'pr' :
			puts (&InputLine[3]);
			break;

		default :
			printf ("Unknown command on line %d\n", LineNo);
			rslt = GE_FALSE;
			break;
	}
	if (!rslt)
	{
		printf ("Error on line %d\n", LineNo);
		printf ("Line = (%s)\n", InputLine);
	}
	return rslt;
}

int main 
	(
	  int argc,
	  char *argv[]
	)
{
	List *pList;
	ListIterator CurItem;
	char *pCurrentData;
	char *InputFilename;
	FILE *infile;
	int LineNo;
	geBoolean rslt;

	puts ("List test version 1.0");
	puts ("---------------------");
	if (argc != 2)
	{
		puts ("Usage is List <scriptname>");
		puts ("See source for scripting information.");
		return 0;
	}


	InputFilename = argv[1];
	infile = fopen (InputFilename, "rt");
	if (infile == NULL)
	{
		printf ("Can't open input file: '%s'\n", InputFilename);
		return 0;
	}

	LineNo = 0;
	pList = NULL;
	CurItem = LIST_INVALID_NODE;
	rslt = GE_TRUE;
	while (rslt && !feof (infile))
	{
		char InputLine[256];
		char *c;

		if (fgets (InputLine, sizeof (InputLine), infile) == NULL)
		{
			// Why is this test necessary?
			// Why doesn't feof return TRUE above?
			if (!feof (infile))
			{
				puts ("Input error");
			}
			break;
		}
		// strip newline
		c = strchr (InputLine, '\n');
		if (c != NULL)
		{
			*c = '\0';
		}
		++LineNo;
		rslt = ParseCommand (InputLine, LineNo, &pList, &CurItem, &pCurrentData);
	}

	if (pList != NULL)
	{
		List_Destroy (&pList, StringDestroyFcn);
	}

	fclose (infile);
	return 0;
}


#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -