Pregunta

I am writing a program that is supposed to take a ZIP code (represented by an int) and parse it into its POSTNET equivalent (represented by a C++ std::string) and vice versa. The algorithm to convert a POSTNET code into a ZIP code works fine, but the algorithm to convert a ZIP code into POSTNET does not work right. I have isolated the cause of the problem to be the getSequence() function; is there any problem there?

Here's my code:

string ZipCode::getBarCode()
{
    string zipCode = itoa(this->zipCode, new char[5], 10);
    string sequences[5];
    for(int i = 0; i < 5; ++i)
        sequences[i] = getSequence(zipCode[i] - '0');
    string toReturn = "1";
    for(string &sequence : sequences)
        toReturn += sequence;
    return toReturn + "1";
}

string ZipCode::getSequence(int digit)
{
    if(digit == 0)
        return "11000";
    string toReturn = "00000";
    int values[4] = {7, 4, 2, 1};
    for(int i = 0; i < 4; ++i)
        if(digit < values[i])
        {
            toReturn = toReturn.replace(i, 1, "1");
            digit -= values[i];
        }
    if(containsOnlyOne1(toReturn))
        toReturn = toReturn.replace(4, 1, "1");
    return toReturn;
}

bool ZipCode::containsOnlyOne1(std::string str)
{
    int instancesOfOne = 0;
    for(int i = 0; i < str.length(); ++i)
        if(str[i] == '1')
            instancesOfOne++;
    return instancesOfOne == 1;
}

Additionally, here are some test cases:

ZIP Code        Expected Output                    Actual Output
24060           100101010011100001100110001        111110111101100011110110001
92064           110100001011100001100010011        100000111101100011110111101
11518           100011000110101000011100101        111110111101111011110000001

Not sure if this helps, but I am a Java programmer learning C++ for the first time.

¿Fue útil?

Solución

I think your problem is here:

if(digit < values[i])

That should be >= not <.

The biggest hint is what comes next - you subtract values[i] from digit, which will result in a negative number if the < condition is true. That doesn't seem at all like what you want.

Otros consejos

For readability's sake, it may be best to just hard-code the POSTNET strings for the digits 0 through 9 (perhaps in a static variable in your ZipCode class) and just perform a lookup for the five digits in the zip code. A minimal example is:

#include <array>
#include <iostream>
#include <string>

std::string zip_to_postnet(const std::string& zip)
{
    std::array<std::string,10> lookup{"11000", "00011", "00101", "00110",
                                      "01001", "01010", "01100", "10001",
                                      "10010", "10100"};

    std::string result = "1";

    for (unsigned int i = 0; i < 5; ++i)
    {
        int digit = zip[i] - '0';
        result += lookup[digit];
    }

    return result + "1";
}

int main()
{
    std::cout << zip_to_postnet("24060") << std::endl;
    std::cout << zip_to_postnet("92064") << std::endl;
    std::cout << zip_to_postnet("11518") << std::endl;

    return 0;
}

A demo passes your three test cases. (This uses C++11's std::array, but you could use a normal array.) If you are intent on retaining your original algorithm, please say so.

EDIT: PS, since I see you are using C++11, just a quick note that it is preferable to use something like std::to_string instead of itoa if trying to convert an integer (e.g. a zip code) to string. (See line 3 of your question's code.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top