6

I have a program which reads the contents of a file line by line, stores each line into a vector of strings, and then prints the contents of the vector.

After reading the file data into the vector of strings, I am attempting to convert each line from string into uint32. Each line of the file consists of 32-bit numbers. An example of the input data file (input_file.dat):

31401402
67662718
74620743
54690001
14530874
13263047
84662943
09732679
13839873

I would like to convert each of those strings into uint32_t, for a different program I have written which converts these numbers into ASCII format (the program requires that uint32_t is used for conversion).

My program so far:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

/*
 * Program to iterate through all lines in file and put them in given vector
 *
 */
bool getFileContent(std::string fileName, std::vector<std::string> & vecOfStrs)
{

    // Open the File
    std::ifstream in(fileName.c_str());

    // Check if object is valid
    if(!in)
    {
        std::cerr << "Cannot open the File : "<<fileName<<std::endl;
        return false;
    }

    std::string str;
    // Read the next line from File untill it reaches the end.
    while (std::getline(in, str))
    {
        // Line contains string of length > 0 then save it in vector
        if(str.size() > 0)
            vecOfStrs.push_back(str);
    }
    //Close The File
    in.close();
    return true;
}


int main()
{
    //Store contents in this vector of strings
    std::vector<std::string> vecOfStr;

    // Get the contents of file in a vector
    bool result = getFileContent("input_file.dat", vecOfStr);

    // If above result is true
    if(result)
    {
        // Iterate through the vector contents
        for(std::string & line : vecOfStr)
        {
            //std::cout<<line<<std::endl;      Ignore this print line, it is for debugging only to show that the vector has been correctly filled

            //For each line, convert from string to uint32_t
            std::vector<std::uint32_t>new_variable
            new_variable.assign(vecOfStr.begin(), vecOfStr.end());

        }
    }
}

In my above attempt, in the for loop underneath the comment which reads "// Iterate through the vector contents", I have attempted to convert each line from a string to uint32_t using the vector::assign function. I did this when researching my problem, and found this function from another SO question: fastest way to convert a std::vector to another std::vector (author: Vlad, answered Oct 26 '11 at 7:36). When I try to run this code, I receive the following error message:

error: cannot convert ‘std::__cxx11::basic_string<char>’ to ‘unsigned int’ in initialization

TO SUMMARISE:

How can I read the contents of a file line by line, and convert each line into the data type uint32_t? I have ensured that each line is equal to 32-bits.

p.luck
  • 646
  • 2
  • 9
  • 34
  • 4
    [`std::stoi`](https://en.cppreference.com/w/cpp/string/basic_string/stol) and friends? – Some programmer dude Jul 29 '19 at 12:27
  • 1
    And to *transform* from a vector of strings to a vector of integers, [`std::transform`](https://en.cppreference.com/w/cpp/algorithm/transform). – Some programmer dude Jul 29 '19 at 12:28
  • 1
    Or if the numbers is all there is in the file, then [`std::istream_iterator`](https://en.cppreference.com/w/cpp/iterator/istream_iterator) to copy the data directly from the file into the integer vector. – Some programmer dude Jul 29 '19 at 12:30
  • 1
    What do you mean by *I have ensured that each line is equal to 32-bits.*? Does each number need to have 32 bits to represent it? – NathanOliver Jul 29 '19 at 12:32
  • @NathanOliver Yes, that is correct. – p.luck Jul 29 '19 at 12:33
  • 1
    So all the number in the file are in the range `[2147483648, 4294967295]`? – NathanOliver Jul 29 '19 at 12:34
  • 1
    @NathanOliver: The example includes `09732679`. – MSalters Jul 29 '19 at 12:38
  • 1
    also https://stackoverflow.com/q/5590381/560648 – Lightness Races in Orbit Jul 29 '19 at 12:40
  • 1
    That word `cast` again. What you are attempting to do here is **convert** a string to an integer. There's no cast that will do what you want. – john Jul 29 '19 at 12:55
  • @john thanks, I have adjusted the title accordingly and have taken your information on board. – p.luck Jul 29 '19 at 12:56
  • 1
    The simplest, in my opinion, would be to not bother with the vector of strings at all and as mentioned use [`std::istream_iterator`](https://en.cppreference.com/w/cpp/iterator/istream_iterator) to copy directly from the file into the integer vector: `std::vector intVector(std::istream_iterator(in), std::istream_iterator());` That's all you need to read all integers from the file into a vector. – Some programmer dude Jul 29 '19 at 13:08

2 Answers2

8

Like this

std::vector<std::uint32_t> new_variable;
for (string str : vecOfStr)
    new_variable.push_back(static_cast<uint32_t>(std::stoul(str)));

The stoul function converts to string to the integer. Strictly it converts to an unsigned long not a uint32_t. But all legal values of uint32_t can be represented by an unsigned long and a cast converts back to the uint32_t that you want.

There's other ways (using std::transform for instance), but I find an explicit loop to be simpler.

There's no error checking in the code above. If that's necessary something like artm's answer is preferable.

BTW your attempt failed because there's no implicit conversion between a string and a uint32_t. When there is an implicit conversion then what you tried would work.

john
  • 85,011
  • 4
  • 57
  • 81
0

Use stringstream for formatting, you'd need to include <stringstream>

Also:

  • Move new_variable outside the loop as otherwise the resulting vector would not be useful

  • There is no need to pass vecOfStrs as reference. Would be better to just return the vector by value.

        std::vector<std::uint32_t> new_variable;

        for(std::string & line : vecOfStr)
        {
            //For each line, convert from string to uint32_t

            std::stringstream ss(line);
            uint32_t val;
            if( !( ss >> val ) )
            {
                throw std::runtime_error( "failed to convert to uint32" );
            }
            
            std::cout << "val = " << val << '\n';   
            new_variable.push_back( val );
        }
Waqar
  • 8,558
  • 4
  • 35
  • 43
artm
  • 17,291
  • 6
  • 38
  • 54