这道题真是扒掉我一层皮,还是有部分问题,大多数案例应该可以通过!c/c++不像java的string那么方便,加之vc6.0实在太难用,只能达到这个效果了!

一、收获

1.size_t pos1 = s.find(";",index);

每次使用find函数时,不要忘记第二个参数(开始查询下标),这个每一轮查询都不一样,这个是查完整个字符串的保证

size_t,本质是unsigned int,用typedef起了个名

2.s.substr(pos1,pos2-pos1);

第一个参数是起始位置,第二个参数是长度

3.C++的char数组与string对象相互转化

char t[100];
strcpy(t, s2.c_str());

由于strtok方法参数只能是char[]和char*必须转化

参考:https://www.cnblogs.com/fnlingnzb-learner/p/6369234.html

4.int和string转化

int len = strtol((v1[i].substr(t1+1,t2-t1-1)).c_str(),NULL,0);//字符串转为long int类型

由于vc6.0实在太难用,只支持86%的C++,stoi等函数都不能用,只能用这个凑合。java多简单。

5.char转为string

这个,找不到好办法??

6.vc6.0的一些问题,见:https://www.cnblogs.com/sybil-hxl/p/10468571.html

7.剩下的一些算法细节,代码中都有注释,就不在此处写了!

二、题目

/*
二,查找未定义变量
输入二个C语言语句u,第一句为正常的C语言变量定义语句,符合C语言语法要求,变量间可以有多个空格,
包括数组、指针定义等。第二句为变量运算语句,要求输出第二个C语言语句中未定义的变量。
Example:
int x12,y=1,num_stu=89,a[30],*p;
Sum=num+x12*y;
Output:
Sum num
*/

2.思路

(1)输入第一行s1,先把数据类型删除,然后删除c的内容,最后用sep1分隔,得到所有已定义变量名存储到v1中

(2)输入第二行s2,从s2中删除空格以及v1中定义的变量

这里数组定义处理那块费了很大的劲!

(3)把删除完已定义变量的s2进行多符号分隔

方法一:采用C语言的strtok方法

方法二:split2方法,即能够被多个符号分隔

(4)输出未定义的变量名

(5)17_2.txt内容可以是:

int x12,y=1,num_stu=89,a[30],*p;
Sum=num+x12*y-a[30]+a[20]*a[31];

int x12,y=1,num_stu=89,a[30],*p;
Sum=num+x12*y-a[30]+a[20]+z;

3.代码

注释掉的代码暂时没用,也不一定能跑出来,防止以后用得着,先留着

/*
#ifdef WIN32
#pragma warning (disable: 4514 4786)
#endif
*/

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <stdlib.h>
using namespace std;

void delStr(string& s,string& str){//删除字符串中的子串,这一个可以顶下面好几个方法了!
    int pos = 0;
    if(!s.empty()){
        while((pos = s.find(str,pos)) != string::npos){
            s.erase(pos,str.length());
        }
    }
}
/*
void delChar(string& s,string& c){
    int n = c.length();
    cout<<n<<endl;
    for(int i=0;i<n;i++){
        string tmp(c[i],1);//这是临时变量,地址就没啦!!!!!
        
        cout<<"========="<<tmp<<"========="<<endl;
        delStr(s,tmp);//直接调用上面的方法,省劲!!
    }
}*/

/*
//暂时不用
void deletChar1(string& s,char c[]){//去掉字符串中的几个字符,空格和*(用于指针定义)。其实最好用regex??
    int n = sizeof(c)/sizeof(char);
    for(int i=0;i<n;i++){
        iterator tmp = find(s.begin(),s.end(),c[i]);
        while(tmp!=s.end()){
            auto x = s.erase(tmp);
            tmp = find(x,s.end(),c[i]);
        }
    }
}
*/

/*
void trim(string& s){//暂时不用
    //去掉头和尾的空格
    if(!s.empty()){
        s.erase(0,s.find_first_not_of(" "));
        s.erase(s.find_last_not_of(" ")+1);//别忘记+1
    }
    //去掉字符串中间的所有空格
    int index=0;
    if(!s.empty){
        while((index = s.find(" ",index)) != npos){//每次使用find函数时,不要忘记第二个参数,这个是查完整个字符串的保证
            s.erase(index,1);
        }
    }
}
*/

void delValue(string& s){//删除变量赋的值
    size_t p = s.find("=");
    if(p != string::npos){
        //if(( p = s.find("=",p) ) == string::npos){//如果只有一个“=”
            s = s.substr(0,p);//直接取等号之前的为变量名。
        //}else{//如果是连续赋值,还真不知道怎么处理???c++好像不支持定义时连续赋值?
            
        //}
    }
}

void split1(vector<string>& v,const string& s,const string& c){//只能根据一个分隔符分隔字符串
    size_t pos1 = 0;
    size_t pos2 = s.find(c);
    while(string::npos != pos2){//表示find找不到
        string tmp = s.substr(pos1,pos2-pos1);//第一个参数是起始位置,第二个参数是长度
        delValue(tmp);//删除变量赋的值
        v.push_back(tmp);
        pos1 = pos2 + c.length();
        pos2 = s.find(c,pos1);//从pos1开始查找,避免没必要的查找和重复
    }
    if(pos1 != s.length()){//最后一个分隔符之后的子串
        v.push_back(s.substr(pos1));
    }
}

void split2(vector<string>& v,const string& s,const string& sep){//可以用多种分隔符分隔字符串
    //1.获得第一个不是分隔符的字母位置f1
    //2.第二个分隔符位置f2
    //3.截取字符串f1-f2
    //4.循环1,2
    int f1=-1,f2=-1;
    int i=0;
    while(i<s.length()){
        //ab;cd;f,ggg,hi
        //;,   f1=0   f2=2
        size_t p1 = sep.find(s[i]);
        if(p1 == string::npos){
            if(f1 == -1){//标志第一个
                f1 = i;    
            }
        }else{
            f2 = i;
        }
        if(f1 != -1 && f2 != -1 && f1<f2){//不能丢f1<f2的条件,否则仍然会出问题
            string tmp = s.substr(f1,f2-f1);
            delValue(tmp);//删除变量赋的值
            v.push_back(tmp);
            f1=f2=-1;//恢复
        }
        //这里没有像split1一样处理最后一个分隔符之后的子串是因为“;”本身就是分隔符,在s2的最后,其后面没有变量了
        i++;
    }
}

void main(){
    freopen("G:/17_2.txt","r",stdin);
    string a[6]={"int","short","long","char","float","double"};
    string b="+-*%/&|!~^><=:?.(),;";//sizeof这种符号就无法使用
    string c[3]={" ","*",";"};
    string sep1 = ",";
    
    while(!cin.eof()){//一共两行,其实没必要这个循环了!,如果有很多测试可以加上循环
        vector<string> v1,v2;//v1存储第一行定义的变量名,v2存储第二行没定义的变量名也就是输出结果
        string s1,s2;
        cin>>s1;
        //一、输入第一行,先把数据类型删除,然后删除c的内容,最后用sep1分隔,得到所有已定义变量名存储到v1中
        for(int i=0;i<6;i++){
            if(s1.compare(a[i]) == 0){
                getline(cin,s1);//应该先把整行全部输入,作为字符串,然后再分析。用","隔开表示两个定义变量。
                for(int j=0;j<3;j++){//把里面的空格,分号,星号删掉
                    delStr(s1,c[j]);
                }
                //split1(v1,s1,sep1);//这两个方法都可以用
                split2(v1,s1,sep1);
            }
        }
        getline(cin,s2);
        //二、第二行处理,从s2中删除空格以及v1中定义的变量
        delStr(s2,c[0]);
        for(i=0;i<v1.size();i++){
            int t1=0,t2=0;
            if((t1=v1[i].find("[")) != string::npos && (t2=v1[i].find("]")) != string::npos){//如果包含数组,对数组变量的处理
                size_t sz;
                int len = strtol((v1[i].substr(t1+1,t2-t1-1)).c_str(),NULL,0);//字符串转为long int类型
                string var1 = v1[i].substr(0,t1);
                int t0=0;
                while((t0=s2.find(var1,t0)) != string::npos){
                    t1=t2=t0;
                    while((t1=s2.find("[",t1)) != string::npos && (t2=s2.find("]",t2)) != string::npos){
                        string index = s2.substr(t1+1,t2-t1-1);
                        //int index = strtol( (s2.substr(t1+1,t2-t1-1)).c_str(),NULL,0 );
                        int index1 = strtol(index.c_str(),NULL,0);
                        if(index1 < len && index1 >=0){
                            delStr(s2,var1+"["+index+"]");
                        }
                        t1=t2=t2+1;
                    }    
                    t0=t0+1;//若没有t0+1,则导致死循环
                }
            }else{//如果不含数组,直接把相应变量删掉就好
                delStr(s2,v1[i]);
            }
        }
        //三、把删除完已定义变量的s2进行多符号分隔
        //方法一:采用C语言的strtok方法
        /*char t[100];
        strcpy(t, s2.c_str());
        const char *sep = "+-*%/&|!=;";
        char *p = strtok(t, sep);
        while(p){
            v2.push_back(p);
            p = strtok(NULL, sep);
        }*/
        //方法二:split2方法,即能够被多个符号分隔
        split2(v2,s2,b);

        //四、输出未定义的变量名
        for(i=0;i<v2.size();i++){
            cout<<v2[i]<<" ";
        }
        cout<<endl;
    }
}

 

posted on 2019-03-06 17:21  西伯尔  阅读(479)  评论(0)    收藏  举报