Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
strcat上的分段故障_C_Segmentation Fault_Strcat - Fatal编程技术网

strcat上的分段故障

strcat上的分段故障,c,segmentation-fault,strcat,C,Segmentation Fault,Strcat,我最近开始学习C语言,并且反复遇到一个错误,从模块调用strcat函数会导致分段错误。我在网上搜索了答案,包括在上,但没有成功。我认为这个社区可能对这个问题有更多的个人见解,因为一般的解决方案似乎不起作用。可能是用户错误,可能是代码的个人问题。看一看 #include <stdio.h> #include <string.h> char * deblank(const char str[]){ char *new[strlen(str)]; char *

我最近开始学习C语言,并且反复遇到一个错误,从
模块调用strcat函数会导致分段错误。我在网上搜索了答案,包括在上,但没有成功。我认为这个社区可能对这个问题有更多的个人见解,因为一般的解决方案似乎不起作用。可能是用户错误,可能是代码的个人问题。看一看

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

char * deblank(const char str[]){
    char *new[strlen(str)];
    char *buffer = malloc(strlen(new)+1);
    for (int i=0; i<strlen(*str); i++){
        if(buffer!=NULL){
            if(str[i]!=" "){
                strcat(new,str[i]); //Segmentation fault
            }
        }
    }
    free(buffer);
    return new;
}

int main(void){
    char str[] = "This has spaces in it.";
    char new[strlen(str)];
    *new = deblank(str);
    puts(new);
}
#包括
#包括
char*deblank(const char str[]){
字符*新[strlen(str)];
char*buffer=malloc(strlen(新)+1);

对于(int i=0;i所以,不确定这是否对您有帮助,但与Java代码相同的C代码如下所示:

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

static char *removeBlanks(const char *str)
{
    char *result = malloc(strlen(str) + 1);
    if (!result) exit(1);
    const char *r = str;
    char *w = result;
    while (*r)
    {
        // copy each character except when it's a blank
        if (*r != ' ') *w++ = *r;
        ++r;
    }
    *w = 0; // terminate the result to be a string (0 byte)
    return result;
}

int main(void)
{
    const char *str = "This has spaces in it.";
    char *new = removeBlanks(str);
    puts(new);
    free(new);
    return 0;
}
#包括
#包括
#包括
静态字符*removeBlanks(常量字符*str)
{
char*result=malloc(strlen(str)+1);
如果(!result)退出(1);
const char*r=str;
char*w=结果;
while(*r)
{
//复制每个字符,空白字符除外
如果(*r!='')*w++=*r;
++r;
}
*w=0;//将结果终止为字符串(0字节)
返回结果;
}
内部主(空)
{
const char*str=“其中包含空格。”;
char*new=删除空白(str);
出售(新);
免费(新);
返回0;
}

< >我不推荐命名变量<代码>新< /C>……如果你想使用C++,这是一个保留关键字。

我尝试用启用警告编译,这里有一些你应该修复的。
  • 您需要包括
    stdlib.h
  • char*new[strlen(str)]
    创建一个
    char*
    数组,而不是
    char
    ,因此不是真正的字符串。将其更改为
    char new[strlen(str)]
  • 要检查
    str[i]
    是否为空格,请将其与空格字符
    '
    ,而不是唯一字符为空格的字符串
    ”。因此将其更改为
    str[i]!='
  • strcat
    将字符串作为第二个参数,而不是字符,就像您用
    str[i]
    给出的那样
另外,您使用
buffer
的目的是什么

另一个错误是,您可能假设未初始化的数组取零值。
new
数组具有随机值,而不是零/空。
strcat
连接两个字符串,因此它会尝试将字符串放在第一个参数
new
末尾的第二个参数中。“end”字符串的第一个参数是空字符。程序在
new
中搜索它能找到的第一个空字符,当它找到这个空字符时,它开始从那里写入第二个参数


但是由于
new
未初始化,程序可能在
new
中找不到空字符,并且它将继续搜索长度超过
new
strlen(str)
,在未分配的内存中继续搜索。这可能是导致分段错误的原因。

您不能像以前那样使用
strcat
,它旨在将一个C字符串链接到另一个给定字符串的末尾。
str[i]
是字符而不是C字符串(请记住,C字符串是连续的字符序列,最后一个是NUL字节)

您也不能将字符串与标准比较运算符进行比较,如果您确实需要比较字符串,那么它就有一个
strcmp
函数。但是您可以将字符与标准运算符进行比较,因为字符只是一种整数类型

这应该可以做到:

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

char * deblank(const char str[]) {
    char *buffer = malloc(strlen(str)+1); // allocate space to contains as much char as in str, included ending NUL byte
    for (int i=0, j=0; i<strlen(str)+1; i++) { // for every char in str, included the ending NUL byte
      if (str[i]!=' ') { // if not blank
        buffer[j++] = str[i]; // copy
      }
    }
    return buffer; // return a newly constructed C-string
}

int main(void){
    char str[] = "This has spaces in it.";
    char *new = deblank(str);
    puts(new);
    free(new); // release the allocated memory
}
#包括
#包括
#包括
char*deblank(const char str[]){
char*buffer=malloc(strlen(str)+1);//分配空间,使其包含与str中相同数量的字符,包括结尾的NUL字节
对于(inti=0,j=0;i好的,让我们这样做

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

char * deblank(const char str[]){
    char *new[strlen(str)];
malloc
未声明。缺少
#include
。此外,您应该在此处检查分配失败

strlen(new)
是一个类型错误。
strlen
接受一个
char*
但是
new
是(或者更确切地说是)一个
char**

    for (int i=0; i<strlen(*str); i++){
                strcat(new,str[i]); //Segmentation fault
}

int main(void){
    char str[] = "This has spaces in it.";
    char new[strlen(str)];
    *new = deblank(str);
    puts(new);
这是一个检查分配失败的奇怪的地方。而且,你没有在任何地方使用
缓冲区
,那么为什么要创建/检查它呢

            if(str[i]!=" "){
str[i]!=“
是一个类型错误。
str[i]
是一个
char
是(或者更确切地说是)一个
char*

                strcat(new,str[i]); //Segmentation fault
    puts(new);
这是一个类型错误。
strcat
接受两个字符串(
char*
),但是
new
是一个
char**
str[i]
是一个
char
。另外,
strcat
的第一个参数必须是有效字符串,但
new
未初始化

            }
        }
    }
    free(buffer);
    return new;
new
是此函数中的一个局部数组。您返回的是它的第一个元素的地址,这毫无意义:函数一返回,它的所有局部变量都将消失。您在此处返回的指针无效

另外,这是一个类型错误:
deblank
声明返回一个
char*
,但实际上返回一个
char**

    for (int i=0; i<strlen(*str); i++){
                strcat(new,str[i]); //Segmentation fault
}

int main(void){
    char str[] = "This has spaces in it.";
    char new[strlen(str)];
    *new = deblank(str);
    puts(new);
这是一个类型错误:
*new
是一个
char
但是
deblank
返回一个
char*

                strcat(new,str[i]); //Segmentation fault
    puts(new);
put
接受一个字符串,但是
new
在这一点上本质上是垃圾

}

这项任务可以有三种方法

第一个是更新字符串“in-place”

#include <stdio.h>
#include <ctype.h>
#include <iso646.h>

char * deblank( char s[] )
{
    size_t i = 0;

    while ( s[i] and not isblank( s[i] ) ) ++i;

    if ( s[i] )
    {
        size_t j = i++;
        do
        {
            if ( not isblank( s[i] ) ) s[j++] = s[i];
        } while( s[i++] );
    }

    return s;
}

int main(void) 
{
    char s[] = "This has spaces in it.";

    puts( s );

    puts( deblank( s ) );

    return 0;
}
#include <stdio.h>
#include <string.h>

int main(void) 
{
    char s1[12] = "Hello ";
    char *s2 = "World";

    for ( size_t i = 0; s2[i] != '\0'; i++ )
    {
        strncat( s1, &s2[i], 1 );
    }

    puts( s1 );

    return 0;
}
另一种方法是跳过空格复制目标字符数组中的源字符串

在这种情况下,函数将有两个参数:源数组和目标数组。目标数组的大小必须等于源数组的大小,因为通常源数组不能有空格

#include <stdio.h>
#include <ctype.h>
#include <iso646.h>

char * deblank( char *s1, const char *s2 )
{
    char *t = s1;

    do 
    {
        if ( not isblank( *s2 ) ) *t++ = *s2;
    } while ( *s2++ );

    return s1;
}

int main(void) 
{
    char s1[] = "This has spaces in it.";
    char s2[sizeof( s1 )];

    puts( s1 );

    puts( deblank( s2, s1 ) );

    return 0;
}
目标字符串的大小通常不应小于源字符串的大小

最后,第三种方法是
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void deblank(const char* str, char *dest) {
    if (!*str) {*dest = '\0';return;}

    // when we encounter a space we skip
    if (*str == ' ') {
      deblank(str+1, dest);
      return;
    }

    *dest = *str;
    deblank(str+1, dest+1);
}

int main(void) {
    const char *str = "This has spaces in it.";
    char *output    = malloc(strlen(str)+1);
    deblank(str, output);
    puts(output);
    free(output);
}