C语言 strShiftLeft(字符串 * 字符串,整数n)持续获得“zsh:总线错误”

tf7tbtn2  于 2022-12-26  发布在  其他
关注(0)|答案(1)|浏览(133)

我正在尝试实现一个C函数char * strShiftLeft(char * string,int n),它接受字符串(str)和一个int n,表示str左移多少个字符。例如,如果我们将其称为strShiftLeft(《托马斯》,2),当我们追加前2个字符时,函数应该返回一个字符指针,指向字符串"omasTh(n)个字符到字符串的末尾,并且每字符向左移位2个时隙。
然而,由于某种原因,当我编译我的程序时,它编译得很好,但当我在Mac上运行它时,我的终端一直显示:

zsh: bus error  ./a.out

下面是我的代码:

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

char* strShiftLeft(char* str, int n)
{

    // If the passed in string is NULL, return NULL 
    if (str == NULL)
    {
        printf("NULL!\n");
        return NULL;
    }

    // Get the length of the string
    int len = 0;
    char* counter_ptr = str;
    while (*counter_ptr != '\0')
    {
        len++;
        counter_ptr++;
    }

    printf("len: %d\n", len);

    // If the integer is longer than the string, return back NULL
    if (n > len)
    {
        printf("n too big!\n");
        return NULL;
    }

    // Create a temp char array to store 1st n chars to append to the end of string later
    char temp_arr[n];
    for (int i = 0; i < n; i++)
    {
        *(temp_arr + i) = *(str + i);
    }

    printf("temp_arr = %s\n", temp_arr);
    printf("str is still: %s\n", str);

    // So far so good

    char* temp = str + n;
    printf("len - n = %d\n", len - n);

    // Update first (len - n) characters of the string (e.g. n = 2, "Thomas" -> "omasas")
    for (int i = 0; i < (len - n); i++)
    {
        printf("*temp = %c\n", *temp);
        printf("*(temp - n) = %c\n", *(temp - n));

        
        *(temp - n) = *(temp); // THIS LINE SEEMS TO BE THE ONE CAUSING ERRORS
        temp++;
    }

    temp = str + (len - n);
    for (int i = 0; i < n; i++)
    {
        *(temp + i) = *(temp_arr+i); // THIS LINE ALSO SEEMS TO BE CAUSING ERRORS
    }

    return str;
}


int main()
{
    char* str = strShiftLeft("Thomas", 2);
    printf("%s\n", str); // Should print out "omasTh"

    return 0;
}

我用了很多printf()来找出问题所在。我注意到有两行代码似乎导致了一些错误,即:(一)

*(temp - n) = *(temp);
*(temp + i) = *(temp_arr+i);

我想用这两行代码做的是,用字符串中其他元素的值来更新字符串中某些元素的值。
虽然我的代码编译了,但当我运行它时,它显示"zsh:bus error ./a. out "。我试着使用一些在线编译器。当我运行我的代码时,我得到了seg错误。
我不知道我犯了什么错。
如果有人能帮我找出我所犯的错误,我将不胜感激。
注意,我不允许使用动态内存分配,括号操作符来解引用指针,或者任何来自C库的函数,比如strlen(),strcpy()等等。谢谢!
我已经使用printf()来查明哪些行导致错误,但是我不明白为什么它们会导致错误。

fxnxkyjh

fxnxkyjh1#

当调用strShiftLeft("Thomas", 2);时,向strShiftLeft()传递的是字符串文字的地址。
strShiftLeft()然后继续尝试并就地修改您传递给它的字符串,这意味着它尝试修改字符串文字。
在C中修改字符串字面量是“未定义的行为”,这意味着任何事情都可能发生。

***任何内容***包括:

  • 什么都没有。如果你运行的环境碰巧在读写内存中存储了C字符串,就会发生这种情况。(这是危险的,因为它可能给予你的印象是你的程序工作,而实际上它没有。)
  • 一碗碗牵牛花和抹香鲸从天而降。(强制性HGGTG参考)
  • 更可能:程序由于分段错误(segfault)而终止,因为字符串文本存储在只读内存中,而程序试图写入该内存。

然而,这并不是您的情况,因为您没有收到segfault,而是收到了总线错误,总线错误意味着您的程序不仅仅试图写入只读存储器;这意味着它试图寻址甚至不能被寻址的存储器。
导致总线错误的原因很可能是:

printf("temp_arr = %s\n", temp_arr);

发生的情况是,您忘记了以null终止temp_arr,因此printf()函数打印temp_arr包含的任何内容,然后在temp_arr结束后继续打印。由于temp_arr位于堆栈中,printf()尝试从内存读取堆栈结束后的内容,这很可能是一些无效页。
这是开始使用调试器并停止使用printf()语句的另一个原因。

相关问题