Не очень полезная ошибка - ошибка сегментации (основной дамп) в домашнем задании - PullRequest
0 голосов
/ 11 сентября 2010

При компиляции программы, содержащей эту конкретную функцию,

/*
 * Function read_integer
 *
 * @Parameter CHAR* stringInt
 *
 * Parameter contains a string representing a struct integer.
 * Tokenizes the string by each character, converts each char
 * into an integer, and constructs a backwards linked list out
 * of the digits.
 *
 * @Return STRUCT* Integer
 */
struct integer* read_integer( char* stringInt )
{
    int i, n;
    struct integer *curr, *head;

    int numDigits = strlen( stringInt ); // Find the length of the struct integer
    char *tok;
    head = NULL;

    for( i = 0; i < numDigits; i++ )
    {
        tok = strtok( stringInt, NULL ); // Tokenize the string by each char
        n = atoi( tok[i] ); // Convert char to an integer

        curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
        curr->digit = n; // Digit of current node is assigned to n
        curr->next = head; // Move to the next node in the list.
        head = curr; // Move head up to the front of the list.
    }

    return head; // Return a pointer to the first node in the list.
}

Я получаю предупреждение:

bigintII.c: In function ‘read_integer’:
bigintII.c:167: warning: passing argument 1 of ‘atoi’ makes pointer from integer without a cast
//usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘char’

Я пробовал несколько разных способов (в основном это были выстрелы в темноте), чтобы избавиться от предупреждения, но безрезультатно. Кто-нибудь может указать мне правильное направление?

--- /// ---

Оригинал, тупой вопрос ниже здесь, оставленный, потому что я не хочу быть тем парнем .---

Я пытаюсь отладить свое задание для CS1, чтобы я мог закончить его и перейти к чему-то интересному (например, работать над своими исследованиями CLisp), но я столкнулся с ошибкой, которую не могу пройти. Теперь, я знаю, что задание еще не завершено (то есть, оно не будет делать то, что я хочу, даже если я его запустил), но я не хочу помогать с этим (кроме того, какое это было бы удовольствие быть?). Если бы кто-то мог просто помочь мне понять, почему следующий код, когда компилируется и выполняется, производит бесполезный (для меня) Segmentation fault (core dumped), ну, это было бы здорово.

/*
 * File:   struct integer.c

 * Description: Assignment in using Linked Lists
 * in order to perform struct integer addition and subtraction.
 *
 * Created on September 1, 2010, 11:38 AM
 */

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


// Constant Definitions
#define ADD 1
#define SUB 2

// Output file
char *fName = "out.txt";
FILE *outFile;


/*
 * Create a prototype of a single
 * node in the Linked List.
 * Each node will represent a single
 * integer comprising one part of a struct integer.
 */
struct integer
{
    int digit;

    struct integer *next;
};


// Function Prototypes
struct integer* read_integer( char *stringInt );
struct integer* add( struct integer *p, struct integer *q );
struct integer* subtract( struct integer *p, struct integer *q);

int compare( struct integer *p, struct integer *q );

void print( struct integer *p );


// Main function
int main( )
{
    //Variable initialization

    /*
     * Initialize pointers to the linked lists.
     * One, *head, will always point to the
     * first element, the head, of the list.
     * The other element, *curr, will point to the
     * node currently being accessed, and will be
     * used to traverse the list.
     */
    struct integer* pHead;
    struct integer* qHead;
    struct integer* tHead; // Used to contain the total

    int numOps, oper, i;
    const char *fileName = "struct integer.txt";
    char bigintstr[200];
    FILE *inputFile;

    // Open output file
    outFile = fopen(fName, "a+");


    // Open up the input file for reading
    inputFile = fopen(fileName, "r");

    // Read in the number of operations to be performed
    fscanf(inputFile, "%d", &numOps);

    /*
     * For each operation that must be performed,
     * construct a linked list for each of the
     * struct integers in the file. Then, perform the operation
     * indicated by the digit preceding them.
     */
    for( i = 0; i < numOps; i++ )
    {
        // Read in the number that dictates operation
        fscanf(inputFile, "%d", &oper);

        // Read in the first struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer string to read_integer()
         * in order to construct a linked list out of it.
         */
        pHead = read_integer( bigintstr );

        // Read in second struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer str to read_integer()
         * in order to construct a linked list out of it.
         */
         qHead = read_integer( bigintstr );

         /*
          * Depending on the operation to be performed,
          * call the corresponding function.
          */
         switch( oper )
         {
             case ADD:
                 tHead = add( pHead, qHead );
                 break;
             case SUB:
                 tHead = subtract( pHead, qHead );
                 break;
             default:
                 printf("Invalid operation parameter.\n");
         }

         print( pHead ); // Print out the first struct integer
         fprintf(outFile, " + ");
         print( qHead ); // Print out the second struct integer
         fprintf(outFile, " = ");
         print( tHead ); // Print out the sum/difference struct integer
         fprintf(outFile, "\n"); // Move to next line for next instruction set
    }
    fclose(inputFile);

    //system(PAUSE);
    return 0;
}


// Function Definitions

/*
 * Function read_integer
 *
 * @Parameter CHAR* stringInt
 *
 * Parameter contains a string representing a struct integer.
 * Tokenizes the string by each character, converts each char
 * into an integer, and constructs a backwards linked list out
 * of the digits.
 *
 * @Return STRUCT* Integer
 */
struct integer* read_integer( char* stringInt )
{
    int i, n;
    struct integer *curr, *head;

    int numDigits = strlen( stringInt ); // Find the length of the struct integer
    char *tok;
    head = NULL;

    for( i = 0; i < numDigits; i++ )
    {
        tok = strtok( stringInt, NULL ); // Tokenize the string by each char
        n = atoi( tok[i] ); // Convert char to an integer

        curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
        curr->digit = n; // Digit of current node is assigned to n
        curr->next = head; // Move to the next node in the list.
        head = curr; // Move head up to the front of the list.
    }

    return head; // Return a pointer to the first node in the list.
}

/*
 * Function print
 *
 * @Parameter STRUCT* Integer
 *
 * Given a linked list, will traverse through
 * the nodes and print out, one at a time,
 * the digits comprising the struct integer that the
 * linked list represents.
 *
 * TODO: Print to file
 */
void print( struct integer *p )
{    
    while( p )
    {
        fprintf(outFile, "%d", p->digit);
        p = p->next;
    }
}

/*
 * Function add
 *
 * @Paramater STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing
 * big integers stored in reversed order,
 * and returns a linked list containing
 * the sum of the two integers.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* add( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *sHead, *sCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    sHead = NULL;

    while( p )
    {
        sCurr = ( struct integer* ) malloc (sizeof(struct integer));
        sCurr->digit = p->digit + q->digit + carry;
        sCurr->next = sHead;
        sHead = sCurr;

        carry = 0;

        /*
         * If the current digits sum to greater than 9,
         * create a carry value and replace the current
         * value with value mod 10.
         */
        if( sCurr->digit > 9 )
        {
            carry = 1;
            sCurr->digit = sCurr->digit % 10;
        }

        /*
         * If the most significant digits of the numbers
         * sum to 10 or greater, create an extra node
         * at the end of the sum list and assign it the
         * value of 1.
         */
        if( carry == 1 && sCurr->next == NULL )
        {
            struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
            sCarry->digit = 1;
            sCarry->next = NULL;
            sCurr->next = sCarry;
        }

        p = p->next;
        q = q->next;
    }

    return sHead;
}

/*
 * Function subtract
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing struct integers.
 * Traverses through the lists, subtracting each
 * digits from the subsequent nodes to form a new
 * struct integer, and then returns the newly formed
 * linked list.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* subtract( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *dHead, *dCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    dHead = NULL;

    while( p )
    {
        dCurr = (struct integer*) malloc (sizeof(struct integer));
        dCurr->digit = p->digit - q->digit - carry;
        dCurr->next = dHead;
        dHead = dCurr;

        if( dCurr->digit < 0 )
        {
            dCurr->digit += 10;
            carry = 1;
        }

        if( dCurr->next == NULL && carry == 1 )
        {
            struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
            dCarry->digit = -1;
            dCarry->next = NULL;
            dCurr->next = dCarry;
        }

        p = p->next;
        q = q->next;
    }

    return dHead;
}

/*
 * Function compare
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes in two linked lists representing struct integers.
 * Traverses the lists one at a time, comparing the
 * digits.
 *
 * Case: p < q
 * @Return -1
 *
 * Case: p == q
 * @Return 0
 *
 * Case: p > q
 * @Return 1
 * 
 * TODO Comment me
 */
int compare( struct integer *p, struct integer *q )
{
    struct integer *pHead, *qHead;
    int comp = 0;

    pHead = p;
    qHead = q;

    while( p )
    {
        if( p->digit > q->digit )
        {
            comp = 1;
        }

        if( p->digit < q->digit )
        {
            comp = -1;
        }

        p = p->next;
        q = q->next;
    }

    return comp;
}

Я сожалею, что есть много чего, я просто пытаюсь привыкнуть к чрезмерному документированию своего кода, потому что мне нравится возвращаться и читать то, что я написал, чтобы пересмотреть концепции. Однако сама программа довольно проста (если не сломана, хаха).

Ответы [ 2 ]

4 голосов
/ 11 сентября 2010

компиляция с помощью gcc дает это:

test.c: в функции read_integer: test.c: 165: предупреждение: передача аргумента 1 из «atoi» делает указатель из целого числа без приведения /usr/include/stdlib.h:148: примечание: ожидается "const char *", но аргумент имеет тип "char"

это 164/165

    tok = strtok( stringInt, NULL ); // Tokenize the string by each char
    n = atoi( tok[i] ); // Convert char to an integer

должно быть

   n =  stringInt - '0'; // Convert char to an integer

переменная tok теперь бессмысленна. он больше не падает со мной и находит правильный ответ (1 + 1 = 2),

кроме того, вы забыли закрыть выходной файл в конце вашей программы. и вы, очевидно, открываете выходной файл в режиме добавления (что неплохо, он просто застал меня врасплох)

затем возникает другое несоответствие, ваша функция добавления меняет порядок, в котором хранятся ваши номера, что означает, что входные числа печатаются в обратном порядке, а ответ печатается в правильном порядке.

Я исправил это сейчас:

/*
 * File:   struct integer.c

 * Description: Assignment in using Linked Lists
 * in order to perform struct integer addition and subtraction.
 *
 * Created on September 1, 2010, 11:38 AM
 */

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


// Constant Definitions
#define ADD 1
#define SUB 2

// Output file
char *fName = "out.txt";
FILE *outFile;


/*
 * Create a prototype of a single
 * node in the Linked List.
 * Each node will represent a single
 * integer comprising one part of a struct integer.
 */
struct integer
{
    int digit;

    struct integer *next;
};


// Function Prototypes
struct integer* read_integer( char *stringInt );
struct integer* add( struct integer *p, struct integer *q );
struct integer* subtract( struct integer *p, struct integer *q);

int compare( struct integer *p, struct integer *q );

void print( struct integer *p );


// Main function
int main( )
{
    //Variable initialization

    /*
     * Initialize pointers to the linked lists.
     * One, *head, will always point to the
     * first element, the head, of the list.
     * The other element, *curr, will point to the
     * node currently being accessed, and will be
     * used to traverse the list.
     */
    struct integer* pHead;
    struct integer* qHead;
    struct integer* tHead; // Used to contain the total

    int numOps, oper, i;
    const char *fileName = "struct_integer.txt";
    char bigintstr[200];
    FILE *inputFile;

    // Open output file
    outFile = fopen(fName, "a+");


    // Open up the input file for reading
    inputFile = fopen(fileName, "r");

    // Read in the number of operations to be performed
    fscanf(inputFile, "%d", &numOps);

    /*
     * For each operation that must be performed,
     * construct a linked list for each of the
     * struct integers in the file. Then, perform the operation
     * indicated by the digit preceding them.
     */
    for( i = 0; i < numOps; i++ )
    {
        // Read in the number that dictates operation
        fscanf(inputFile, "%d", &oper);

        // Read in the first struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer string to read_integer()
         * in order to construct a linked list out of it.
         */
        pHead = read_integer( bigintstr );

        // Read in second struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer str to read_integer()
         * in order to construct a linked list out of it.
         */
         qHead = read_integer( bigintstr );

         /*
          * Depending on the operation to be performed,
          * call the corresponding function.
          */
         switch( oper )
         {
             case ADD:
                 tHead = add( pHead, qHead );
                 break;
             case SUB:
                 tHead = subtract( pHead, qHead );
                 break;
             default:
                 printf("Invalid operation parameter.\n");
         }

         print( pHead ); // Print out the first struct integer
         fprintf(outFile, " + ");
         print( qHead ); // Print out the second struct integer
         fprintf(outFile, " = ");
         print( tHead ); // Print out the sum/difference struct integer
         fprintf(outFile, "\n"); // Move to next line for next instruction set
    }
    fclose(inputFile);
    fclose(outFile);
    //system(PAUSE);
    return 0;
}


// Function Definitions

/*
 * Function read_integer
 *
 * @Parameter CHAR* stringInt
 *
 * Parameter contains a string representing a struct integer.
 * Tokenizes the string by each character, converts each char
 * into an integer, and constructs a backwards linked list out
 * of the digits.
 *
 * @Return STRUCT* Integer
 */
struct integer* read_integer( char* stringInt )
{
    int i, n;
    struct integer *curr, *head;

    int numDigits = strlen( stringInt ); // Find the length of the struct integer
    char *tok;
    head = NULL;

    for( i = 0; i < numDigits; i++ )
    {
        n =  stringInt[i] - '0'; // Convert char to an integer

        curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
        curr->digit = n; // Digit of current node is assigned to n
        curr->next = head; // Move to the next node in the list.
        head = curr; // Move head up to the front of the list.
    }

    return head; // Return a pointer to the first node in the list.
}

void reverse (struct integer **p){
    if((*p)->next==0) return;
    struct integer *i=*p,*j;
    while(i->next){
        j=i;
        i=i->next;
    }//i is now the tail;
    i->next=j;
    j->next=0;
    reverse(p);
    *p=i;
}

/*
 * Function print
 *
 * @Parameter STRUCT* Integer
 *
 * Given a linked list, will traverse through
 * the nodes and print out, one at a time,
 * the digits comprising the struct integer that the
 * linked list represents.
 *
 * TODO: Print to file
 */
void print( struct integer *p )
{
    struct integer *head=p;
    reverse(&p);    
    while( p )
    {
        fprintf(outFile, "%d", p->digit);
        p = p->next;
    }
    reverse(&head);
}


/*
 * Function add
 *
 * @Paramater STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing
 * big integers stored in reversed order,
 * and returns a linked list containing
 * the sum of the two integers.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* add( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *sHead, *sCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    sHead = NULL;

    while( p )
    {
        sCurr = ( struct integer* ) malloc (sizeof(struct integer));
        sCurr->digit = p->digit + q->digit + carry;
        sCurr->next = sHead;
        sHead = sCurr;

        carry = 0;

        /*
         * If the current digits sum to greater than 9,
         * create a carry value and replace the current
         * value with value mod 10.
         */
        if( sCurr->digit > 9 )
        {
            carry = 1;
            sCurr->digit = sCurr->digit % 10;
        }

        /*
         * If the most significant digits of the numbers
         * sum to 10 or greater, create an extra node
         * at the end of the sum list and assign it the
         * value of 1.
         */
        if( carry == 1 && sCurr->next == NULL )
        {
            struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
            sCarry->digit = 1;
            sCarry->next = NULL;
            sCurr->next = sCarry;
        }

        p = p->next;
        q = q->next;
    }
    reverse(&sHead);
    return sHead;
}



/*
 * Function subtract
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing struct integers.
 * Traverses through the lists, subtracting each
 * digits from the subsequent nodes to form a new
 * struct integer, and then returns the newly formed
 * linked list.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* subtract( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *dHead, *dCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    dHead = NULL;

    while( p )
    {
        dCurr = (struct integer*) malloc (sizeof(struct integer));
        dCurr->digit = p->digit - q->digit - carry;
        dCurr->next = dHead;
        dHead = dCurr;

        if( dCurr->digit < 0 )
        {
            dCurr->digit += 10;
            carry = 1;
        }

        if( dCurr->next == NULL && carry == 1 )
        {
            struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
            dCarry->digit = -1;
            dCarry->next = NULL;
            dCurr->next = dCarry;
        }

        p = p->next;
        q = q->next;
    }

    return dHead;
}

/*
 * Function compare
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes in two linked lists representing struct integers.
 * Traverses the lists one at a time, comparing the
 * digits.
 *
 * Case: p < q
 * @Return -1
 *
 * Case: p == q
 * @Return 0
 *
 * Case: p > q
 * @Return 1
 * 
 * TODO Comment me
 */
int compare( struct integer *p, struct integer *q )
{
    struct integer *pHead, *qHead;
    int comp = 0;

    pHead = p;
    qHead = q;

    while( p )
    {
        if( p->digit > q->digit )
        {
            comp = 1;
        }

        if( p->digit < q->digit )
        {
            comp = -1;
        }

        p = p->next;
        q = q->next;
    }

    return comp;
}

я написал для вас обратное:

void reverse (struct integer **p){
    if((*p)->next==0) return;
    struct integer *i=*p,*j;
    while(i->next){
        j=i;
        i=i->next;
    }//i is now the tail;
    // 1->2->3->4->NIL

    i->next=j;
    // 1 -> 2 -> 3 <-> 4

    j->next=0;
    // 1 -> 3 -> 3 <- 4
    //           |
    //           v
    //          NIL
    reverse(p);// p looks like 1 -> 2 -> 3 now recurse
    *p=i;
}
3 голосов
/ 11 сентября 2010

Ваша проблема вызвана передачей неправильной вещи в atoi.atoi ожидает строку, которая, как вы знаете в C, является указателем на символ.Вы передаете один символ, который не является указателем символа.atoi пытается трактовать значение символа как адрес памяти, который почти наверняка является адресом, к которому у вас нет доступа, поэтому ваша программа идет на ура.

Чтобы получить числовое значение char, содержащий цифру ASCII, вычтите из нее '0', т.е. измените

n = atoi( tok[i] );

на

n = tok[i] - '0';

Но вам не нужно strtok:

for (i = 0; i < numDigits; i++) {
    n = stringInt[i] - '0';
    // etc
}
...