Запись в c-строку - PullRequest
       77

Запись в c-строку

3 голосов
/ 10 сентября 2009

мой код segfaults, и я не знаю почему.

 1  #include <stdio.h>
 2
 3  void overwrite(char str[], char x) {
 4    int i;
 5    for (i = 0; str[i] != '\0'; i++)
 6      str[i] = x;
 7  }
 8
 9  int main(void) {
10    char *s = "abcde";
11    char x = 'X';
12    overwrite(s, x);
13    printf("%s\n", s);
14    return 0;
15  }

Отладчик gdb говорит мне, что проблема в строке 6, где я хочу сохранить символ в c-строку (если я использую разыменование указателя lvalue, это та же проблема.) Это то, что он говорит:

(gdb) run
Starting program: /tmp/x/x 

Breakpoint 1, overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:5
5         for (i = 0; str[i] != '\0'; i++)
(gdb) s
6           str[i] = x;
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0x080483e3 in overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:6
6           str[i] = x;
(gdb) q

Я учусь на книге K & R-C, и это упрощенный пример из главы 2.8 (функция удаления). Я понятия не имею, в чем проблема.

Ответы [ 5 ]

17 голосов
/ 10 сентября 2009

потому что char * s = "abcde"; создает строку в постоянной памяти. попробуйте

char s[] = "abcde";

РЕДАКТИРОВАТЬ: объяснение: char * является указателем, и "abcde" создается в постоянной памяти -> неизменный.

char [] - это массив, который полностью хранится в стеке и инициализируется из памяти, поэтому может изменяться

2 голосов
/ 10 сентября 2009

Если вы определите указатель на строковый литерал , объявите его как const char *.

const char *s = "abcde";

Таким образом, ваш компилятор жалуется, когда вы пытаетесь отправить эту строку в функцию overwrite ().

const char *s = "abcde";
char t[] = "fghij";
char x = 'X';

overwrite(s, x); /* oops */
overwrite(t, x); /* ok */
1 голос
/ 10 сентября 2009

Не согласен, а просто уточню: подумайте, что произойдет, если компилятор это допустит. Вы могли бы написать:

char *s1="abcde";
char *s2="abcde";
s1[0]='x';
puts(s1);
puts(s2);

Если компилятор распознает, что два литерала одинаковы, и использует их повторно, но затем также разрешает строку 3, ваш вывод будет:

xbcde
xbcde

Что, вероятно, не то, что вы хотели бы. Это было бы особенно загадочно, если бы два литерала находились в разных частях программы.

0 голосов
/ 10 сентября 2009

Попробуйте:

#include <iostream>
#include <cstring>

using namespace std;

void overwrite(char[], char);

int main(void)
{
        char *s = strdup("abcde");
        char X = 'X';
        overwrite(s, X);
        cout << s << endl;

        if(s!=NULL)
                delete [] s;

        return 0;
}

void overwrite(char str[], char x)
{
        for(int i=0; str[i]!='\0'; i++)
                str[i] = x;
}
0 голосов
/ 10 сентября 2009

мое предположение - это определение параметра, в котором вы определяете тип как массив символов. Пока вы передаете указатель на символ

Вы можете попробовать изменить первую строку следующим образом:

 void overwrite(char *str, char x) {

Массив char и указатель char не являются семантически одинаковыми.

...