C程序设计基础Lab09

内容纲要

1036. atof

Extend atof to handle scientific notation of the form 123.45e-6 where a floating-point number may be followed by e or E and an optionally signed exponent.

Write a program to enter a string and call atof.

See also Exercise 4-2 in the textbook.

#include <stdio.h>

/***************************************************************/
/*                                                             */
/*  DON'T MODIFY main function ANYWAY!                         */
/*                                                             */
/***************************************************************/

double atof(char s[]) {
    // TODO: your function definition
}

#define MAXLINE 80  /* maximum input line length */

int main() {
    char s[MAXLINE];
    scanf("%s", s);
    printf("%f\n", atof(s));
}

样例

Input
123.45e-6
Output
0.000123

题解:

本题的数据卡得非常死,并且题面也没有给出很明确的数据提示,以至于会出现1e+03这样的妖孽数据。一个个特判吧。

代码:

#include <stdio.h>

double atof(char s[])
{
    int i = 0;
    int foundE = 0;
    int foundDot = 0;

    //特判是否存在'e'和'.'
    while (s[i] != '\0'){
        if (s[i] == 'e' || s[i] == 'E') foundE = 1;
        if (s[i] == '.') foundDot = 1;
        i++;
    }

    double integerPart = 0;
    int index = 0;int temp = 0;int sig = 1;
    i = 0;

    //特判负数情况
    if (s[i] == '-'){sig = -1;i++;}
    while (!foundDot && s[i] != 'e' && s[i] != 'E' && s[i] != '\0'){integerPart = integerPart * 10 + (int)s[i] - 48;i++;}
    while (foundDot && s[i] != '.'){integerPart = 10 * integerPart + (int)s[i] - 48;i++;}
    if(foundDot)i++;
    while ((foundE && s[i] != 'e' && s[i] != 'E' && s[i] != '\0') || (!foundE && s[i] != '\0')){integerPart = 10 * integerPart + (int)s[i] - 48;i++;index--;}
    if (foundE && s[++i] == '-'){
        i++;
        while (s[i] != '\0'){temp = 10 * temp + (int)s[i] - 48;i++;}
        index -= temp;
    }
    else if (foundE){
        while (s[i] == 0 || s[i] == '+') i++;
        while (s[i] != '\0'){temp = 10 * temp + (int)s[i] - 48;i++;}
        index += temp;
    }
    if (index > 0){for (int i = 0; i < index; i++) integerPart *= 10;}
    else{for (int i = 0; i < -1 * index; i++) integerPart /= 10;}
    if (sig > 0) return integerPart;
    else return -1 * integerPart;
}

#define MAXLINE 80

int main()
{
    char s[MAXLINE];
    scanf("%s", s);
    printf("%f\n", atof(s));
    return 0;
}

1037. RPN calculator

Extend the program for reverse polish notation calculator to add the modulus (%) operator and provisions for negative numbers.

See also Exercise 4-3 in the textbook.

样例

Input
6 7 * 5 -
Output
37

题解

计算逆波兰表达式最常用也是最好用的方法,就是使用“栈”这一数据结构。

算法描述:

1) 碰到数字,入栈; 2) 碰到运算符,弹出两次数字,计算得到的答案入栈; 3) 反复执行上面两个步骤; 4) 弹出最终结果。

注意事项:

本题需要同时读入数字和符号,同时,因为空格符号的存在,如果对数据类型的理解不够深入,建议采用getchar()进行读入。如果使用scanf("%s",s)会导致读到第一个空格处就停止读入了。 PS:但是或许可以反复执行scanf,对每一个字符串分别处理之后再进行操作?

代码

代码描述:

我写了一个可以计算多位整数的程序,或许数据要求只要计算个位数就行了,但题面并没有写清楚。

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

typedef struct Stack{
    int num[1001];
    int top;
    int size;
}S;

void push(S* s, int num){s->num[s->top] = num; s->top--; s->size++;}

int pop(S* s){if(s->size) {s->size--; return s->num[++s->top];}}

long long calc(S* s, char a[]){
    for(int i = 0; i < strlen(a); i++){
        int sig = 1;int num = 0;int isNum = 0;
        if(a[i] == '-'){
            if(a[i + 1] != ' ' && a[i + 1] != '\0'){sig = -1;i++;}
            else{
                int temp1 = pop(s);
                int temp2 = pop(s);
                push(s, temp2-temp1);
            }
        }
        while(a[i] <= '9' && a[i] >= '0'){
            isNum = 1;
            num = num*10 + a[i]-48;
            i++;
        }
        if(isNum) push(s, num*sig);
        if(a[i] == '+'){
            int temp1 = pop(s);
            int temp2 = pop(s);
            push(s, temp2+temp1);
        }
        if(a[i] == '*'){
            int temp1 = pop(s);
            int temp2 = pop(s);
            push(s, temp2*temp1);            
        }
        if(a[i] == '/'){
            int temp1 = pop(s);
            int temp2 = pop(s);
            push(s, temp2/temp1);            
        }
        if(a[i] == '%'){
            int temp1 = pop(s);
            int temp2 = pop(s);
            push(s, temp2%temp1);            
        }
    }
    return(pop(s));
}

int main(){
    S* s = (S*)malloc(sizeof(S));
    s->top = 1000;
    s->size = 0;
    char a[1001] = {'\0'};
    char ch;
    int i = 0;
    while((ch = getchar())!='\n')a[i++] = ch;
    printf("%lld\n", calc(s,a));
    return 0;
}

1038. reverse string

Write a recursive version of the function reverse(s), which reverses the string in place.

Write a program to enter a string and call reverse(s).

See also Exercise 4-13 in the textbook

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

/***************************************************************/
/*                                                             */
/*  DON'T MODIFY main function ANYWAY!                         */
/*                                                             */
/***************************************************************/

void reverse(char s[]) {
    // TODO: your function definition
}

#define MAXLINE 80  /* maximum input line length */

int main() {
    char s[MAXLINE];
    scanf("%s", s);
    //********** reverse is called here *************
    reverse(s);
    //**************************************************
    printf("%s", s);
}

样例

Input
ecnu
Output
unce

题解

这题要求是用递归完成原地倒序,但只给用一个参数,似乎普通的递归需要至少两个参数?三个就更好写了。但是没办法,题目要求如此。 我这里是开了全局变量,用指针移位的操作来完成递归,看不懂的话可以了解一下什么是指针,指针和数组有什么关系。

代码

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

char *p;
int flag = 1;
void reverse(char s[]){
    char temp;
    if(flag){p = s+strlen(s)-1; flag = 0;}
    if(s==p) return;
    else{
        temp = *s;*s = *p;*p = temp;p--;
        if(s==p) return;
        reverse(s+1);
    }
}

#define MAXLINE 80

int main()
{
    char s[MAXLINE];
    scanf("%s",s);
    reverse(s);
    printf("%s",s);
    return 0;
}

《C程序设计基础Lab09》有5条留言

  1. 的确可以scanf(“%s”,s),每次读一个东西,再写一个判断是否是数字的函数(现在看来只需要判断是不是操作符?),是数字入栈(标准库有atoi函数将字符串转化为对应的int),是运算符进行出栈入栈操作

    回复
  2. 我的1038(非指针)
    void reverse(char s[]) {
    char media;
    static int cnt = 0;
    int i = 0 + cnt;
    int j = strlen(s) – 1 – cnt;
    media = s[i];
    s[i] = s[j];
    s[j] = media;

    cnt ++;

    if (cnt < strlen(s) / 2) reverse(s);
    }

    回复

留下评论