您当前的位置:首页 > IT编程 > C++
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:C++ AssertWarn函数代码示例

51自学网 2021-06-01 19:48:00
  C++
这篇教程C++ AssertWarn函数代码示例写得很实用,希望能帮到您。

本文整理汇总了C++中AssertWarn函数的典型用法代码示例。如果您正苦于以下问题:C++ AssertWarn函数的具体用法?C++ AssertWarn怎么用?C++ AssertWarn使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。

在下文中一共展示了AssertWarn函数的23个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: AssertWarn

//-----------------------------------------------------------------------------// Get the size of the file in bytes.// It is an error to query the file size for a Closed file, or for one with an// error status.//-----------------------------------------------------------------------------U32 File::getSize() const{   if (handle != NULL)   {	  AssertWarn(Closed != currentStatus, "File::getSize: file closed");	  AssertFatal(handle != NULL, "File::getSize: invalid file handle");	  if (Ok == currentStatus || EOS == currentStatus)	  {		 struct stat statData;		 if(fstat(fileno((FILE*)handle), &statData) != 0)			return 0;		 // return the size in bytes		 return statData.st_size;	  }	  return 0;   }   AssertWarn(Closed != currentStatus, "File::getSize: file closed");   AssertFatal(buffer != NULL, "File::getSize: invalid file buffer");      if (Ok == currentStatus || EOS == currentStatus)   {      return size;   }      return 0;}
开发者ID:120pulsations,项目名称:Torque2D,代码行数:37,


示例2: CreateFile

Bool GFXFont::read( const char *in_name ){   Bool           success;   HANDLE         fileHandle;    // handle of opened file   fileHandle = CreateFile(in_name,                           GENERIC_READ,                           FILE_SHARE_READ,                           NULL,                           OPEN_EXISTING,                           FILE_ATTRIBUTE_NORMAL,                           NULL                           );   if ( fileHandle == INVALID_HANDLE_VALUE )   {      AssertWarn(0, avar("GFXFont::load: Unable to load font %s, CreateFile for reading failed.", in_name));      return FALSE;   }   FileRStream frs(fileHandle);   success = read( &frs );   frs.close();   CloseHandle( fileHandle );   if ( success )      return TRUE;   else   {      AssertWarn(0, avar("GFXFont::load: Unable to load font %s, StreamIO for reading failed.", in_name));      return FALSE;   }}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:32,


示例3: GetDateFormat

String Platform::localTimeToString( const LocalTime &lt ){   // Converting a LocalTime to SYSTEMTIME   // requires a few annoying adjustments.   SYSTEMTIME st;   st.wMilliseconds  = 0;   st.wSecond        = lt.sec;   st.wMinute        = lt.min;   st.wHour          = lt.hour;   st.wDay           = lt.monthday;   st.wDayOfWeek     = lt.weekday;   st.wMonth         = lt.month + 1;   st.wYear          = lt.year + 1900;         TCHAR buffer[1024] = {0};   S32 result = 0;   String outStr;   // Note: The 'Ex' version of GetDateFormat and GetTimeFormat are preferred    // and have better support for supplemental locales but are not supported    // for version of windows prior to Vista.    //   // Would be nice if Torque was more aware of the OS version and    // take full advantage of it.   result = GetDateFormat( LOCALE_USER_DEFAULT,                           DATE_SHORTDATE,                           &st,                           NULL,                           (LPTSTR)buffer,                           1024 );   // Also would be nice to have a standard system for torque to   // retrieve and display windows level errors using GetLastError and   // FormatMessage...   AssertWarn( result != 0, "Platform::getLocalTime" );   outStr += buffer;   outStr += "/t";   result = GetTimeFormat( LOCALE_USER_DEFAULT,                           0,                           &st,                           NULL,                           (LPTSTR)buffer,                           1024 );   AssertWarn( result != 0, "Platform::localTimeToString, error occured!" );      outStr += buffer;      return outStr;}
开发者ID:fr1tz,项目名称:terminal-overload,代码行数:55,


示例4: AssertWarn

ResourceOld<AtlasFile> AtlasFile::load(const char *filename){   ResourceOld<AtlasFile> af;   af = gResourceManager->load(filename);   // If we didn't get something back from the resman or we fail to open it,   // then clean up and error out.   if(af.isNull())   {      Con::errorf("AtlasFile::load - cannot open atlas file '%s'.", filename);      return af;   }   if(!af->hasStream())   {      Con::printf("AtlasFile::load - loading Atlas resource %x with %s", (AtlasFile*)af, filename);      if(!af->open(filename))         Con::errorf("AtlasFile::load - cannot open atlas file '%s'.", filename);   }   AssertWarn(!af.isNull() && af->getTOCCount(), "AtlasFile::load - loaded empty atlas file!?");   return af;}
开发者ID:gitrider,项目名称:wxsj2,代码行数:25,


示例5: CreateFile

//================================================================// NAME//   GFXBitmapArray::read//   // DESCRIPTION//   //   // ARGUMENTS //   //   // RETURNS //   //   // NOTES //   //================================================================Bool GFXBitmapArray::read(const char *in_filename, DWORD in_flags){   Bool   result;   HANDLE fileHandle;   fileHandle = CreateFile(in_filename,                           GENERIC_READ,                           FILE_SHARE_READ,                           NULL,                           OPEN_EXISTING,                           FILE_ATTRIBUTE_NORMAL,                           NULL                           );   if (fileHandle == INVALID_HANDLE_VALUE)   {      AssertWarn(0, avar("GFXBitmapArray::load: Unable to open file %s, CreateFile for reading failed.", in_filename));      return (FALSE);   }   FileRStream frs(fileHandle);   result = read(&frs, in_flags);   frs.close();   CloseHandle(fileHandle);   return(result);}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:41,


示例6: m_mul

Point2F& m_mul( const Point2F& a, const TMat2F& m, Point2F* r ){	AssertWarn( &a != r, "m_mul: dest should not be same as source" );   r->x = a.x * m.m[0][0] + a.y * m.m[1][0] + m.p.x;   r->y = a.x * m.m[0][1] + a.y * m.m[1][1] + m.p.y;   return *r;}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:7,


示例7: FileStream

void Journal::Record(const char * file){   if (_State == DisabledState)   {      Con::errorf("//---------------------------------------------//");                  Con::errorf("Journal::Record() - Cannot record a journal after GuiCanvas or NetConnection creation!");                  Con::errorf("To record before canvas/netConnection creation, run %s with the following arguments: -jSave %s",         Platform::getExecutableName(), file);      Con::errorf("//---------------------------------------------//");            return;   }   if (_State == StopState)   {      _Count = 0;      mFile = new FileStream();      if( ((FileStream*)mFile)->open(file, Torque::FS::File::Write) )      {         mFile->write(_Count);         _State = RecordState;      }      else      {         AssertWarn(false,"Journal: Could not create journal file");         Con::errorf("Journal: Could not create journal file '%s'", file);      }   }}
开发者ID:campadrenalin,项目名称:terminal-overload,代码行数:29,


示例8: read

   /// Reads "size" bytes from the file, and dumps data into "dst".   /// The number of actual bytes read is returned in bytesRead   /// @returns The status of the file   File::Status read(U32 size, char *dst, U32 *bytesRead)   {#ifdef DEBUG      //   fprintf(stdout,"reading %d bytes/n",size);fflush(stdout);#endif      AssertFatal(Closed != currentStatus, "File::read: file closed");      AssertFatal(NULL != handle, "File::read: invalid file handle");      AssertFatal(NULL != dst, "File::read: NULL destination pointer");      AssertFatal(true == hasCapability(FileRead), "File::read: file lacks capability");      AssertWarn(0 != size, "File::read: size of zero");            /* show stats for this file */#ifdef DEBUG      //struct stat st;      //fstat(*((int *)handle), &st);      //fprintf(stdout,"file size = %d/n", st.st_size);#endif      /****************************/      long lastBytes=0;      File::Status lastStatus = File::Ok;      if (Ok != currentStatus || 0 == size) {         lastStatus = currentStatus;	  } else      {         long *bytes = &lastBytes;         if ( (*((U32 *)bytes) = x86UNIXRead(*((int *)handle), dst, size)) == -1)         {#ifdef DEBUG            //   fprintf(stdout,"unsuccessful: %d/n", *((U32 *)bytes));fflush(stdout);#endif            setStatus();                                    // unsuccessful            lastStatus = currentStatus;         } else {            //            dst[*((U32 *)bytes)] = '/0';            if (*((U32 *)bytes) != size || *((U32 *)bytes) == 0) {#ifdef DEBUG               //  fprintf(stdout,"end of stream: %d/n", *((U32 *)bytes));fflush(stdout);#endif               currentStatus = EOS;                        // end of stream               lastStatus = currentStatus;            }         }      }      //    dst[*bytesRead] = '/0';#ifdef DEBUG      //fprintf(stdout, "We read:/n");      //fprintf(stdout, "====================================================/n");      //fprintf(stdout, "%s/n",dst);      //fprintf(stdout, "====================================================/n");      //fprintf(stdout,"read ok: %d/n", *bytesRead);fflush(stdout);#endif	  // if bytesRead is a valid pointer, put number of bytes read there.	  if(bytesRead)         *bytesRead = lastBytes;      currentStatus = lastStatus;      return currentStatus;                                    // successfully read size bytes   }
开发者ID:jamesu,项目名称:libDTShape,代码行数:63,


示例9: AssertWarn

//-----------------------------------------------------------------------------bool FileStream::flush(){   AssertWarn(0 != mStreamCaps, "FileStream::flush: the stream isn't open");   AssertFatal(false == mDirty || BUFFER_INVALID != mBuffHead, "FileStream::flush: buffer must be valid if its dirty");   // if the buffer is dirty   if (mDirty)   {      AssertFatal(hasCapability(StreamWrite), "FileStream::flush: a buffer without write-capability should never be dirty");            // align the file pointer to the buffer head      if (mBuffHead != mFile->getPosition())      {         mFile->setPosition(mBuffHead, Torque::FS::File::Begin);         if (mFile->getStatus() != Torque::FS::FileNode::Open && mFile->getStatus() != Torque::FS::FileNode::EndOfFile)            return(false);      }      // write contents of the buffer to disk      U32 blockHead;      calcBlockHead(mBuffHead, &blockHead);      mFile->write((char *)mBuffer + (mBuffHead - blockHead), mBuffTail - mBuffHead + 1);      // and update the file stream's state      setStatus();      if (EOS == getStatus())         mEOF = true;      if (Ok == getStatus() || EOS == getStatus())         // and update the status of the buffer         mDirty = false;      else         return(false);   }   return(true);}
开发者ID:Dwarf-King,项目名称:OmniEngine.Net,代码行数:36,


示例10: AssertFatal

//-----------------------------------------------------------------------------// Write to a file.// The number of bytes to write is passed in size, the data is passed in src.// The number of bytes written is available in bytesWritten if a non-Null// pointer is provided.//-----------------------------------------------------------------------------File::Status File::write(U32 size, const char *src, U32 *bytesWritten){	if (handle != NULL)	{	   AssertFatal(Closed != currentStatus, "File::write: file closed");	   AssertFatal(handle != NULL, "File::write: invalid file handle");	   AssertFatal(NULL != src, "File::write: NULL source pointer");	   AssertFatal(true == hasCapability(FileWrite), "File::write: file lacks capability");	   AssertWarn(0 != size, "File::write: size of zero");	   if ((Ok != currentStatus && EOS != currentStatus) || 0 == size)		  return currentStatus;	   // write bytes to the stream	   U32 nBytes = fwrite(src, 1, size,(FILE*)handle);	   // if we couldn't write everything, we've got a problem. set error status.	   if(nBytes != size)		  setStatus();	   // if bytesWritten is a valid pointer, put number of bytes read there.	   if(bytesWritten)		  *bytesWritten = nBytes;	   // return current File status, whether good or ill.	   return currentStatus;	}   AssertFatal(0, "File::write: Not supported on Android.");   return setStatus();}
开发者ID:120pulsations,项目名称:Torque2D,代码行数:38,


示例11: SAFE_DELETE

void Journal::Play(const char * file){     if (_State == DisabledState)   {      Con::errorf("//---------------------------------------------//");                  Con::errorf("Journal::Play() - Cannot playback a journal after GuiCanvas or NetConnection creation!");                  Con::errorf("To playback before canvas/netConnection creation, run %s with the following arguments: -jPlay %s",         Platform::getExecutableName(), file);      Con::errorf("//---------------------------------------------//");            return;   }   if (_State == StopState)   {      SAFE_DELETE(mFile);      mFile = new FileStream();      if( ((FileStream*)mFile)->open(file, Torque::FS::File::Read) )      {         mFile->read(&_Count);         _State = PlayState;      }      else      {         AssertWarn(false,"Journal: Could not open journal file");         Con::errorf("Journal: Could not open journal file '%s'", file);      }   }}
开发者ID:campadrenalin,项目名称:terminal-overload,代码行数:28,


示例12: setMaskBits

//------------------------------------------------------------------------------void Sky::load(){   if (manager->isServer()) {      // don't load sky resources in server      setMaskBits(Modified);      return;   }         unload();   if ( dmlName[0] ) {      ResourceManager &rm = *SimResource::get(manager);      // const char *filename = SimTagDictionary::getString(manager, matListTag);         // load the material list from file      hMaterialList = rm.load(dmlName);      // don't want to bring down the mission editor, so if an invalid      // dml is given, set the color to ugly      AssertWarn((bool)hMaterialList, avar("Error reading materialList file /"%s/"", dmlName));      if ((bool)hMaterialList && hMaterialList->getMaterialsCount() > 0)       {         loaded = true;         hMaterialList->load(rm, true);         if (initialize() == false)            addToSet(SimTimerSetId);      }      else                 // set ugly color if dml wasn't found         set(ColorF(1.0f, 0.0f, 0.0f));   }   setMaskBits(Modified);}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:32,


示例13: AssertWarn

//------------------------------------------------------------------------------// NAME //    void //    Surface::drawSurface(GFXSurface*    /*lpSourceSurface*/,//                         const RectI*   /*in_subRegion*/,//                         const Point2I* /*in_at*/)//    // DESCRIPTION //    Not implemented for hardware cards...//    //------------------------------------------------------------------------------void Surface::drawSurface(GFXSurface*    /*lpSourceSurface*/,                     const RectI*   /*in_subRegion*/,                     const Point2I* /*in_at*/){   AssertWarn(0, "DrawSurface not implemented in hardware");}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:18,


示例14: AssertWarn

void SimGroup::popObject(){   MutexHandle handle;   handle.lock( mMutex );   if( objectList.empty() )   {      AssertWarn( false, "SimGroup::popObject - Stack underflow" );      return;   }   SimObject* object = objectList.last();   objectList.pop_back();   object->onGroupRemove();   object->mGroup = NULL;   clearNotify( object );   mNameDictionary.remove( object );         getSetModificationSignal().trigger( SetObjectAdded, this, object );   if( object->isProperlyAdded() )      onObjectRemoved_callback( object );      object->decRefCount();}
开发者ID:BadBehavior,项目名称:BadBehavior_T3D,代码行数:26,


示例15: while

void StdMoveList::clientReadMovePacket(BitStream * bstream){#ifdef TORQUE_DEBUG_NET_MOVES   Con::printf("pre move ack: %i", mLastMoveAck);#endif   mLastMoveAck = bstream->readInt(32);#ifdef TORQUE_DEBUG_NET_MOVES   Con::printf("post move ack %i, first move %i, last move %i", mLastMoveAck, mFirstMoveIndex, mLastClientMove);#endif   if (mLastMoveAck < mFirstMoveIndex)      mLastMoveAck = mFirstMoveIndex;   if(mLastMoveAck > mLastClientMove)      mLastClientMove = mLastMoveAck;   while(mFirstMoveIndex < mLastMoveAck)   {      if (mMoveVec.size())      {         mMoveVec.pop_front();         mFirstMoveIndex++;      }      else      {         AssertWarn(1, "Popping off too many moves!");         mFirstMoveIndex = mLastMoveAck;      }   }}
开发者ID:campadrenalin,项目名称:terminal-overload,代码行数:31,


示例16: dVsprintf

S32 dVsprintf(char *buffer, dsize_t bufferSize, const char *format, void * arglist){   S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);      AssertWarn( len < bufferSize, "Buffer too small in call to dVsprintf!" );   return (len);}
开发者ID:souxiaosou,项目名称:OmniEngine.Net,代码行数:8,


示例17: TranslateOSKeyCode

U8 TranslateOSKeyCode(U8 macKeycode){    AssertWarn(macKeycode < sizeof(sOSToKeyCode) / sizeof(sOSToKeyCode[0]), avar("TranslateOSKeyCode - could not translate code %i", macKeycode));    if(macKeycode >= sizeof(sOSToKeyCode) / sizeof(sOSToKeyCode[0]))        return KEY_NULL;    return sOSToKeyCode[ macKeycode ].mKeyCode;}
开发者ID:Bloodknight,项目名称:T3D-MIT-GMK-Port,代码行数:8,


示例18: dVsprintf

S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, va_list arglist){   S32 len = vsnprintf(buffer, bufferSize, format, arglist);      AssertWarn( len < bufferSize, "Buffer too small in call to dVsprintf!" );   return (len);}
开发者ID:03050903,项目名称:Torque3D,代码行数:8,


示例19: AssertFatal

bool Surface::describeDevice(int deviceNumber, GFXDeviceDescriptor *dev){   AssertFatal(initialized == true, "Error describeDevice called before Direct3D::Surface::init()");   // Some trickiness here.  deviceNumber actually refers to the n_th, _valid_   //  device, rather than the device with deviceMinorId = deviceNumber...   //   int numValidDevices = 0;   int deviceMinorId = -1;   for (int i = 0; i < pD3D2Vector.size(); i++) {      if ((pD3D2Vector[i] != NULL) && (D3DDevDescVector[i].valid == true))         numValidDevices++;               if ((numValidDevices - 1) == deviceNumber) {         deviceMinorId = i;         break;      }   }   AssertWarn(deviceMinorId != -1, avar("Error, unable to find specified device: %d size: %d",                                        deviceNumber, pD3D2Vector.size()));   if (deviceMinorId == -1)      return false;         // Ok, we have the correct minorId, fill in the dev structure...   //   dev->flags         = GFXDeviceDescriptor::runsFullscreen;  // D3D Devices always run fullscreen for now   dev->deviceId      = GFX_D3D_DEVICE;   dev->deviceMinorId = deviceMinorId;   dev->driverLibrary = NULL;   dev->name          = D3DDevDescVector[deviceMinorId].devName;      // Place the resolutions into the devices resolution list...   getDeviceResolutions(deviceMinorId, DevResVector[deviceMinorId]);   // If resVector's size is 0, then no valid modes were found   if (DevResVector[deviceMinorId]->size() == 0) {      return false;   }      // Place the resolutions into the device descriptor list.  Note: we don't sort   //  them, this is handled by the GFXD3DDevice...   //   int k = 0;   DWORD totalVidMem = getTotalSurfaceMemory(deviceNumber);   dev->resolutionList = new Point2I[DevResVector[deviceMinorId]->size()];   for (int j = 0; j < DevResVector[deviceMinorId]->size(); j++) {      if (vidMemRequired((*DevResVector[deviceMinorId])[j].res) <= totalVidMem) {         dev->resolutionList[k] = (*DevResVector[deviceMinorId])[j].res;         k++;      }   }   dev->resolutionCount = k;      // Ok, the device is fully described, and if we're here, it's also valid   //   return true;}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:58,


示例20: glBegin

void Surface::flip(){   if (m_flareBlend != 0.0f) {      m_pTextureCache->enableTexUnits(false);      m_pTextureCache->setBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      m_pTextureCache->enableZBuffering(true, false, GL_ALWAYS);      m_pTextureCache->setTransparent(false);      glBegin(GL_POLYGON);         glColor4f(m_flareColor.red, m_flareColor.green, m_flareColor.blue, m_flareBlend);         glVertex2f(0, 0);         glVertex2f(surfaceWidth, 0);         glVertex2f(surfaceWidth, surfaceHeight);         glVertex2f(0, surfaceHeight);      glEnd();   }   m_flareBlend = 0.0f;   if (m_alphaBlend != 0.0f) {      m_pTextureCache->enableTexUnits(false);      m_pTextureCache->setBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      m_pTextureCache->enableZBuffering(true, false, GL_ALWAYS);      m_pTextureCache->setTransparent(false);      glBegin(GL_POLYGON);         glColor4f(m_alphaColor.red, m_alphaColor.green, m_alphaColor.blue, m_alphaBlend);         glVertex2f(0, 0);         glVertex2f(surfaceWidth, 0);         glVertex2f(surfaceWidth, surfaceHeight);         glVertex2f(0, surfaceHeight);      glEnd();   }   m_alphaBlend = 0.0f;   // Swap buffers   glFinish();   BOOL sbSuccess = SwapBuffers(m_hDC);   if (sbSuccess == FALSE) {      char buffer[1024];      buffer[0] = '/0';      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,                    NULL,                    GetLastError(),                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language                    buffer, 1023, NULL);      AssertWarn(0, buffer);   }   if (m_pTextureCache != NULL) {      m_pTextureCache->incFrameKey();      m_pTextureCache->clearState();   }}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:56,


示例21: AssertWarn

Bool GFXFont::write( const char *in_name ){   FileWStream fws;   if (fws.open(in_name) == false) {      AssertWarn(0, avar("GFXFont::write: Unable to write font %s, CreateFile for writing failed.", in_name));      return false;   }   Bool result = write(&fws);   fws.close();   if ( result )      return TRUE;   else   {      AssertWarn(0, avar("GFXFont::write: Unable to write font %s, StreamIO for writing failed.", in_name));      return FALSE;   }}
开发者ID:AltimorTASDK,项目名称:TribesRebirth,代码行数:19,


示例22: dSprintf

S32 dSprintf(char *buffer, dsize_t bufferSize, const char *format, ...){   va_list args;   va_start(args, format);   S32 len = vsnprintf(buffer, bufferSize, format, args);   AssertWarn( len < bufferSize, "Buffer too small in call to dSprintf!" );   return (len);}
开发者ID:souxiaosou,项目名称:OmniEngine.Net,代码行数:11,


示例23: AssertFatal

ConsoleObject* AbstractClassRep::create(const char* in_pClassName){   AssertFatal(initialized,      "AbstractClassRep::create() - Tried to create an object before AbstractClassRep::initialize().");   const AbstractClassRep *rep = AbstractClassRep::findClassRep(in_pClassName);   if(rep)      return rep->create();   AssertWarn(0, avar("Couldn't find class rep for dynamic class: %s", in_pClassName));   return NULL;}
开发者ID:1414648814,项目名称:Torque3D,代码行数:12,



注:本文中的AssertWarn函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


C++ Assert_函数代码示例
C++ AssertValidStringPtr函数代码示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。