2016-02-13 27 views
0

当我有一个功能,以空格替换选项卡中,看起来像这样的字符串:分段故障detabing串

#include <stdio.h> 

char *detab(char *string) 
{ 
    for (int i = 0; string[i] != '\0'; i++) 
     if (string[i] == '\t') 
      string[i] = ' '; 
    return string; 
} 

int main(int argc, char **argv) 
{ 
    char *string = "\thello\thello"; 
    detab(string); 
    printf("%s\n", string); 
    return 0; 
} 

但是当我在"\thello\thello\t"运行它,它会产生分段错误。它为什么这样做?我对C很新,所以我可能会错过一些微不足道的东西。

+2

你不能修改字符串在C字面[是否有可能修改的char在C语言的字符串?](https://stackoverflow.com/questions/1011455/is-it-it-it-of-char-in-c/1011545#1011545) – Rabbid76

+0

我们不知道这个函数是否在字符串文字上被调用。你能否说明你是如何称呼这个函数的,以及你如何声明你作为参数传递的东西? – e0k

+1

@ e0k他说:但是当我在“\ thello \ thello \ t”上运行它时 – Rabbid76

回答

2

这可能是因为调用代码没有为字符串分配足够的空间。它必须始终至少分配一个大于字符串中可见字符的空间,以允许\ 0的空间。

这就是说,由于字符串是可变的,所以不需要返回字符串。它会在你工作时修改字符串。

这里将是你的代码的工作版本:

void detab(char * myStr) 
{ 
    for (int i = 0; myStr[i] != '\0'; i++) 
     if (myStr[i] == '\t') 
      myStr[i] = ' '; 
} 

char theString[] = "\thello\thello\t"; 
printf("Before: %s", theString); 
detab(theString); 
printf("After: %s", theString); 

另外,请记住以下几点:

char buffer[4] = "test"; //THIS IS NOT SAFE. It might work, but it will overwrite stuff it shouldn't 
char buffer[5] = "test"; //This is Ok, but could be an issue if you change the length of the string being assigned. 
char buffer[] = "test"; //This is preferred for string literals because if you change the size of the literal, it will automatically fit. 

UPDATE:此基础上添加的主要方法,这里是你的问题:

您需要更改

char * string = "\thello\thello"; 

char string[] = "\thello\thello"; 

的原因是,当你定义一个字符串,并将其分配给一个char *,它驻留在记忆的文字部分,并且不能安全地修改。相反,您应该将字符串文字分配给一个char [](它可以作为char *传递,因为这是它的实际类型)。这个语法将让编译器知道它应该在堆栈上分配空间,并用字符串文本中的值填充它,从而允许修改它。

char * joe =“blah”只是创建char *指针,并将其指向文本部分中的数据(它是不可变的)。

char joe [] =“blah”告诉编译器在堆栈上创建一个长度合适的数组,用字符串文字加载它来创建char *指针,然后将指针指向启动堆栈上的数据阵列。

+1

我应该补充说,通常最好传递字符串的长度并使用它来代替检查\ 0终止,因为它可以允许函数在包含其他数据的二进制字符串上工作,而不仅仅是c字符串。 – techdude

+1

根据你如何分配你传入的字符串,你必须小心,他们保持空终止,并且他们有足够的空间分配。在你的问题中没有足够的上下文来确定你的问题是什么,但这应该指向你正确的方向。 – techdude

+1

如果你正在使用malloc,让我知道一些额外的细节,我可以覆盖那些 – techdude

1

这工作:

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

char *detab(char *string) 
{ 
    for (int i = 0; string[i] != '\0'; i++) 
     if (string[i] == '\t') 
      string[i] = ' '; 
    return string; 
} 

int main (int argc, char ** argv) { 
    char str[21] = "\thello\thello\t"; 

    printf("%s\n", detab(str)); 

    return 0; 
} 

正如其他人所说,这可能是因为段错误你正在修改一个字符串。使用char str[21]时,字符串文字被复制到堆栈分配的str中,然后可以在其中通过函数进行修改。

+0

没有必要这样做。假如它被分配给在堆栈上分配的char数组,它就会很好。 – techdude

+0

我想你的意思是''char str [21] =“\ thello \ thello \ t”''......是的,那也行得通。谢谢,我会更新我的答案。 – Chad

0

你确定字符串总是空终止。

尝试一些带和背带......

char *detab(char *string) 
{ 
    int s_len= strlen(string) + 1; 

    for (int i = 0; string[i] != '\0'; i++) 
    { 
     if (string[i] == '\t') 
     { string[i] = ' '; } 
     if (i == s_len) { /* failure - print some diagnostic */ return NULL; } 
    } 
    return string; 
    } 
+0

这不会是一个足够的检查,因为strlen使用空终止字符来确定长度,这与OP最初所做的没有什么不同。 http://www.cplusplus.com/reference/cstring/strlen/ – techdude

+0

字符串文字自动为您插入“\ 0”。 – Majora320

+0

strlen返回字符串的大小,不包括空终止字符,因此除了s_len(有人已经整理成一个而不是两行)。 – cdcdcd