ورود

View Full Version : سوال: تابعی برای مقایسه رشته ها



feri88
چهارشنبه 24 خرداد 1391, 13:05 عصر
سلام

این تیکه کد، یه بخش از برنامه من هست که یه لیست از dll های ویندوز رو می خونه و نمایش میده:

while(CryptEnumProviders(dwIndex, NULL, 0, &dwType, NULL, &cbName))
{
if (!(pszName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, cbName)))
{
printf("ERROR - LocalAlloc failed!");
}

//-----------------------------------------------------------
// Get the provider name.
if (CryptEnumProviders(dwIndex++, NULL, 0, &dwType, pszName, &cbName))
{
if( strcmp((const char *)pszName, "Microsoft") < 0 )
{
printf (" %4.0d %s\n", dwType, pszName);
}
}
else
{
printf("ERROR - CryptEnumProviders");
}

LocalFree(pszName);
}

همون طور که می بینین، توی یک حلقه اسم اونها رو می خونه و چاپ می کنه.
حالا من می خوام اسم اونهایی که با رشته ''Microsoft" شروع میشه رو حذف کنم و نمایش داده نشن!
یعنی مثلاً اگه لیست این dll ها به صورت زیر باشه:

EnterSafe ePass3003
Microsoft Base Cryptographic Provider v1.0
Microsoft Base DSS and Diffie-Hellman Cryptographic Provider
Microsoft Base DSS Cryptographic Provider
Microsoft Base Smart Card Crypto Provider
Microsoft DH SChannel Cryptographic Provider
Microsoft Enhanced Cryptographic Provider v1.0
Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider
Microsoft Enhanced RSA and AES Cryptographic Provider
Microsoft RSA SChannel Cryptographic Provider
Microsoft Strong Cryptographic Provider

فقط رشته اول که با "Microsoft' شروع نمیشه، نمایش داده بشه.
اینه که اومدم از strcmp استفاده کردم که رشته دریافت شده از سیستم رو با "Microsoft" مقایسه کنه و اگه خروجی تابع منفی بود (دو رشته با هم مطابقت نداشتن) اون رو چاپ کنه و بقیه رو که با "Microsoft" شروع میشن چاپ نکنه.

ولی بعد از اجرای برنامه، می بینم که همه رو نمایش میده!

به نظرتون چی کار باید بکنم و اینکه آیا تابع دیگه ای غیر از strcmp وجود داره که این کاری رو که می خوام انجام بده؟

مرسی

Hossenbor
پنج شنبه 25 خرداد 1391, 17:50 عصر
سلام دوست عزیز شما میگید اگر رشته برابر مایکروسافت بود اونو نمایش ندید باید بنویسید که رشته مایکروسافت جزعی از اون نباشه یا همون تابع indexof سی شارپ که یک دوتابع بودند من تست کردم جواب نگرفتم یکی strchr بود فکر کنم یکی هم strstr بنابراین دستی با توابع و کدهایی خودم نوشتم دنبال اون رشته گشتم اگه براتون زحمتی نیست کد رو تو قالبش قرار بدین من با موبایلم جاوا برام غیر فعاله

char *fnd="Microsoft",yourstr="Microsoft Visual Studio 2010";
int lnt=strlen(fnd),cnt=0,slnt=strlen(yourstr);

for(int i=0;i<slnt;i++){
if(yourstr[i]==fnd[cnt]){
if(cnt==lnt)
continue;
cnt++;
}
}

خوب توضیحش میشه اینکه اگر رشته رو پیدا کرد توجه نکنه و کارشو ادامه بده کد رو باید تو بلاک while بزارین یا اگر امکان نداره بجای continue دستور break یا هر دستور خروج از چرخه رو بدین توضیح خواستین در خدمتم

mehdi.mousavi
پنج شنبه 25 خرداد 1391, 17:53 عصر
سلام.
کافیه تا if رو بدین شکل تغییر بدید:

char *pSubStr = "Microsoft";
if(strncmp(pszName, pSubStr, strlen(pSubStr)) == 0)
{
//Starts with Microsoft...
}


موفق باشید.

feri88
شنبه 27 خرداد 1391, 17:52 عصر
سلام دوست عزیز شما میگید اگر رشته برابر مایکروسافت بود اونو نمایش ندید باید بنویسید که رشته مایکروسافت جزعی از اون نباشه یا همون تابع indexof سی شارپ که یک دوتابع بودند من تست کردم جواب نگرفتم یکی strchr بود فکر کنم یکی هم strstr بنابراین دستی با توابع و کدهایی خودم نوشتم دنبال اون رشته گشتم اگه براتون زحمتی نیست کد رو تو قالبش قرار بدین من با موبایلم جاوا برام غیر فعاله

char *fnd="Microsoft",yourstr="Microsoft Visual Studio 2010";
int lnt=strlen(fnd),cnt=0,slnt=strlen(yourstr);

for(int i=0;i<slnt;i++){
if(yourstr[i]==fnd[cnt]){
if(cnt==lnt)
continue;
cnt++;
}
}

خوب توضیحش میشه اینکه اگر رشته رو پیدا کرد توجه نکنه و کارشو ادامه بده کد رو باید تو بلاک while بزارین یا اگر امکان نداره بجای continue دستور break یا هر دستور خروج از چرخه رو بدین توضیح خواستین در خدمتم
سلام

خیلی ممنونم از جوابتون.

من موارد زیر رو امتحان کردم:
1)
به جای خطوط 12 تا 15 کدی که در پست قبلی گذاشتم، موارد زیر رو جایگزین کردم که نتیجه هر کدوم رو گذاشتم.

char *pdest;
char *pSubStr = "Microsoft";

if( !(pdest = (char*)strstr((const char *)pszName, pSubStr)) )
{
printf (" %4.0d %s\n", dwType, pszName);
}

نتیجه:
نمایش همه موارد!

EnterSafe ePass3003
Microsoft Base Cryptographic Provider v1.0
Microsoft Base DSS and Diffie-Hellman Cryptographic Provider
Microsoft Base DSS Cryptographic Provider
Microsoft Base Smart Card Crypto Provider
Microsoft DH SChannel Cryptographic Provider
Microsoft Enhanced Cryptographic Provider v1.0
Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider
Microsoft Enhanced RSA and AES Cryptographic Provider
Microsoft RSA SChannel Cryptographic Provider
Microsoft Strong Cryptographic Provider

انتظار میره که فقط رشته اول نمایش داده بشه، چون تابع strstr هم تابع درستی هست و برای پیدا کردن یک زیررشته در رشته دیگر بکار می ره!
نمی دونم علت این خروجی غیرقابل انتظار چیه؟!

2)


char *pSubStr = "Microsoft";
int lnt = strlen(pSubStr), cnt = 0;

cnt = 0;
for(int i = 0; i < cbName; i++)
{
if( pszName[i] == pSubStr[cnt] )
{
if( cnt == lnt )
continue;
cnt++;
}
}

if( cnt == 0 )
{
printf (" %4.0d %s\n", dwType, pszName);
}

خروجی:

EnterSafe ePass3003

خروجی صحیح هست و همین انتظار رو داشتم.

اما می خوام ببینم که چرا استفاده از تابع آماده strstr درست جواب نداد؟!

می تونین راهنماییم کنید؟

مرسی

feri88
شنبه 27 خرداد 1391, 18:04 عصر
سلام.
کافیه تا if رو بدین شکل تغییر بدید:

char *pSubStr = "Microsoft";
if(strncmp(pszName, pSubStr, strlen(pSubStr)) == 0)
{
//Starts with Microsoft...
}


موفق باشید.
سلام
ممنونم دوست عزیز

من کد شما رو امتحان کردم طوریکه که به جای خطوط 12 تا 15، کدهای زیر رو جایگزین کردم که خروجی های هر کدوم رو می گذارم:
1)


if(strncmp((char*)pszName, pSubStr, strlen(pSubStr)) == 0)
{
printf (" %4.0d %s\n", dwType, pszName);
}
خروجی: هیچ چیزی نمایش داده نشد.

بعد به جای علامت مساوی در if، علامت =! رو گذاشتم که بعد از اجرا، همه موارد رو نمایش داد.

به جای strncmp، تابع strnicmp_ رو هم امتحان کردم که نتیجه مثل قبل شد، یعنی در حالت استفاده از علامت == هیچ چیزی نمایش داده نشد و در حالت =! همه موارد رو نمایش داد.

ممنون میشم علت رو بفرمایید.

mehdi.mousavi
شنبه 27 خرداد 1391, 19:15 عصر
سلام ممنونم دوست عزیز من کد شما رو امتحان کردم طوریکه که به جای خطوط 12 تا 15، کدهای زیر رو جایگزین کردم که خروجی های هر کدوم رو می گذارم:
1)


if(strncmp((char*)pszName, pSubStr, strlen(pSubStr)) == 0)
{
printf (" %4.0d %s\n", dwType, pszName);
}
خروجی: هیچ چیزی نمایش داده نشد. بعد به جای علامت مساوی در if، علامت =! رو گذاشتم که بعد از اجرا، همه موارد رو نمایش داد. به جای strncmp، تابع strnicmp_ رو هم امتحان کردم که نتیجه مثل قبل شد، یعنی در حالت استفاده از علامت == هیچ چیزی نمایش داده نشد و در حالت =! همه موارد رو نمایش داد. ممنون میشم علت رو بفرمایید.

سلام.
برنامه رو Unicode کامپایل می کنید یا Multi-Byte؟ من کد رو بدین شکل تغییر دادم و بدون هیچ مشکلی در هر دو Character Set کار کرد:

DWORD dwIndex = 0, dwType, cbName;
LPTSTR pszName;
TCHAR *pSubStr = _T("Microsoft");

while(CryptEnumProviders(dwIndex, NULL, 0, &dwType, NULL, &cbName))
{
if (!(pszName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, cbName)))
{
printf("ERROR - LocalAlloc failed!");
return -1;
}

if (CryptEnumProviders(dwIndex++, NULL, 0, &dwType, pszName, &cbName))
{
if(_tcsnccmp(pszName, pSubStr, _tcslen(pSubStr)) == 0)
{
_tprintf(_T(" %4.0d %s\n"), dwType, pszName);
}
}
else
{
printf("ERROR - CryptEnumProviders");
}

LocalFree(pszName);
}

return 0;

موفق باشید.

ahmad.b.74
شنبه 27 اردیبهشت 1393, 19:08 عصر
نمیشه یه کم کوتا توضیح بدید که چه کار کنیم و یه مقدار هم ساده تر اگه میشه لطفا.؟