首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >K&R练习4-10:在实现getline时分割故障

K&R练习4-10:在实现getline时分割故障
EN

Stack Overflow用户
提问于 2022-07-21 14:04:28
回答 1查看 48关注 0票数 0

我试图找出为什么我的程序总是有一个分段错误,这是一个练习的一部分,数字4-10,在中,C编程语言图书的K&R。

我实现了每一种功能,就像这本书本身所教导的那样。我想尽可能坚持下去。

有人能给我个提示吗?我会非常感激的。谢谢!

代码语言:javascript
复制
/* An alternate organization uses getline to read an entire input line;
this makes getch and ungetch unnecessary. Revise the calculator to use
this approach. */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>  // for atof()

#define MAXLINE 100  // max size of input
#define MAXOP 100    // max size of operand or operator
#define MAXVAL 100   // maximum depth of val stack
#define NUMBER '0'   // signal that a number was found

int getop(char[]);
int getl(char[], int);
void push(double);
double pop(void);

int li = 0;          // input line index
char line[MAXLINE];  // one input line

int sp = 0;          // next free stack position
double val[MAXVAL];  // value stack

/* reverse Polish calculator */
int main(void) {
    int type;
    double op2;
    char s[MAXOP];

    while ((type = getop(s)) != EOF) {
        switch (type) {
            case NUMBER:
                push(atof(s));
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() * pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if (op2 != 0.0)
                    push(pop() / op2);
                else
                    printf("Error: Zero Divisor\n");
                break;
            case '\n':
                printf("\t%.8g\n", pop());
                break;
            default:
                printf("Error: Unknown Command %s\n", s);
                break;
        }
    }
    return 0;
}

/* getop: get next operator or numeric operand */
int getop(char s[]) {
    int c, i;

    if (line[li] == '\0') {
        if (getl(line, MAXLINE) == 0)
            return EOF;
        else
            li = 0;
    }
    while ((s[0] = c = line[li++]) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    if (!isdigit(c) && c != '.') return c;  // not a number
    if (isdigit(c))                         // collect integer part
        while (isdigit(s[++i] = c = line[li++]))
            ;
    if (c == '.')
        while (isdigit(s[++i] = c = line[li++]))
            ;
    s[i] = '\0';
    li--;
    return NUMBER;
}

/* getl: get line into s, return length */
int getl(char s[], int lim) {
    int c, i;

    i = 0;
    while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
        s[i++] = c;
    if (c == '\n')
        s[i++] = c;
    s[i] = '\0';
    return i;
}

/* push: push f onto value stack */
void push(double f) {
    if (sp < MAXVAL)
        val[sp++] = f;
    else
        printf("Error: Stack full, can't push %g\n", f);
}

/* pop: pop and return top value from stack */
double pop(void) {
    if (sp > 0)
        return val[--sp];
    else {
        printf("Error: Stack empty\n");
        return 0.0;
    }
}

多亏了MikeCAT,这个程序现在已经完全开始工作了。在这里,源代码:

代码语言:javascript
复制
/* An alternate organization uses getline to read an entire input line;
this makes getch and ungetch unnecessary. Revise the calculator to use
this approach. */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>  // for atof()

#define MAXLINE 100  // max size of input
#define MAXOP 100    // max size of operand or operator
#define MAXVAL 100   // maximum depth of val stack
#define NUMBER '0'   // signal that a number was found

int getop(char[]);
int getl(char[], int);
void push(double);
double pop(void);

int li = 0;          // input line index
char line[MAXLINE];  // one input line

int sp = 0;          // next free stack position
double val[MAXVAL];  // value stack

/* reverse Polish calculator */
int main(void) {
    int type;
    double op2;
    char s[MAXOP];

    while ((type = getop(s)) != EOF) {
        switch (type) {
            case NUMBER:
                push(atof(s));
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() * pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if (op2 != 0.0)
                    push(pop() / op2);
                else
                    printf("Error: Zero Divisor\n");
                break;
            case '\n':
                printf("\t%.8g\n", pop());
                break;
            default:
                printf("Error: Unknown Command %s\n", s);
                break;
        }
    }
    return 0;
}

/* getop: get next operator or numeric operand */
int getop(char s[]) {
    int c, i;

    if (line[li] == '\0') {
        if (getl(line, MAXLINE) == 0)
            return EOF;
        else
            li = 0;
    }
    while ((s[0] = c = line[li++]) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    if (!isdigit(c) && c != '.') return c;  // not a number
    i = 0;
    if (isdigit(c))  // collect integer part
        while (isdigit(s[++i] = c = line[li++]))
            ;
    if (c == '.')
        while (isdigit(s[++i] = c = line[li++]))
            ;
    s[i] = '\0';
    li--;
    return NUMBER;
}

/* getl: get line into s, return length */
int getl(char s[], int lim) {
    int c, i;

    i = 0;
    while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
        s[i++] = c;
    if (c == '\n')
        s[i++] = c;
    s[i] = '\0';
    return i;
}

/* push: push f onto value stack */
void push(double f) {
    if (sp < MAXVAL)
        val[sp++] = f;
    else
        printf("Error: Stack full, can't push %g\n", f);
}

/* pop: pop and return top value from stack */
double pop(void) {
    if (sp > 0)
        return val[--sp];
    else {
        printf("Error: Stack empty\n");
        return 0.0;
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-21 14:11:09

在行中使用未初始化的非静态局部变量i的不确定值。

代码语言:javascript
复制
while (isdigit(s[++i] = c = line[li++]))

函数getop。在使用i值之前,必须初始化它。

您应该学会使用调试器来确定程序在哪一行失败,以及不需要哪个变量的值。例如,我以这种方式使用GDB:

代码语言:javascript
复制
D:\Temp>gcc -Wall -Wextra -g3 -o a a.c

D:\Temp>gdb a
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\Temp\a.exe...done.
(gdb) r
Starting program: D:\Temp/a.exe
[New Thread 9144.0x6d24]
[New Thread 9144.0x2f1c]
22+22-/

Program received signal SIGSEGV, Segmentation fault.
0x004015fe in getop (s=0x61feac "2") at a.c:79
79              while (isdigit(s[++i] = c = line[li++]))
(gdb) p s
$1 = 0x61feac "2"
(gdb) p line
$2 = "22+22-/\n", '\000' <repeats 91 times>
(gdb) p i
$3 = 14027921
(gdb) p li
$4 = 2
(gdb)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73067667

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档