0

Four digit numbers stored in a file are written in ASCII and separated by "Space". How do I read them as Integers?

Example file:

53545153 49575150 56485654 53565257 52555756 51534850 56575356 56505055 55525453 

Here is what I tried:

ifstream infile("afile2.txt");
if (infile.is_open()) 
{
    string str2;
    char c;
    while (!infile.eof())
    {
        getline(infile, str2, ' ');

        for (std::string::iterator it = str2.begin(); it != str2.end(); ++it)
            cout << (char)*it;
        cout << " ";


    }
}
infile.close();

In the above code (char)*it is picking only first digit but ASCII number start at 2 digit number i.e. 48.

Shwabster
  • 482
  • 1
  • 12
  • 26
kamalzai
  • 3
  • 2
  • you can use `int x; infile >> x;` – fas Oct 24 '19 at 16:22
  • 2
    Related: [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – Algirdas Preidžius Oct 24 '19 at 16:27
  • Your question is unclear and confusing people - or at least me. Is your goal to read numbers that are represented in ascii in a file into integer values in your program as your title and the beginning of your post indicate, or to read in such numbers preserving their ascii representation (not converting them to int values) and outputting the ascii value of their decimal digits in decimal as your code and end of your post suggests? – Avi Berger Oct 24 '19 at 16:45
  • 1
    Combining OP's comments with the example data shows that the input is text (probably ASCII) encoding of the hexadecimal digits in the ASCII values of the digits in the (decimal?) string representation of the number. That is, the number `5635` has become `"5635"` which is `{ '5', '6', '3', '5', NUL }` which is `(char[]){ 0x53, 0x54, 0x51, 0x53, 0 }` and finally "53545153" – Ben Voigt Oct 24 '19 at 16:47
  • @BenVoigt Good catch that makes things a lot clearer, but I think it is the ASCII encoding of the decimal ( not hex ) digits of the ASCII values ... – Avi Berger Oct 24 '19 at 16:52
  • 1
    @Avi: oops, you're right. `'5'` is `0x35` is `53`. Remove every `0x` from my earlier comment. It's also very bad, because while the hexadecimal representation of a `char` is always two nibbles, the decimal representation varies in length (although digits' ASCII values are all two decimal digits) – Ben Voigt Oct 24 '19 at 16:53
  • @avi my goal is to read numbers that are represented in ASCII(decimal) in a file, into integer(or char) values in my program, Hope that clears it. – kamalzai Oct 24 '19 at 16:57
  • @kamalzai It would help if you added what the correct iterpretation of `"53545153"` would be to your question. Is `"53"` supposed to be converted to an integer `53` or a n ASCII `'5'` or ... something else? – Ted Lyngmo Oct 24 '19 at 17:13
  • 1) If you looked at your file in a text editor (e.g. Windows' Notepad) or printed it out, would you see 53545153 or 5635? – Avi Berger Oct 24 '19 at 17:44
  • @Ted 53545153 should be equal to 5635 – kamalzai Oct 24 '19 at 17:44
  • (cont) 2) Do you want to use the number in your program as a) a numeric value that you might be doing arithmetic on; b) a text representation that you will be using only/primarily for storage and output; c) a custom representation that you will be using to simulate decimal arithmetic even though computer arithmetic is generally done in binary; or d) something else? – Avi Berger Oct 24 '19 at 17:44
  • @AviBerger in text file it is stored as 53545153 but i need it as 5635 to perform some calculation on. – kamalzai Oct 24 '19 at 17:46
  • That clarifies things. You will have to read in the string and write the code to reinterpret it to a numeric value piece by piece. I can't help you more now - I have to leave. – Avi Berger Oct 24 '19 at 17:59

2 Answers2

0

Four digit numbers stored in a file are written in ASCII and separated by "Space", How do I read them as Integers. Example file: 53545153 49575150 56485654 53565257 52555756 51534850 56575356 56505055 55525453

Those look like 8 digit numbers.

To read a space separated number from a file simple use operator>> from a stream to an integer.

int value;
if (stream >> value) {
    // Successfully read a number.
}

If you want to read all the values from a file. You can use a loop:

int value;
while (stream >> value) {
    // Enter the body of the loop each time a number is read.
}

Note: Your usage of eof() is bad practice:

while (!infile.eof()) {
    // If you enter here the file may be open and readable
    // BUT there may be no data left in the file and thus the next
    // attempt to read will fail if there is no data.
    //
    // This happens because the last successful read will read up-to
    // but not past the EOF. So you have read all the data but not read
    // past the EOF so eof() will return false.
}

More Info

So how do we read 2 digit numbers from groups of 8 digit larger numbers that are space separated.

Well we want to make it work like standard stream readding so we still want to use the operator>> to read from the stream. But none of the built in types read two digit numbers. So we need to define our own class that will read a two digit number.

 struct TwoDigit
 {
     int    value;                  // store the result here
     operator int() {return value;} // Convert TwoDigit to integer
 };
 std::ostream& operator<<(std::ostream& str, TwoDigit const& data) {
     str << data.value; // You can do something more complicated
                        // for printing but its not the current question
                        // so I am just going to dump the value out.
 }
 std::istream& operator>>(std::istream& str, TwoDigit& data) {
     char c1 = 'X';
     char c2 = 'Y';

     if (str >> c1 >> c2) {
         // successfully read two characters from the stream.
         // Note >> automatically drops white space (space return etc)
         // so we don't need to worry about that.

         if (('0' <= c1 && c1 <= '9') && ('0' <= c2 && c2 <= '9')) {
              // We have all good data.
              // So let us update the vale.
              data.value = ((c1 - '0') * 10) + (c2 - '0');
         }
         else {
              // We have bad data read from the stream.
              // So lets mark the stream as bad;
              str.clear(std::ios::failbit);
         }
    }
    return str;
}

Now in your code you can simply read

 TwoDigit  data;
 if (stream >> data) {
      // Read a single two digit value correctly.
 }

 // or for a loop:
 while(stream >> data) {
      // Keep reading data from the stream.
      // Each read will consume two digits.
 }

 // or if you want to fill a vector from a stream.
 std::vector<TwoDigit> data(std::istream_iterator<TwoDigit>(stream),
                            std::istream_iterator<TwoDigit>());

 // You can even create a vector of int just as easily.
 // Because the TwoDigit has an `operator int()` to convert to int.
 std::vector<int>      data(std::istream_iterator<TwoDigit>(stream),
                            std::istream_iterator<TwoDigit>());
Martin York
  • 234,851
  • 74
  • 306
  • 532
0

This could be an approach if I've understood the problem correctly.

#include <cmath>
#include <iostream>
#include <string>
#include <vector>

std::vector<int> conv(std::istream& is) {
    std::vector<int> retval;

    std::string group;
    while(is >> group) { // read "53545153" for example
        int mul =
            static_cast<int>(std::pow(10, (group.size() / 2) - 1)); // start at 1000

        int res = 0;

        for(size_t i = 0; i < group.size(); i += 2, mul /= 10) {
            // convert "53" to dec ASCII char 53 ('5') and then to an int 5 and
            // multiply by 1000 (mul)
            res += (((group[i] - '0') * 10 + (group[i + 1] - '0')) - '0') * mul;
        }
        retval.emplace_back(res); // store
    }
    return retval;
}

Testing the function:

#include <sstream>

int main() {
    std::istringstream is(
        "53545153 49575150 56485654 53565257 52555756 51534850 56575356 56505055 55525453");

    auto r = conv(is);

    for(int x : r) {
        std::cout << x << "\n";
    }
}

Output:

5635
1932
8086
5849
4798
3502
8958
8227
7465
Ted Lyngmo
  • 37,764
  • 5
  • 23
  • 50