كيف يمكنني الوصول إلى الفرد حرف من مجموعة من السلاسل في c ؟

StackOverflow https://stackoverflow.com/questions/606879

  •  03-07-2019
  •  | 
  •  

سؤال

فقط أحاول أن أفهم كيفية معالجة حرف واحد في مجموعة من السلاسل.أيضا, وهذا بالطبع سوف اسمحوا لي أن أفهم المؤشرات إلى مؤشرات subscripting بشكل عام.إذا كان لدي char **a وأريد أن تصل إلى 3 حرف من 2 سلسلة ، هل هذا العمل: **((a+1)+2)?يبدو أنه ينبغي أن...

هل كانت مفيدة؟

المحلول

وتقريبا، ولكن ليس تماما. والجواب الصحيح هو:

*((*(a+1))+2)

ولأنك بحاجة إلى إزالة الإشارة أولا إلى واحد من مؤشرات سلسلة الفعلي ثم لنزع المرجعية التي اختارت سلسلة المؤشر أسفل إلى الحرف المطلوب. (لاحظ أن أضفت قوسين اضافية لالوضوح في ترتيب العمليات هناك).

وبدلا من ذلك، هذا التعبير:

a[1][2]

وستعمل أيضا! .... وربما سيكون من المفضل لأن القصد من ما تحاول القيام به هو أكثر بديهية وتدوين نفسه أكثر إيجازا. هذا النموذج قد لا يكون واضحا على الفور لأشخاص جدد إلى اللغة، ولكن فهم أن السبب يعمل تدوين مجموعة لأن في C، وهي عملية الفهرسة مجموعة هو في الحقيقة مجرد اختصار لتشغيل المؤشر ما يعادلها. أي: * (أ + س) هو نفسه بأنه [س]. لذلك، من خلال توسيع هذا المنطق على السؤال الأصلي، وهناك نوعان مؤشر منفصل عمليات الرجوع دي تتالي معا حيث التعبير و[س] [ص] ما يعادل الشكل العام لل* ((* (أ + س)) + ذ).

نصائح أخرى

وليس لديك لاستخدام المؤشرات.

<اقتباس فقرة>   

والباحث الرئيسي (الباحث ARGC، شار ** ARGV) {

     

وprintf ( "الحرف الثالث من   ARGV [1] هو [٪ ج] \ ن "، ARGV [1] [2])؛.

     

و}

وبعد ذلك:

<اقتباس فقرة>   

و$ ./main مرحبا الحرف الثالث من   ARGV [1] هو [ل].

وهذا هو واحد ولتر.

هل يمكن استخدام المؤشرات إذا كنت تريد ...

<اقتباس فقرة>   

و* (ARGV [1] +2)

وأو حتى

<اقتباس فقرة>   

و* ((* (أ + 1)) + 2)

وكما أشار أحد أعلاه.

وذلك لأن أسماء مجموعة هي المؤشرات.

وIIRC، سلسلة هي في الواقع مجموعة من حرف، لذلك هذا يجب أن تعمل:

a[1][2]

هناك عبقري البرمجة C التفسير في كتاب القرصنة فن استغلال 2nd Edition جون إريكسون الذي يناقش مؤشرات, سلاسل, يستحق الذكر عن البرمجة شرح القسم وحده https://leaksource.files.wordpress.com/2014/08/hacking-the-art-of-exploitation.pdf.

على الرغم من أن هذا السؤال سبق أن أجاب شخص آخر يريد أن يعرف أكثر قد تجد ما يلي مقتطفات من Ericksons الكتاب المفيد أن نفهم بعض من هيكل وراء السؤال.

رؤوس

أمثلة على رأس الملفات المتاحة متغير التلاعب ربما كنت سوف تستخدم.

stdio.ح - http://www.cplusplus.com/reference/cstdio/

stdlib.ح - http://www.cplusplus.com/reference/cstdlib/

السلسلة.ح - http://www.cplusplus.com/reference/cstring/

حدود.ح - http://www.cplusplus.com/reference/climits/

وظائف

أمثلة الغرض العام من الوظائف التي سوف تستخدم على الأرجح.

malloc() - http://www.cplusplus.com/reference/cstdlib/malloc/

calloc() - http://www.cplusplus.com/reference/cstdlib/calloc/

strcpy() - http://www.cplusplus.com/reference/cstring/strcpy/

الذاكرة

"ترجمة البرنامج الذاكرة مقسمة إلى خمسة أجزاء:النص والبيانات bss, كومة, و كومة.كل جزء يمثل الخاصة جزء من الذاكرة جانبا من أجل غرض معين.نص الجزء ويسمى أيضا في بعض الأحيان مقطع التعليمات البرمجية.هذا هو حيث جمعت لغة الآلة تعليمات برنامج تقع".

"تنفيذ تعليمات في هذا الجزء هو غير الخطية ، وذلك بفضل المذكورة عالية-التحكم في مستوى الهياكل والوظائف التي تجمع في فرع القفز و استدعاء التعليمات في لغة التجميع.كبرنامج ينفذ ، EIP هو أول التدريس في النص الجزء.على المعالج ثم عقب تنفيذ حلقة أن يفعل ما يلي:"

"1.يقرأ التعليمات التي EIP يشير إلى"

"2.ويضيف بايت طول تعليمات إلى السكان غير النشطين اقتصاديا"

"3.ينفذ التعليمات التي كان يقرأ في الخطوة 1"

"4.يعود إلى الخطوة 1"

"في بعض الأحيان سوف تكون هذه التعليمات قفزة أو استدعاء التعليمات ، التغييرات السكان غير النشطين اقتصاديا إلى عنوان مختلف من الذاكرة.المعالج لا يهتمون التغيير, لأنه يتوقع التنفيذ أن يكون غير الخطية على أي حال.إذا EIP تغيير في الخطوة 3 من المعالج فقط والعودة إلى الخطوة 1 و قراءة التعليمات الموجودة في عنوان ما EIP تم تغيير".

"إذن الكتابة المعوقين في النص الجزء ، كما أنه لا يستخدم لتخزين المتغيرات رمز فقط.هذا يمنع الناس من الواقع تعديل البرنامج المدونة ؛ أي محاولة الكتابة إلى هذا الجزء من الذاكرة يؤدي البرنامج إلى تنبيه المستخدم أن شيئا سيئا حدث البرنامج سيتم قتل.ميزة أخرى من هذا الجزء يتم قراءة فقط هو أنه يمكن أن تكون مشتركة بين مختلف نسخ من البرنامج, يسمح متعددة الإعدام من برنامج في نفس الوقت بدون أي مشاكل.يجب أن أن يلاحظ أيضا أن هذه الذاكرة شريحة حجم ثابت, بما أن لا شيء من أي وقت مضى التغييرات في هذا".

"البيانات bss القطاعات تستخدم لتخزين العالمية ثابتة البرنامج المتغيرات.مقطع البيانات يتم تعبئة مع تهيئة العالمية و متغيرات ثابتة ، بينما bss الجزء مليء بها غير مهيأ نظرائهم.على الرغم من أن هذه القطاعات هي للكتابة, لديهم أيضا حجم ثابت.تذكر أن المتغيرات العالمية لا تزال قائمة رغم وظيفية السياق (مثل المتغير ي في الأمثلة السابقة).سواء على الصعيد العالمي أو متغيرات ثابتة قادرة على أن تستمر لأنها مخزنة في الذاكرة الخاصة بهم شرائح".

"كومة هو الجزء من الذاكرة يمكن للمبرمج مباشرة التحكم.كتل من الذاكرة في هذا الجزء يمكن تخصيصها واستخدامها مهما كان مبرمج قد تحتاج إليها.أحد أبرز نقطة عن كومة الجزء هو أنه ليس من حجم ثابت ، لذلك يمكن أن تنمو أكبر أو أصغر حسب الحاجة".

"جميع الذاكرة في كومة الذاكرة المؤقتة التي تديرها مخصص و deallocator الخوارزميات التي على التوالي الاحتياطي منطقة الذاكرة في كومة الذاكرة المؤقتة لاستخدامها وإزالة التحفظات للسماح ذلك الجزء من الذاكرة التي يمكن استخدامها في وقت لاحق التحفظات.كومة سوف تنمو وتتقلص اعتمادا على كيفية الكثير من الذاكرة محجوز للاستخدام.وهذا يعني مبرمج استخدام كومة الذاكرة المؤقتة تخصيص وظائف يمكن أن الاحتياطي الذاكرة الحرة على الطاير.نمو كومة يتحرك نحو الانخفاض نحو أعلى عناوين الذاكرة".

"قطعة مكدس أيضا متغير الحجم و يستخدم مؤقت الصفر الوسادة لتخزين المحلية وظيفة المتغيرات السياق من خلال وظيفة المكالمات.هذا ما GDB هو تعقب الأمر يبدو في.عند استدعاء برنامج وظيفة ، أن وظيفة لديها مجموعتها الخاصة من تمرير المتغيرات ، وظيفة هذا الكود سوف يكون في موقع ذاكرة مختلفة في النص (أو رمز) الجزء.منذ السياق السكان غير النشطين اقتصاديا يجب أن تتغير عندما يتم استدعاء وظيفة ، يتم استخدام المكدس أن نتذكر كل من مر المتغيرات الموقع السكان غير النشطين اقتصاديا يجب أن تعود إلى بعد الانتهاء من وظيفة ، وجميع المتغيرات المحلية المستخدمة من قبل تلك الوظيفة.كل هذه المعلومات يتم تخزينها معا على المكدس في ما تسمى مجتمعة إطار مكدس.المكدس يحتوي على العديد من إطارات المكدس".

"في علوم الكمبيوتر حيث كومة مجردة بنية البيانات التي يتم استخدامها بشكل متكرر.وقد الأولى-في الماضي-من أصل (فيلو) يأمر مما يعني أول بند من البنود التي وضعت في كومة هو العنصر الأخير للخروج من ذلك.كما أنها تفكر في وضع الخرز على قطعة من السلسلة يحتوي على عقدة واحدة على نهاية—لا يمكنك الحصول على أول حبة حتى الانتهاء من إزالة جميع الخرز.عندما يتم وضع البند في كومة ، كما هو معروف دفع, وعندما تتم إزالة عنصر من المكدس ، ويسمى ظهرت".

"كما يوحي الاسم, قطعة مكدس الذاكرة في الحقيقة كومة بنية البيانات التي تحتوي على إطارات المكدس.ESP سجل يستخدم لتتبع عنوان نهاية المكدس ، والتي تتغير باستمرار حيث العناصر هي التي دفعت إلى و برزت من ذلك.لأن هذا هو السلوك الديناميكي ، فمن المنطقي أن المكدس هو أيضا ليس من حجم ثابت.عكس النمو الديناميكي كومة ، المكدس تغيير s في الحجم ، فإنه ينمو التصاعدي في visual قائمة من الذاكرة ، نحو أقل من عناوين الذاكرة".

"فإن فيلو طبيعة كومة قد يبدو غريبا, ولكن منذ يتم استخدام المكدس لتخزين السياق انها مفيدة جدا.عند استدعاء عدة دفعت الأمور إلى كومة معا في الإطار المكدس.EBP التسجيل—أحيانا يسمى مؤشر الإطار (FP) أو المحلية قاعدة (LB) مؤشر —يستخدم للإشارة المحلية وظيفة المتغيرات الحالية في الإطار المكدس.كل إطار المكدس يحتوي على معلمات الدالة المتغيرات المحلية و اثنين من المؤشرات اللازمة لوضع الأمور تعود كما كانت:المحفوظة الإطار مؤشر (SFP) و عنوان المرسل.على SFP يستخدم لاستعادة EBP إلى قيمتها السابقة ، وعنوان المرسل تستخدم لاستعادة EIP إلى التعليمة التالية وجدت بعد استدعاء دالة.هذا يعيد وظيفية السياق السابق المكدس frame".

سلاسل

"في C ، صفيف هو ببساطة قائمة n عناصر محددة نوع البيانات.20-صفيف حرف هو ببساطة 20 المجاورة الشخصيات الموجودة في الذاكرة.المصفوفات هي كما يشار إلى مخازن".

#include <stdio.h>

int main()
{
    char str_a[20];
    str_a[0] = 'H';
    str_a[1] = 'e';
    str_a[2] = 'l';
    str_a[3] = 'l';
    str_a[4] = 'o';
    str_a[5] = ',';
    str_a[6] = ' ';
    str_a[7] = 'w';
    str_a[8] = 'o';
    str_a[9] = 'r';
    str_a[10] = 'l';
    str_a[11] = 'd';
    str_a[12] = '!';
    str_a[13] = '\n';
    str_a[14] = 0;
    printf(str_a);
}

"في السابق برنامج, 20 عنصر صفيف حرف تعريف str_a و كل عنصر من الصفيف هو مكتوب على واحد.لاحظ أن الرقم يبدأ عند 0 بدلا من 1.أيضا لاحظ أن الحرف الأخير هو 0".

"(وهذا ما يسمى أيضا null byte.) في صفيف حرف تعريف ، حتى 20 وحدات البايت المخصصة لذلك ، ولكن فقط 12 من هذه بايت تستخدم في الواقع.Null byte البرمجة في النهاية هو استخدام محدد الحرف أن أقول أي وظيفة التعامل مع سلسلة لوقف العمليات هناك.المتبقية إضافية بايت فقط القمامة سيتم تجاهلها.إذا بايت فارغة يتم إدراجها في الخامسة عنصر صفيف حرف فقط الشخصيات مرحبا سيكون المطبوعة من قبل الدالة printf() ".

"منذ وضع كل حرف في حرف مجموعة مضنية و سلاسل تستخدم إلى حد ما في كثير من الأحيان مجموعة من الوظائف القياسية تم إنشاء سلسلة التلاعب.على سبيل المثال ، strcpy() وظيفة نسخ سلسلة من المصدر إلى الوجهة ، بالتكرار عبر سلسلة المصدر و نسخ كل بايت إلى الوجهة (ووقف بعد ذلك نسخ إنهاء null byte)".

"ترتيب وظائف حجج مماثلة إنتل الجمعية جملة الوجهة الأولى ثم المصدر.على char_array.برنامج c يمكن إعادة كتابة باستخدام strcpy() لإنجاز نفس الشيء باستخدام سلسلة المكتبة.النسخة القادمة من char_array البرنامج هو مبين أدناه يتضمن سلسلة.ساعة لأنه يستخدم سلسلة وظيفة".

#include <stdio.h>
#include <string.h>

int main() 
{
    char str_a[20];
    strcpy(str_a, "Hello, world!\n");
    printf(str_a);
}

العثور على مزيد من المعلومات على C سلاسل

http://www.cs.uic.edu/~jbell/CourseNotes/C_Programming/CharacterStrings.html

http://www.tutorialspoint.com/cprogramming/c_strings.htm

مؤشرات

"السكان غير النشطين اقتصاديا سجل هو مؤشر على أن "النقاط" الحالية التعليم خلال برامج التنفيذ يتضمن عنوان الذاكرة.فكرة المؤشرات المستخدمة في ج أيضا.لأن الذاكرة الفعلية لا يمكن في الواقع أن يتم نقل المعلومات في أنه يجب أن يتم نسخها.فإنه يمكن أن تكون مكلفة حسابيا إلى نسخ أجزاء كبيرة من الذاكرة التي يمكن استخدامها من خلال وظائف مختلفة في أماكن مختلفة.هذا هو أيضا مكلفة من الذاكرة نظر لأن مساحة الوجهة الجديدة يجب حفظ نسخ أو تخصيص من قبل المصدر يمكن نسخها.مؤشرات حل هذه المشكلة.بدلا من نسخ كتلة كبيرة من الذاكرة ، هو أبسط من ذلك بكثير لتمرير حول عنوان بداية تلك الكتلة من الذاكرة".

"المؤشرات في ج يمكن تعريف و استخدامها مثل أي نوع المتغير.لأن الذاكرة على الهندسة المعمارية x86 يستخدم 32 بت معالجة المؤشرات أيضا 32 بت الحجم (4 بايت).مؤشرات محددة يتبع علامة النجمة (*) إلى اسم المتغير.بدلا من تعريف متغير من هذا النوع ، مؤشر يعرف شيء يشير إلى أن البيانات من هذا النوع.المؤشر.برنامج c مثال على مؤشر المستخدمة مع نوع البيانات char, الذي هو فقط 1byte في الحجم".

#include <stdio.h>
#include <string.h>

int main() 
{
    char str_a[20]; // A 20-element character array
    char *pointer; // A pointer, meant for a character array
    char *pointer2; // And yet another one
    strcpy(str_a, "Hello, world!\n");
    pointer = str_a; // Set the first pointer to the start of the array.
    printf(pointer);
    pointer2 = pointer + 2; // Set the second one 2 bytes further in.
    printf(pointer2); // Print it.
    strcpy(pointer2, "y you guys!\n"); // Copy into that spot.
    printf(pointer); // Print again.
}

"كما التعليقات في المدونة تشير إلى المؤشر الأول في بداية صفيف حرف.عندما صفيف حرف المشار إليها مثل هذا ، هو في الواقع مؤشر نفسها.هذا المخزن المؤقت تم تمرير مؤشر إلى printf() و strcpy() وظائف في وقت سابق.والمؤشر الثاني هو تعيين أول المؤشرات عنوان زائد اثنين ، ثم بعض الأشياء المطبوعة (كما هو موضح في الإخراج أدناه)".

reader@hacking:~/booksrc $ gcc -o pointer pointer.c
reader@hacking:~/booksrc $ ./pointer
Hello, world!
llo, world!
Hey you guys!
reader@hacking:~/booksrc $

"عنوان المشغل غالبا ما تستخدم بالاقتران مع مؤشرات ، منذ مؤشرات تحتوي على عناوين الذاكرة.على addressof.برنامج c يوضح عنوان المشغل يستخدم لوضع عنوان متغير عدد صحيح في مؤشر.هذا الخط هو مبين في أدناه جريئة".

#include <stdio.h>

int main() 
{
    int int_var = 5;
    int *int_ptr;
    int_ptr = &int_var; // put the address of int_var into int_ptr
}

"إضافية الأحادية مشغل يسمى dereference المشغل موجود للاستخدام مع المؤشرات.هذا المشغل إرجاع البيانات الموجودة في العنوان المؤشر يشير إلى بدلا من العنوان نفسه.فإنه يأخذ شكل النجمة أمام اسم متغير ، على غرار إعلان مؤشر.مرة أخرى إلغاء مرجعية المشغل موجود سواء في GDB و في ج".

"بعض الاضافات addressof.ج كود (كما هو موضح في addressof2.ج) سوف تثبت جميع هذه المفاهيم.وأضاف printf() وظائف استخدام تنسيق المعلمات التي سأشرح في القسم التالي.الآن فقط التركيز على برامج الانتاج".

#include <stdio.h>

int main() 
{
    int int_var = 5;
    int *int_ptr;
    int_ptr = &int_var; // Put the address of int_var into int_ptr.
    printf("int_ptr = 0x%08x\n", int_ptr);
    printf("&int_ptr = 0x%08x\n", &int_ptr);
    printf("*int_ptr = 0x%08x\n\n", *int_ptr);
    printf("int_var is located at 0x%08x and contains %d\n", &int_var, int_var);
    printf("int_ptr is located at 0x%08x, contains 0x%08x, and points to %d\n\n", &int_ptr, int_ptr, *int_ptr);
}

"عند استخدام عوامل التشغيل الأحادية تستخدم مع مؤشرات العنوان-المشغل يمكن أن تكون من حيث الفكر تتحرك إلى الوراء ، في حين أن إلغاء مرجعية مشغل يتحرك إلى الأمام في اتجاه المؤشر يشير".

معرفة المزيد عن المؤشرات & تخصيص الذاكرة

البروفيسور دان Hirschberg قسم علوم الحاسب في جامعة كاليفورنيا في ذاكرة الكمبيوتر https://www.ics.uci.edu/~dan/class/165/notes/memory.html

http://cslibrary.stanford.edu/106/

http://www.programiz.com/c-programming/c-dynamic-memory-allocation

المصفوفات

هناك البرنامج التعليمي بسيطة على المصفوفات متعددة الأبعاد من قبل شاب يدعى أليكس ألين المتاحة هنا http://www.cprogramming.com/tutorial/c/lesson8.html

هناك معلومات عن المصفوفات من قبل شاب يدعى تود جيبسون المتاحة هنا http://www.augustcouncil.com/~tgibson/tutorial/arr.html

تكرار مجموعة

#include <stdio.h>

int main() 
{

    int i;
    char char_array[5] = {'a', 'b', 'c', 'd', 'e'};
    int int_array[5] = {1, 2, 3, 4, 5};
    char *char_pointer;
    int *int_pointer;
    char_pointer = char_array;
    int_pointer = int_array;

    for(i=0; i < 5; i++) { // Iterate through the int array with the int_pointer.
        printf("[integer pointer] points to %p, which contains the integer %d\n", int_pointer, *int_pointer);
        int_pointer = int_pointer + 1;
    }

    for(i=0; i < 5; i++) { // Iterate through the char array with the char_pointer.
        printf("[char pointer] points to %p, which contains the char '%c'\n", char_pointer, *char_pointer);
        char_pointer = char_pointer + 1;
    }

}

القوائم المرتبطة مقابل المصفوفات

المصفوفات ليست الخيار الوحيد المتاح المعلومات على قائمة مرتبطة.

http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_linklist.aspx

الختام

هذه المعلومات كانت مكتوبة ببساطة أن تمر على بعض ما قرأت طوال بحثي في هذا الموضوع التي قد تساعد الآخرين.

اقتباس من ويكيبيديا المقالة على مؤشرات C -

في C، يتم تعريف الفهرسة مجموعة رسميا من حيث الحساب المؤشر. هذا هو، مواصفات اللغة يتطلب أن مجموعة [أنا] يكون معادلا ل* (مجموعة + ط). وهكذا في C، المصفوفات يمكن اعتبار مؤشرات إلى أجزاء متتالية من الذاكرة (مع عدم وجود فجوات)، وبناء الجملة من أجل الوصول إلى صفائف مطابق لذلك والتي يمكن استخدامها لdereference المؤشرات. على سبيل المثال، يمكن تعريف مجموعة واستخدامها على النحو التالي:

int array[5];      /* Declares 5 contiguous (per Plauger Standard C 1992) integers */
int *ptr = array;  /* Arrays can be used as pointers */
ptr[0] = 1;        /* Pointers can be indexed with array syntax */
*(array + 1) = 2;  /* Arrays can be dereferenced with pointer syntax */

وهكذا، وذلك ردا على سؤالك - على نعم ، أو مؤشرات إلى مؤشرات يمكن استخدام مجموعة واسعة من دون أي نوع من إعلان آخر على الإطلاق

وحاول a[1][2]. أو *(*(a+1)+2).

والأساس، والمراجع مجموعة هي نحوي السكر لdereferencing المؤشر. و[2] هو نفس + 2، وأيضا نفس 2 [أ] (إذا كنت تريد حقا رمز غير قابل للقراءة). مجموعة من السلاسل هي نفس مؤشر مزدوج. حتى تتمكن من استخراج السلسلة الثانية باستخدام إما [1] أو *(a+1). ثم يمكنك العثور على الحرف الثالث في هذه السلسلة (يطلق عليه 'ب' في الوقت الحالي) مع إما ب [2] أو *(b + 2). استبدال السلسلة الثانية الأصلي ل 'ب'، نحن في نهاية المطاف مع إما [1] [2] أو *(*(a+1)+2).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top