سؤال

وبعد قراءة التعليمات وكل شيء آخر يمكنني العثور عليها، وأنا ما زلت في حيرة. إذا كان لدي مؤشر شار الذي initialised في هذا الشكل:

وchar *s = "Hello world!"

والسلسلة هي في ذاكرة القراءة فقط وأنا لا يمكن تغييره مثل هذا:

*s = 'W';

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

وهذا هو قانون بلدي:

char *s = str;
char *e = s;
while (*e != '\0')
e++;
e--;
char *temp;
//Swop the string around
while (s <= e) {
    *temp = *s;
    *s = *e;
    *e = *temp;
    e--;
    s++;
}

ورسالة الخطأ هو مجرد خطأ تجزئة. الاعتذار مقدما إذا كان هذا هو سؤال غبي حقا.

وشكرا جزيلا على كل المساعدة. بعد أخذ كل ما تبذلونه من المشورة، وأحصل على هذا:

void something(char * str) {
    char *store = str;
    char *s = new char[strlen(str) + 1]; //Allocate memory. Nice one.
    strcpy(s, str);
    char *e = new char[strlen(str) + 1];
    strcpy(e, str);
    while (*e != '\0')
        e++;
    e--;
    char temp; //no longer a pointer
    while (s <= e) {
        cout << *e;
        temp = *s;
        *s = *e;
        *e = temp;
        e--;
        s++;

    }
    delete [] e;
    delete [] s;        
}

ولكن، والحذف في نهاية الدالة يبدو أن يسبب تجزئة أخطاء الخاصة بها. لماذا ا؟

لأجل مصلحة ل: كانت أخطاء بسبب الوصول إلى البريد والصورة مؤشرات بعد أن تم زيادة. والحل أبسط من ذلك بكثير يتبع من ذلك:

void something(char * str) {
    char *s = new char[strlen(str) + 1];
    strcpy(s, str);
    char temp;
    int j = strlen(str) - 1;
    for (int i = 0; i <= strlen(str)/2; i++) {
        cout << s << endl;
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        j--;
    }
    delete [] s;
}
هل كانت مفيدة؟

المحلول

وأسهل طريقة لتعديله هو خلق مجموعة لتخزين الخاص بك، ثم قم بنسخ السلسلة إلى ذلك.

وعلى سبيل المثال:

char buf[128];
const char *src = "Hello World";
strncpy(buf, src, 127); // one less - we always 0-terminate
buf[127] = '\0';

// you can now modify buf
buf[0] = 'W';

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

في الحال عندما كنت لا تعرف طول سلسلة مسبقا، يمكنك أيضا استخدام malloc (أو حتى أفضل، وتفعل ما drschnz والجواب يقول واستخدام <م> شار الجديد [] ):

const char *src = "Hello world";
char *buf = malloc(strlen(src) + 1);   // or = new char[strlen(src) + 1];
strcpy(buf, src);
// you can now modify buf
// later, you need to free it
free(buf);                             // or delete [] buf;

وأيضا، إذا كنت تستخدم C ++، يمكنك فقط استخدام الأمراض المنقولة جنسيا :: سلسلة:

std::string myString("Hello world");
myString[0] = "W";

وعلى أمل أن يساعد.

نصائح أخرى

وجرب:

char src[] = "Hello world";
src[6]     = 'W';

-- // or

char   buffer[] = "Hello world";
char*  src      = buffer;
src[6]          = 'W';

إذا كنت تريد نسخ سلسلة في المخزن مؤقت ثم استخدام strcpy () أو strncpy ()

char   buffer[20];
char const* s = "Hello World"

strcpy(s,buffer);

وإذا كان يجب إرسال نسخة سلسلة الخاصة بك ومن ثم ينبغي أن تبدو هذه:

char   buffer[20];
char const* s = "Hello World";

// OK this is not the perfect solution but it is easy to read.
for(int loop = 0;s[loop] != '\0';++loop)
{
    buffer[loop] = s[loop];
}
buffer[loop] = '\0';

ومؤشر ليست للقراءة فقط. (البيانات سلسلة نفسه، ولكن مؤشر لافتا إلى أنه يمكن تعديل بحرية) ومع ذلك، تعيين حرف لمؤشر لا تفعل ما كنت تتوقع.

في عام، والشيء الوحيد الذي يمكن أن يسند إلى نقطة هو عنوان. لا يمكنك تعيين القيم، إلا أن عنوان القيم.

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

والنقطة الأخرى هي أن الشخصيات في C ++ هي أنواع البيانات المتكاملة. ويمكن التعامل معها على أنها صحيحة مع عدم وجود الصب المطلوبة. أستطيع أن أفعل int i = 'W' وسوف مترجم لا يشكو.

وذلك ما يحدث إذا قمت بتعيين 'W' إلى مؤشر؟ فإنه يأخذ 'W' باعتبارها قيمة عددية، ويفترض أن هذا العنوان. 'W' له قيمة ASCII 127، لذلك كنت تقوم بشكل فعال المؤشر للإشارة إلى معالجة 127، الذي لا معنى له.

وأنا لا أرى كيف أن لديها الكثير لتفعله مع التعليمات البرمجية الخاصة بك على الرغم من. المشكلة يبدو أن هناك أن temp لا يشير إلى بيانات صالحة. قمت بتعريف المؤشر، مما يشير إلى بعض عنوان غير معروف. ثم تقول "أينما كان يشير إلى، أريد أن أكتب القيمة التي s يشير إلى أن تعمل على نحو أفضل إلى حد ما يلي:.

char temp; // not a pointer. We want a character to store our temporary value in
while (s <= e) {
    temp = *s; // note, no * on temp.
    *s = *e;
    *e = temp; // note, no * on temp.
    e--;
    s++;
}

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

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

تحرير تعليقات وتصحيحات إلى رمز المحدثة:

void something(const char * str) { // let the function take a pointer to a non-modifiable string, so add the const. Now it's clear that we're not allowed to modify the string itself, so we have to make a copy.
    char *s = new char[strlen(str) + 1]; // Since the original string is const, we have to allocate a copy if we want to modify it - in C, you'd use malloc(strlen(str)) instead
    strcpy(s, str);
    char *e = s; // make e point to the start of the copied string (don't allocate two copies, since e and s are supposed to work on the same string
    while (*e != '\0') { // add braces so it's clear where the loop starts and ends.
        e++;
    }
    e--;

    while (s <= e) { // the loop condition wouldn't work if s and e pointed to separate copies of the string
        cout << *e; // why? I thought you just wanted to reverse the string in memory. Alternatively, if you just want to print out the string reversed, you don't need to do most of the rest of the loop body. In C, you'd use printf instead of *e
        char temp = *s; // might as well declare the temp variable when you need it, and not before
        *s = *e;
        *e = temp;
        e--;
        s++;

    }
}

وفقط للرجوع اليها، وردا على تعليقات حول C ++ C مباراة، وهنا كيف كنت أكتب وظيفة لعكس سلسلة في C ++:

std::string revert_string(const std::string& str) {
  return std::string(str.rbegin(), str.rend());
}

وأو أن تعود السلسلة في نفس المكان:

std::string revert_string(const std::string& str) {
  std::reverse(str.begin(), str.end());
}

ومن الناحية الفنية، ما عليك القيام به هو كتب أكثر بشكل صحيح مثل ما يلي:

const char *s = "Hello world!"

وماذا كنت فعلا تريد أن يكون شيء من هذا القبيل:

char s[] = "Hello world!"

وبعد بضعة أسطر قد تساعدك على فهم أكثر من ذلك:

const char *p = "Hello World";
char q[] = "Hello World";
printf("%d %d", sizeof(p), sizeof(q));
// p[0] = 'W' // INVALID
q[0] = 'W'; // valid

وحذف لديك تولد أخطاء، لأنك غيرت المؤشر. يجب حفظ الموقع الأصلي من جديد، وحذف [] ذلك. حاولت حذف موقع غير موجود في جدول تخصيص. إذا كنت ترغب في تغيير قيمة المؤشر، وجعل تشار * درجة الحرارة = ر آخر؛ واستخدامه لتكرار عبر السلسلة.

وهناك # ق وظيفة "strdup ()" لعمل نسخة من سلسلة ... فإنه يجعل من أنك لا ننسى "+1" في malloc الخاص بك.

char* source = "Hello World";
char* dest = strdup(source);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top