0

I am reading from a ascii file, which contains information from a picture. The file looks like

1,434,341,158,498,... until the end of a row of pixels. The next pixel row then starts below 5,316,211,323,269,... etc repeating until all pixels have been covered.

I am trying to use getline() to write these data values to an array for processing. The part of my code responsible for exacting the value is as follows:

while(!asciiimage.eof()){   
string pixelvalue;
getline(asciiimage, pixelvalue, ',');
cout << pixelvalue << endl;
}

This loops until the end of the file. This works fine for one row of pixels, however at the end of the row of pixels the cout look something like this:

115
134

465
200

with a gap inbetween the values. I would like to detect this gap. I have tried to detect it using

pixelvalue.length();
pixelvalue.size();

but both of these were unsuccessful. How else can i detect this blank value of pixelvalue?

Adam
  • 177
  • 1
  • 8
  • You want to remove the gap or just check for the gap? – DodoSombrero Jul 27 '14 at 12:15
  • I would like to detect the gap so that i can tell the code to start filling the next row of an array, and also delete the gap too so that the first element of the next row is not blank – Adam Jul 27 '14 at 12:16
  • By any chance is your loop condition something like `while (!asciiimage.eof())`? You need to post a compilable example that demonstrates the issue. – user657267 Jul 27 '14 at 12:21
  • I will edit my post for a complete example – Adam Jul 27 '14 at 12:22
  • 3
    As expected, [do not use the eof check](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – user657267 Jul 27 '14 at 12:24
  • Here's [another answer](http://stackoverflow.com/a/24520662/1413395) that is related to your problem. – πάντα ῥεῖ Jul 27 '14 at 12:28
  • This approach seems dubious. Why not just have two nested loops, an outer one for actual lines and an inner one for comma-separated values? – Kerrek SB Jul 27 '14 at 12:28
  • the problem is not the eof check as these blank values exist if this check is used or not. Though, i have read the linked article and will use another loop from now on. – Adam Jul 27 '14 at 12:43
  • The problem *is* the eof check, as it causes your loop to run one too many times, unless you don't end rows with a comma. – user657267 Jul 27 '14 at 13:08
  • Whether this is the main problem or not, your loop _is_ flawed and you _shall_ fix it. – Lightness Races in Orbit Jul 27 '14 at 15:07

3 Answers3

2

if

if(pixelvalue.length() == 0)

doesn't help, then it's not empty, but has some spaces in it. In particular, the last element of the row is the newline character. Trim the string before checking it for emptiness

boost::trim(pixelvalue);
if(pixelvalue.empty()) ...

For more information on trimming, see this question.

Alternatively, first read the whole line into a string, without the line terminating character, then read values from the string.

string line; 
while(getline(file, line))
{
   //optionally trim the line here.
   istringstream iss(line);
   string value;
   while(getline(iss, value, ',')
       cout << value << endl; 
}
Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Can't you also check for newlines like `if (ch == '\n' || ...) to check for the empty spaces? – DodoSombrero Jul 27 '14 at 12:20
  • @DodoSerebro: If we're absolutely sure about the format, yes. But I don't know if we have a guarantee that there are no spaces in the end. – Armen Tsirunyan Jul 27 '14 at 12:22
  • or maybe do a method like isWhiteSpace(ch) which checks for every whitespace ranging from '\n', ' ', '\t' or so. – DodoSombrero Jul 27 '14 at 12:24
  • OP's problem is the ever-present while(!eof())). – user657267 Jul 27 '14 at 12:25
  • (!eof()) sometimes is worse, as even after trim or something, if any garbage data is produced, it is still read. EOF check is one of the worst things I found in c++. EDIT: Sorry user657267. I didn't notice you said NOT to use !eof – DodoSombrero Jul 27 '14 at 12:31
  • 1
    I have tried to implement your alternative solution. boost::trim is not available to me it seems in the software i'm using. The output still contains the blank data values. Is there another way to trim them? – Adam Jul 27 '14 at 12:41
  • I think for boost you need to download an external library found online for free. – DodoSombrero Jul 27 '14 at 14:45
0

Use strtol to convert to long value & print only if its non-zero value.

pixelbits = strtol (pixelvalue.c_str(),&pEnd,16);
if(pixelbits)
  cout << pixelvalue << endl;
dvasanth
  • 1,337
  • 1
  • 9
  • 10
0

Your main problem probably is the

 while(!asciiimage.eof()){ 

condition IMHO. You can read about more of the reasoning here: Why is iostream::eof inside a loop condition considered wrong?


Here's what I would do

// Consider asciiimage is your text file input
std::istringstream asciiimage(R"input(1,434,341,158,498
5,316,211,323,269
42,508,645,232,2)input");

std::vector<std::vector<int>> pixelrows;
std::string line;
while(std::getline(asciiimage,line)) {
    pixelrows.push_back(std::vector<int>());
    std::istringstream linein(line);
    int num;
    while(linein >> num || !linein.eof()) { // << Note these different conditions
        if(linein.fail()) { // just clear the streams error state, and
                            // consume any characters, that don't fit your 
                            // expected formats
            linein.clear();
            char dummy;
            linein >> dummy;
            continue;
        }
        pixelrows.back().push_back(num);
    }
}

To output/process the gathered pixel values you can do as follows then

for(auto itRow = pixelrows.begin();
    itRow != pixelrows.end();
    ++itRow) {
    for(auto itCol = itRow->begin();
        itCol != itRow->end();
        ++itCol) {
        if(itCol != itRow->begin()) {
            std::cout << ", ";
        }
        std::cout << *itCol;
    }
    std::cout << std::endl;
}

Output

1, 434, 341, 158, 498
5, 316, 211, 323, 269
42, 508, 645, 232, 2

See a complete working sample of the code here please.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190