【问题标题】:Run into segmentation fault when doing string manipulation in C在 C 中进行字符串操作时遇到分段错误
【发布时间】:2020-08-20 12:19:39
【问题描述】:

我正在努力从 C 中的主字符串中删除混淆子字符串。子字符串的格式为xx:xx:xx:xx:xx:xx,其中x 可以是数字或字母。子字符串的开头总是有一个空格,但子字符串的结尾并不总是有空格。

例如输入可以是"Found new device with wlan 33:33:33:33:33:33. Total 4 devices connected" 输出应该是"Found new device with wlan *. Total 4 devices connected"

我需要创建一个辅助函数来做到这一点,这就是我想出的:

//find the first occurency of ":" record as first_position_ptr and the last occurency of ":" record as last_position_ptr. 
// Add 2 to first_position_ptr to beginning of the substring and set it to "*"
// Subtract 2 from the last_position_ptr to get the pointer of the last charactor in substrung. 
// Iterate from 1 + first_position_ptr to last_position_ptr - 2 and set inStr to 0 to deleted the rest of substring. 

const char *proc(char *inStr) {
    const char tar[] = ":";
    char *first_position_ptr = strchr(inStr, tar[0]);
    char *last_position_ptr = strrchr(inStr, tar[0]);

    int first_position = (first_position_ptr == NULL ? -1 : first_position_ptr - inStr);
    int last_position = (last_position_ptr == NULL ? -1 : last_position_ptr - inStr);

    if (first_position != -1 && last_position != -1) {
        inStr[first_position + 2] = "*";
    }

    for (int i = (first_position + 1); i < (last_position + 2); i++) {
        inStr[i] = 0;
    }
    return inStr;
}

int main() {
    const char str[] = "Found new device with wlan 33:33:33:33:33:33. Total 4 devices connected";
    proc(*str);
    printf("%s\n", str);
    return 0;
}

但是当我编译代码时,我遇到了这些警告:

Jeff-MacBook-Pro-2:Desktop jBerman$ gcc test.c -o test
test.c:35:29: warning: incompatible pointer to integer conversion assigning to 'char' from
      'char [2]' [-Wint-conversion]
                inStr[first_position + 2] = "*";
                                          ^ ~~~
test.c:43:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
test.c:49:7: warning: incompatible integer to pointer conversion passing 'const char' to
      parameter of type 'char *' [-Wint-conversion]
        proc(*str);
             ^~~~
test.c:26:24: note: passing argument to parameter 'inStr' here
const char* proc(char *inStr){
                       ^
3 warnings generated.

当我运行它时,编译显示:

Segmentation fault: 11

所以我尝试在 main 中更正这一行:

proc(*str) -> proc(&str);

编译器返回:

Bus error: 10

有人可以告诉我可能出了什么问题吗?或者,如果您帮助更有效地执行此操作,请告诉我

【问题讨论】:

  • proc(*str)-->proc(str).

标签: c segment bus-error


【解决方案1】:

您应该将str 传递给proc,而不是*str,并将str 定义为可修改的char 数组。 proc 函数也应该简化:将中间的字符设置为零不会擦除中间部分,它会使字符串在* 之后停止。要保留字符串的结尾,您必须使用memmove() 复制它。

这是修改后的版本:

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

// replace the mac address from the input string with a *
char *proc(char *inStr) {
    char *p1 = strchr(inStr, ':');
    char *p2 = strrchr(inStr, ':');

    if (p1) {  // no need to test p2, there is at least one ':' in the string
        /* backtrack 2 characters, but not before the start of inStr */
        if (p1 > inStr) p1--;
        if (p1 > inStr) p1--;
        /* skip 3 characters, but not past the end of the string */
        p2++;
        if (*p2) p2++;
        if (*p2) p2++;
        /* replace the MAC address with a '*' */
        *p1++ = '*';
        /* move the rest of the string, including the null terminator */
        memmove(p1, p2, strlen(p2) + 1);
    }
    return inStr;
}

int main() {
    char str[] = "Found new device with wlan 33:33:33:33:33:33. Total 4 devices connected";
    printf("%s\n", proc(str));
    return 0;
}

【讨论】:

  • 非常感谢。代码效果很好。我只是对代码有一些疑问。例如,我尝试将两个 if (p1 &gt; inStr) p1--; 更改为 if (p1 &gt; inStr) p1-2; 它仍然保留子字符串的前 2 个字符
  • @ImTrying: p1-2 不会修改 p1p1 -= 2; 会将 p1 递减 2,但如果字符串以 a: 开头,这将使 p1 指向前面字符串的开头。这解释了为什么我有 2 行 if (p1 &gt; inStr) p1--; 和解释逻辑的注释。
  • 嗨,我在 bash shell 上运行这段代码,它运行良好。但是当我试图在 sh shell 上运行这个程序时,它会导致总线错误。我认为跳过指针导致了这种情况。你能告诉我你可以解决这个问题吗?
  • @ImTrying:你在运行哪个代码?你用什么系统?你如何编译代码?你如何运行代码?我的答案中的代码不使用命令行参数,也不读取标准输入,如果您从bashsh 运行它应该不会有什么不同。
  • 等等,抱歉,您刚才指出的正是错误。我很抱歉。我非常感谢您的帮助
猜你喜欢
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多