Detalhes de uso comum do "diário de 6.3 notas de aprendizado do Algorithm Note"

6.3 Explicação detalhada do uso comum de string

ID do Concurso de Codeup: 100000598

Pergunta A: Processamento de sequência (resposta incorreta causada pela pergunta bancária da pergunta)

Título Descrição
Leia duas cadeias de caracteres.Além dos números, as cadeias de caracteres podem incluir '-', 'E', 'e' e '. ', O resultado da saída após a adição, se for do tipo de ponto flutuante, precisará ser expresso em notação científica (até 10 dígitos significativos).
Entrada A
entrada contém vários conjuntos de dados de teste.
Cada grupo de entrada ocupa duas linhas, uma sequência por linha, e os dados de teste garantem que a composição da sequência esteja estritamente de acordo com a descrição no título.
Saída
Produz o resultado da adição de dois números, uma linha para cada grupo de saída.
Entrada de amostra

34.56
2.45e2

Saída de amostra

2.7956e2

Pensamentos
escritos para uma tarde, eu realmente não sei o que está errado, o código AC do ityanger pode de fato AC, mas também há erros (Quando as entradas 1 e 1.245e-2, a saída é 1.1245e0), Não sei onde está o ponto de teste do Codeup.

Adicionado na noite de 2020.4.2 : comprei o banco de testes. A saída do banco de testes original é a operação do salto 0 (Entrada 1 e 1.245e-2, saída 1.1245e0), Bêbado ... Uma das deficiências do meu código é que números inteiros grandes ainda geram notação científica; portanto, o conteúdo do primeiro bloco precisa ser alterado (o primeiro conteúdo atual lida com muitos pontos decimais e gera ciência automaticamente O problema do método de contagem), vou atualizá-lo.

Suplemento 2020.4.2 noites : o código foi atualizado, eu testei, e a saída de dados de todos os bancos de teste está correta (exceto a parte que pula 0, que é um problema com os dados no banco de testes), é claro, por causa de to_string Ambos stringstream e stringstream têm problemas de precisão (representados pelo fato de haver muitos dígitos após o ponto decimal, ambos têm problemas de precisão no momento, mas se você usar notação científica, to_string terá problemas de precisão e o stringstream não), portanto, se você digitar Se o número for muito grande ou muito pequeno, há um problema com a saída convertida to_string ou stringstream.

Você pode dar uma olhada no banco de perguntas do pai do poço (a saída de resposta à esquerda e minha saída à direita):
Insira a descrição da imagem aqui
estas são as duas entradas correspondentes aos dados de saída do cursor (a terceira linha é a saída do meu programa):
Insira a descrição da imagem aqui
minha idéia é definir o tipo duplo Depois de inserir dois números, converta sua soma no tipo de sequência (já que o tipo duplo reconhecerá automaticamente a notação científica para cálculo, portanto, você só precisa operar com o resultado da adição). Existem três casos aqui: are Há muitas casas decimais, o tipo duplo gera automaticamente notação científica, mas a notação científica padrão está com sinal positivo e 0 (como a saída de notação padrão da amostra é 2.7956e + 002), portanto Ele também precisa ser tratado; ② O caso de decimais de saída comuns precisa ser processado para gerar notação científica; ③ Inteiros não são produzidos por notação científica.

Meu segundo caso aqui é modificado para que, se for 10 0, e não seja produzido (como as entradas 1 e 1.245e-2 1.01245 e não 1.01245e0), embora ainda esteja errado ... (Suplemento: Depois de ler a saída do banco de perguntas acima, deve ser necessário enviar e0

Além disso, se você usar a função to_string do C ++ 11, a precisão da conversão será de apenas 6. Se você desejar uma precisão mais alta, precisará usar o stringstream para converter dados em dobro.

Aqui, colocarei o código AC e o meu código, mas não o
observei com cuidado.Se você quiser ver os comentários detalhados, poderá ver esta postagem no blog: problema de processamento da string de codificação Um código 1983

  • Código disponível no CodeupAC
#include<stdio.h>
int main()
{
    char str1[50],str2[50];
    long long s,s1,s2,ans;
    int i,a1,a2,a,b,c,w,flag;
    while(scanf("%s %s",str1,str2)!=EOF){
        s1=s2=flag=b=c=a1=0;
        for(i=0;str1[i];i++){
            if(str1[i]=='-')
                flag=1;
            else if(str1[i]=='.')
                c=1;
            else if(str1[i]=='e'||str1[i]=='E'){
                sscanf(str1+i+1,"%d",&b);
                a1+=b;
                break;
            }
            else{
                s1=s1*10+str1[i]-'0';
                a1-=c;
            }
        }
        if(flag) s1=-s1;
        flag=b=c=a2=0;
        for(i=0;str2[i];i++){
            if(str2[i]=='-')
                flag=1;
            else if(str2[i]=='.')
                c=1;
            else if(str2[i]=='e'||str2[i]=='E'){
                sscanf(str2+i+1,"%d",&b);
                a2+=b;
                break;
            }
            else{
                s2=s2*10+str2[i]-'0';
                a2-=c;
            }
        }
        if(flag) s2=-s2;
        if(a1<a2)
            for(;a1<a2;a2--)
                s2*=10;
        else if(a1>a2)
            for(;a1>a2;a1--)
                s1*=10;
        a=a1;s=s1+s2;
        if(!s){
            printf("0\n");
            continue;
        }
        while(a<0&&s%10==0){
            s/=10;
            a++;
        }
        if(a>=0){
            printf("%lld",s);
            for(i=0;i<a;i++)
                printf("0");
            printf("\n");
            continue;
        }
        flag=0;
        if(s<0){
            s=-s;
            flag=1;
        }
        ans=1;w=0;
        while(ans<=s){
            ans*=10;
            w++;
        }
        if(ans>1){
            ans/=10;
			w--;
        }
        if(flag)
            printf("-");
        printf("%lld",s/ans);
        if(ans>1)
            printf(".%lld",s%ans);
        printf("e%d\n",a+w);
    }
    return 0;
}
  • Meu código (modificado, exceto para a saída de dados da parte skip 0, todas as outras saídas estão corretas)
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<string>
#include<iostream>
#include<iomanip>
#include<sstream>
//#include<fstream> 
using namespace std;
int main(){
	double a, b;
	while(cin>>a>>b){
		stringstream s;//使用stringstream,控制转换为字符串后的有效数字能达到10位 
		s<<setprecision(10)<<a+b;
		string str = s.str();
		//////判断是否是大整数//////
		bool integer = false;
		//判断是否是整数,因为stringstream会自动科学计数法
		//然而to_string虽然能完整保存整数,但是又有精度问题(小数点后一定只有6位,而且小数点位数过多to_string直接是0)
		string sss = to_string(a+b);
		int PointPosition = sss.find(".");//标记小数点的位置
		int cntzero = 0;//数0的个数 
		for(int i=PointPosition+1;i<sss.length();i++) if(sss[i]=='0') cntzero++;
		if(cntzero==sss.length()-1-PointPosition && sss[0]!='0' || str[0]=='0' && str.length()==1){
		//保证不是因为精度问题而输出0.000000的情况,但又不能把本来就是0的情况排除
			integer = true;//如果小数点之后全是0,就是大整数
			sss.erase(PointPosition, sss.length()-PointPosition);//删除小数点和后面的0 
		}
		///////////////////////////
		//ofstream ofs;
		//ofs.open("C:\\Users\\kykj\\Desktop\\aaaa.txt", ios::out|ios::app);
		string temp = "e";//用于处理e及后面的数字 
		if(str.find("e") != string::npos && integer==false){//如果自动输出了科学计数法,且是小数 
			int pos = str.find("e");//记录e的位置
			int pos2 = 0;//记录e后面第一个非0数的位置
			bool flag = false;//记录是否是负号 
			string tmp;
			for(int i=pos+1;i<str.length();i++){
				if(str[i]=='-'){
					flag = true;
					continue;
				}
				if(str[i]!='0'){
					pos2 = i;
					break;
				}
			}
			if(flag==true) str.erase(pos+2, pos2-(pos+2));
			else str.erase(pos+1,pos2-(pos+1));
			//ofs<<str<<endl;
			cout<<str<<endl;
		}
		else if(str.find(".") != string::npos && integer==false){//如果相加之后是浮点型
			bool flag = false;//默认不是负数
			bool dot = false;
			int pos = str.find(".");//记录小数点所在的位置 
			int ff = 0;//记录第一个非0数字出现的位置 
			str.erase(str.begin()+pos);//删除小数点
			if(str[0]=='-'){
				flag = true;//如果true,表明结果是个负数
				str.erase(str.begin());//把负号先删了 
			} 
			for(int i=0;i<str.length();i++){
				if(str[i]!='0'){
					ff = i;
					str.erase(0, i);//删除前面多余的0 
					break;
				}
			}
			if(str.length()==1) dot = true;//只有一位有效数字 
			if(dot==false) str.insert(1, ".");//如果不止一位有效数字,则直接在第一个数后面插入小数点
			if(flag==true){
				ff = ff+1+1;//如果是负数,ff加上原本删去的负号和小数点
				str.insert(0, "-");//放回负号 
			}
			else ff = ff+1;//如果是非负数,则只加上原来的小数点即可 
			if(pos-ff>=0){
				string num = to_string(pos-ff);
				temp += num;
				str += temp;
			}
			else{
				temp += "-";
				string num = to_string(abs(pos-ff));
				temp += num;
				str += temp;
			}
			//ofs<<str<<endl;
			cout<<str<<endl;
		}
		else{//如果不是浮点型
			//ofs<<sss<<endl;
			cout<<sss<<endl;//这里输出to_string后的sss 
		}
		//ofs.close();
	}
	return 0;
}

Sumário

As seqüências de caracteres C ++ são realmente muito convenientes de usar, especialmente as operações de inserção e exclusão (sentindo que essas duas são as mais usadas), o que é muito mais conveniente que as matrizes de caracteres C, e também existem funções como to_string no C ++ 11. Converta o tipo numérico para o tipo de string diretamente, mas parece que o tipo de string para o tipo numérico não possui função encapsulada, só pode usar o atoi ou o método stringstream? (Provavelmente) O
método detalhado pode ser visto na seguinte postagem no blog:
C ++ string to int

Publicado 54 artigos originais · ganhou 27 · visualizações 4988

Acho que você gosta

Origin blog.csdn.net/weixin_42257812/article/details/105273742
Recomendado
Clasificación