【问题标题】:Segmentation fault at writing the telephone number program编写电话号码程序时出现分段错误
【发布时间】:2021-01-29 07:28:14
【问题描述】:

我正在编写一个 C 程序,提示用户以 (xxx)xxx-xxxx 的形式输入电话号码,然后以 xxx.xxx.xxxx 的格式显示该号码。这是一个例子:

Enter a phone number [(xxx) xxx-xxxx]: (404)817-6200
You entered the data 404.817.6200

我创建了两个字符串,一个用于存储带有括号和“-”符号的电话号码,另一个是空的。我想将每个字符添加到空字符串中,将 ')' 和 '-' 更改为 '.'。这是我的代码:

#include <stdio.h>
int main(void){
    char num[15];
    char phone[13];

    int i = 1;
    int j = 0;
    printf("Please, enter your phone number in the format (xxx)xxx-xxxx:");
    scanf("\n%s", num);
    while(num != '\0'){
        if(num[i] == ')' || num[i] == '-'){
            phone[j] = '.';
        }else{
            phone[j] = num[i];
        }
        i++;
        j++;
        
    }
    printf("\n%s",phone);
}

当我运行程序时,它给了我一条错误消息:

Segmentation fault

有人可以解释为什么会发生这种情况以及将来如何预防吗?

【问题讨论】:

  • while(num != '\0') -> while(num[i] != '\0')
  • 成功了!你能解释一下吗?
  • @RomanMukosieiev 你的编译器应该已经警告你了。 num 是数组,但您只需要数组的 一个 元素。
  • 您没有将空终止符复制到phone
  • 至于为什么会这样,和你的原因一样num[i] == ')'

标签: c string segmentation-fault scanf


【解决方案1】:

当您在 C 中引用数组变量的名称时,没有附加 [](索引)运算符,您(实际上)是在引用该数组第一个元素的 地址。对于声明为局部变量的数组,这永远不会为零(或NULL),因此numwhile 循环中的零('\0')的比较将永远 true,并且循环将不间断地运行,直到您尝试读取或写入无效地址,此时程序将崩溃。

启用编译器警告后,您应该会看到如下内容(由 clang-cl 生成):

警告:将指针与空字符常量进行比较;你是否 意思是与NULL比较? [-Wpointer-compare]
警告:比较 数组 'num' 不等于空指针始终为真 [-Wtautological-pointer-compare]

相反,您应该将“当前”元素(位于索引i)与nul 字符('\0')进行比较,以检查字符串的结尾:

    while (num[i] != '\0') {// Check character at position "i"
        // rest of your loop ...

您还应该确保您的phone 字符串正确地以nul 终止(尽管一些编译器会将数组初始化为零,但不要依赖于此)。您可以通过在 phone 的声明中添加一个初始化器来做到这一点:

    char phone[13] = { 0 }; // Will set all elements to zero

或在while 循环结束后添加nul 终止符立即

        // body of while loop
        // ...
    }
    phone[j] = '\0'; // Append the terminator

【讨论】:

    【解决方案2】:

    我在您的程序中发现了三个问题:

    (1) while(num != '\0') 应该是 while(num[i] != '\0'num 是一个数组(永远不会比较等于 '\0',所以你会得到一个无限循环并超出数组边界。

    (2) phone 至少需要 14 个字节(仅比 num 少一个,而不是少两个)

    (3) 你需要在phone中写入一个字符串终止符;否则printf("\n%s",phone); 将再次超出phone 的范围;例如:

    }
    phone[j] = '\0';
    printf("\n%s",phone);`
    

    【讨论】:

    • 如果输出确实是 alwaysxxx.xxx.xxxx 格式,那么对于phone ... 和num 而言,13 的大小就足够了 ... 和 num 只需 14 .
    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2022-11-23
    • 1970-01-01
    • 2019-11-03
    • 2017-02-08
    • 1970-01-01
    相关资源
    最近更新 更多