C + + Write PTA BaseLevel topic - topic 1029

First, give my all pass answer

#include <iostream>
#include <cstring>
using namespace std;
int main(){
    char str_1[81];
    char str_2[81];
    char ret[80] = "\0";
    int num = 0; //Cumulative number of missing characters
    int _num = 0; //Number of bad keys
    cin >> str_1 >> str_2;
    for(int i = 0;str_1[i] != 0;i++){
        if(str_1[i] != str_2[i - num]){
            int chr = str_1[i];
            if(chr >= 'a'){
                chr += 'A' - 'a';
            }
            if(strchr(ret, chr) == nullptr){
                ret[_num++] = chr;
            }
            num++;
        }
    }
    for(int i = 0;i < _num;i++){
        cout << ret[i];
    }
}

Solution process

        Let's look at the topic first. The default scene of the topic is that there are bad keys on the keyboard, resulting in no input after one or more keys are knocked. The title gives two strings. The first represents the text that should be input when hitting the normal keyboard, and the second represents the actual input text. It is required to find out the bad key by comparing the differences between the two strings.

         Input limit: two strings are not empty and contain no more than 80 characters. They are only composed of letters A-Z (including upper and lower case), numbers 0-9, and underscores  _ (stands for space) composition, the title guarantees that there must be a bad key.

        Output limit: bad keys are output in one line, and English letters are only output in uppercase (it is reasonable that after all, there will be no keys a and a on the keyboard, but most keyboards use uppercase). Each bad key is output only once without space separation.

        Although there are various compilation problems and various logic bugs in the process of writing code, the idea of the solution is still very clear. First, define two character arrays of length 81 to store the input two strings respectively. Then, the for statement compares characters one by one, and the variable num stores the missing characters encountered as the subscript offset of the second string. Simply answer why such a subscript offset is required. For example, "This" and "Tis", when the loop variable i is 1, str_1 points to the letter H and str_2 points to the letter i. obviously, h is a bad key. Because the second string is missing characters, the position pointed to by the second string in the next round of comparison should not change. Otherwise, the first string will point to the letter i and the second string will point to the letter s, resulting in the parent i being regarded as a bad key. The correct situation is that the subscript of the first string is + 1, The subscript of the second string does not move, so we add a negative offset num to the subscript of the second string, num + 1 every time we encounter a bad key. Here we have realized the identification of bad keys. In order to realize the output of bad keys, we need to use a character array RET to store bad keys. According to the requirements of the topic, each bad key is output only once, so we can't output bad keys immediately every time. In order to prevent repetition, we need to remember the bad keys we encounter. Every time a bad key is encountered, if   If the key does not appear in RET, the key is stored in ret. Finally, simply output the result - character array RET character by character.

Various errors in problem solving

        First of all, the first time the answer is wrong, the problem is still quite big. The first four test points have passed, if there is no fifth test point. It's useless here_ Num is used alone as the subscript of ret, but directly   num . At that time, I thought that ret has been initialized, and all elements except ret[0] are \ 0. In this way, although repeated bad keys are not stored in ret, Num is increasing, which is equivalent to skipping several subscripts for assignment in ret, but \ 0 does not output any characters. Therefore, I thought it was feasible at that time. It was found that after the first encounter with \ 0, the subsequent elements could not be output, and note that I used the method of character by character output here, so what caused the problem that the subsequent elements could not be output after the encounter with \ 0 was still not found.

#include <iostream>
#include <cstring>
using namespace std;
int main(){
    char str_1[81];
    char str_2[81];
    char ret[80] = "0";
    int num = 0;
    cin >> str_1 >> str_2;
    for(int i = 0;str_1[i] != 0;i++){
        if(str_1[i] != str_2[i - num]){
            if(strchr(ret, str_1[i]) == nullptr)
                ret[num] = str_1[i];
            num++;
        }
    }
    for(int i = 0;i < num;i++){
        if(ret[i] >= 'a'){
            ret[i] += 'A' - 'a';
        }
        cout << ret[i];
    }
}

          Then there is the second answer error. The wrong version is closer to the correct answer than the first answer error, but it only passed two test points with a score of 1. The score is terrible compared with the first time, which reminds me of the online joke: "the software can run all by this BUG". Yes, the reason why the first solution can pass the four test points is that the subsequent elements cannot be output after encountering \ 0. This problem masks a logical loophole, that is, whether there are duplicates when encountering bad keys compared with the bad keys memorized before. In fact, the case of the same letter is ignored here. Because the conversion from lowercase to uppercase is not done when saving ret, Instead, you choose to do it in the output process, so a may be stored in RET, even though a already exists in ret.

#include <iostream>
#include <cstring>
using namespace std;
int main(){
    char str_1[81];
    char str_2[81];
    char ret[80] = "\0";
    int num = 0; //Cumulative number of missing characters
    int _num = 0; //Number of bad keys
    cin >> str_1 >> str_2;
    for(int i = 0;str_1[i] != 0;i++){
        if(str_1[i] != str_2[i - num]){
            if(strchr(ret, str_1[i]) == nullptr){
                ret[_num++] = str_1[i];
            }
            num++;
        }
    }
    for(int i = 0;i < _num;i++){
        if(ret[i] >= 'a'){
            ret[i] += 'A' - 'a';
        }
        cout << ret[i];
    }
}

summary

        Hoo ~, the code is almost finished. The time of code words is almost as fast as that of looking for problems in a computer without a compiler yesterday. Although it is not a complex thing to write an article for the first time, it is quite challenging to explain the logic bit by bit. We should consider the words and sentences, express clearly, and recall the details in the title, And this process is more interesting than looking for bugs.

        Generally speaking, there are two errors when doing this problem: the first is to allow \ 0 to be output, which leads to the error of unknown principle - all elements after \ 0 cannot be output; The second is the logic problem. Instead of saving after case conversion when memorizing bad keys, it chooses to output after conversion when outputting, resulting in repeated letter output.

Tags: C++

Posted on Mon, 27 Sep 2021 01:56:05 -0400 by mkoga