【问题标题】:Binary conversion code Segmentation fault二进制转换代码分段错误
【发布时间】:2014-06-02 23:52:39
【问题描述】:

我是 C 编程的新手(只用了 2 周)。我无法弄清楚为什么我的代码会引发分段错误。如果我将 long int num 设置为一个静态数字,我就能让程序工作。但是我需要程序能够接受来自命令行的用户输入(不是在程序运行后)

示例: ./binary 7

应该输出 7的二进制数是:111

我尝试过使用 strcpy(num, argv[0]) 但编译时也会抛出错误。

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

void decToBinary(long int num)   // Function Definition
{
    long int remainder[50];
    int i=0;
    int length=0;
    printf("The binary number for %d is: ",num);
    while(num > 0)
     {
             remainder[i]=num%2;    // does the mod function
             num=num/2;             // Divides original number by 2
             i++;                   // Increases count for the upcoming for-loop
             length++;              // Increases length display digits
     }
    for(i=length-1;i>=0;i--)        // Prints out the binary number in order (ignoring the previous 0's)
    {
            printf("%ld",remainder[i]);
    }
    printf("\n");                   // Adds a new line after the binary number     (formatting)
}
//================================================================================================
int main(char argc, char* argv[])
{
    long int num;                           //HOW DO I TAKE ARGV[0] AND MAKE IT A USEABLE VARIABLE???

    printf("Enter the decimal number:  ");  //TEMPORARY until problem above is solved
    scanf("%ld",&num);                      //TEMPORARY until problem above is solved

    decToBinary(*num);                      // Calling decToBinary function
    return 0;                               // Program terminated successfully
}

【问题讨论】:

  • 如果您是 C 新手,那么您的第一个致命错误就是您正在丢弃 scanf 的返回值。您的第二个致命错误是您忽略了编译器的警告,或者更糟糕的是,没有指示您的编译器警告您明显的错误(例如*num)。
  • Ideone 出于三个不相关的原因放弃了您的代码。

标签: c pointers binary segmentation-fault


【解决方案1】:

提示1:如果你想在decToBinary()函数中改变num的值,你必须在其中传递它的地址。所以你应该这样称呼它:

decToBinary(&num);

那么你的函数原型应该是这样的:

void decToBinary(long int *num)

所以你也必须正确地修改函数的主体。我猜这就是导致分段错误的原因。


提示2:argc 代表参数计数,因此它的类型不是char,而是int


正如 @Kerrek SB 在他的 cmets 中指出的那样,scanf(3) 是一个返回值类型为 int 的函数。检查返回值并处理任何可能发生的错误被认为是明智的。


argv[0] 是可执行文件的名称。如果您想使用命令行中的第一个参数,它存储在argv[1] 中,并且它的类型为char *。所以如果你想用它作为一个数字,你可以使用stdlib.hthese函数之一。

【讨论】:

  • atoi 似乎是我需要的,我将如何将其隐含到代码中以获取第一个参数并存储它,这样我就可以将它传递给 decTobinary 函数?是否像在代码中添加“int atoi(const char *num) = argv[1]; 而不是“long int num;”一样简单?
  • @user3701193 如果您希望num 的类型为现在的long,那么您需要函数atol。它将像这样使用:long num = atol(argv[1]);。也请注意#include &lt;stdlib.h&gt;
  • 我猜我(经常)搞砸的是指针和取消引用。 atol 似乎工作得很好,但错误现在在 mod 操作中。 link
【解决方案2】:

类似的东西(不处理一些错误情况)

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

void decToBinary(long int num)   // Function Definition
{
    long int remainder[50];
    int i=0;
    int length=0;
    printf("The binary number for %ld is: ", num);
    while(num > 0)
     {
             remainder[i]=num%2;    // does the mod function
             num=num/2;             // Divides original number by 2
             i++;                   // Increases count for the upcoming for-loop
             length++;              // Increases length display digits
     }
    for(i=length-1;i>=0;i--)        // Prints out the binary number in order (ignoring the previous 0's)
    {
            printf("%ld",remainder[i]);
    }
    printf("\n");                   // Adds a new line after the binary number     (formatting)
}
//================================================================================================
int main(int argc, char* argv[])
{
    if (argc > 1)
    {
        long int mylong = atol(argv[1]);
        decToBinary(mylong);                      // Calling decToBinary function
    } else
    {
        int errno = 0;
        long int num;                           
        int res;

        printf("Enter the decimal number:  ");  //TEMPORARY until problem above is solved
        res = scanf("%ld",&num);                      //TEMPORARY until problem above is solved

        if (res != EOF)
        {
            decToBinary(num);                      // Calling decToBinary function
        } else
        if (errno != 0)
        {
            perror("scanf");
        } else
        {
            printf("No number found in input\n");
        }
    }

    return 0;                               // Program terminated successfully
}

** 我在 Ubuntu 14.04 上构建它 **

请注意 decToBinary(*num) 是错误的。您只能在指针上使用取消引用运算符,而不是 int 或任何非指针类型。

指针在内存中保存一个地址,当您取消引用它时,您是在告诉您的程序从该地址读取。如果您取消引用例如 10 的 int 值,则您是在告诉程序读取地址 10 处的值。这是一个非常低的地址值,将超出您的程序允许访问的内存范围,因此它将是分段错误。

首先你必须注意编译器警告。如果适用,在构建可执行文件时使用 -Werror 和可能的 -Wextra 标志。

例如 gcc -g -Werror -Wextra myfile.c -o myfile

这是学习使用调试器查找段错误的好机会,如果您对 C 编程的基本知识很认真的话。请注意上面的 -g 标志,它将调试符号构建到您的可执行文件中(没有符号,调试器将不知道函数名称)。然后,您可以使用 gdb(或其他适用的调试器)并启动您的可执行文件,然后运行它并获取回溯以告诉您何时发生段错误。

【讨论】:

    【解决方案3】:

    一种将argv[1] 参数提取到其组成位并显示这些位的简单方法...

    // following eliminates any nonnumeric char from input
    // by stopping at first nonnumeric char
    long int value = atol(argv[1]);  
    int position = sizeof( long int ) -1;
    
    // following loop could be modified/prefixed with a loop to skip leading 0's
    for( ; position >= 0; position-- )
    {
        printf( "%c, ", ('0' + ( value >> position) & 1) );
    }
    
    printf( "\n" );
    

    【讨论】:

      猜你喜欢
      • 2016-04-15
      • 2015-07-19
      • 1970-01-01
      • 2012-04-10
      • 2017-02-04
      • 1970-01-01
      • 2018-10-22
      • 2011-04-18
      相关资源
      最近更新 更多