f



Giving up: strtol problems

Hello!

During a few days I did my best not to come here because I wanted
to post a more or less finished first (yes, still that first one) piece of 
the program I am working on (remember from my previous posts?).
This first piece is on reading and storing the data from csv file. 
I have been breaking the program, I have showed here a few days
ago, into functions and also bringing in important improvements.

I did forebear from posting here numerous questions I had during 
these days because I truly wanted to cope with them myself, and 
show the piece that is more or less ready, or at least done to a degree,
beyond which I won't be able to improve it myself.

I have managed to put up a few important parts. But I do give up 
on the one I am posting now: for a third day I can't find my mistake;
this function doesn't work, although I had exactly the same 'for loop'
and the same process in the combined program (the one that reads 
each line, parses the row names, and then converts all numbers into
integer values) I have posted a few days ago. 

I have reached the stage, at which I am not gaining any more knowledge
trying to find my mistake and simply loosing the precious time. 
As usual, I will be grateful for your help.

Please, do me a favor and do not comment on the overall approach; 
only help me to find out why this test piece doesn't do the job. I have 
to understand my mistake within this exact environment, and leave
all improvements till later, when I present all pieces of this first part
together. Please. 

This test piece demonstrates a function that should take only those
parts of the line, which contain numerical characters
and turn them into integers. I am using the same for loop I have already 
used, with the strtol function. I have added my understanding of the 
way the loop works within the function separated by //////    //////
to distinguish these lines from all other comments. 
Some line return partially correct array of integers, with the rest
of the array filled in with junk values. Others return the whole array
of junk values. I did try to spot the pattern hoping that his will help
me to figure out the mistake; I don't see that pattern. I get partially
correct array closer to the end lines of the input. Very strange.
(Please, do not pay attention to ending two zeros; this is that
old file I have not yet corrected based on our discussion of the 
windows csv format).


INPUT 
Years,2011,2012,2013,2014,2015
Sales,1062,1252,1587,1934,2519
Cost of Goods Sold,654,814,1009,1190,1499
  Gross Profit,408,438,578,744,1020
"Selling, General, and Admin Exp",254,271,364,454,576
  Operating Income before Depr,154,167,214,290,444
Depreciation and Amortization,25,31,38,52,70
  Operating Profit,129,136,176,238,374
Interest Expense,4,3,3,1,4
Other Gains and Losses,0,7,10,0,-1
  Pretax Income,125,126,163,237,371
Income Tax Expense,55,52,65,92,141
  Net Income,70,74,98,145,230

OUTPUT (skipping the middle part to save the space)
(1) BUFFER:: Years,2011,2012,2013,2014,2015,
(1.2) Line number passed to fun_values = 0
(1.3) Index number passed to fun_values = 6
(1.4) Ptr_buffer:: 2011,2012,2013,2014,2015,


(1.5) Line number values after the fun_values = 1
(1.6) Index after the fun_values = 12
(1.7) Values_Index after the fun_values = 6

(2) -37 -36 -35 -34 -33 0 

(1) BUFFER:: Sales,1062,1252,1587,1934,2519,
(1.2) Line number passed to fun_values = 1
(1.3) Index number passed to fun_values = 6
(1.4) Ptr_buffer:: 1062,1252,1587,1934,2519,


(1.5) Line number values after the fun_values = 2
(1.6) Index after the fun_values = 12
(1.7) Values_Index after the fun_values = 6

(2) 38 -28 51 -114 -41 0 

(1) BUFFER:: Cost of Goods Sold,654,814,1009,1190,1499,
(1.2) Line number passed to fun_values = 2
(1.3) Index number passed to fun_values = 19
(1.4) Ptr_buffer:: 654,814,1009,1190,1499,


(1.5) Line number values after the fun_values = 3
(1.6) Index after the fun_values = 26
(1.7) Values_Index after the fun_values = 7

(2) -114 46 -15 -90 -37 0 0 
////////////////////////////////////

(1) BUFFER::   Pretax Income,125,126,163,237,371,
(1.2) Line number passed to fun_values = 10
(1.3) Index number passed to fun_values = 16
(1.4) Ptr_buffer:: 125,126,163,237,371,


(1.5) Line number values after the fun_values = 11
(1.6) Index after the fun_values = 23
(1.7) Values_Index after the fun_values = 7

(2) 125 126 -93 -19 115 0 0 

(1) BUFFER:: Income Tax Expense,55,52,65,92,141,
(1.2) Line number passed to fun_values = 11
(1.3) Index number passed to fun_values = 19
(1.4) Ptr_buffer:: 55,52,65,92,141,


(1.5) Line number values after the fun_values = 12
(1.6) Index after the fun_values = 26
(1.7) Values_Index after the fun_values = 7

(2) 55 52 65 92 -115 0 0 

(1) BUFFER::   Net Income,70,74,98,145,230,
(1.2) Line number passed to fun_values = 12
(1.3) Index number passed to fun_values = 13
(1.4) Ptr_buffer:: 70,74,98,145,230,


(1.5) Line number values after the fun_values = 13
(1.6) Index after the fun_values = 20
(1.7) Values_Index after the fun_values = 7

(2) 70 74 98 -111 -26 0 0 

//Function to read a line and convert numerical characters into integers
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define BUFFER_SIZE 100
#define INCOME_STATEMENT "files/income_test.csv"

int fill_row_values(char *buffer, char array_values[][50],
                   size_t *line_number_values, size_t *index,
                                        size_t *values_index);

int main(int argc, char *argv[])
{
    //Check for correct number of arguments
    if(argc > 2)
    {
        fputs("Sorry, the program processes only one file.\n", stderr);
        return EXIT_FAILURE;
    }
    //Determine a file to use
    const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
    
    FILE *fp = fopen(data_file, "r");
    
    if ( fp )
    {
        char buffer[BUFFER_SIZE] = "";
        char array_values[50][50] = {{0}};
        int function_values_success;
        size_t line_number_values = 0;
        
        //Read each line from the file, store in the buffer
        while(fgets(buffer, sizeof(buffer), fp) != NULL)
        {
            /*******************/
            //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
            putchar('\n');
            printf("(1) BUFFER:: %s", buffer);
            /*******************/
            
            size_t index = 0;

            while(!isdigit(buffer[index++]));
            index--;
            size_t values_index = 0;
            
            if((function_values_success = fill_row_values(buffer,
                      array_values, &line_number_values, &index,
                                &values_index)) == EXIT_SUCCESS)
            {
                line_number_values++;
                
                /*******************/
                //DEBUG: LINE_NUMBER_VALUES && INDEXES
                printf("(1.5) Line number values after the fun_values = %zu\n",
                       line_number_values);
                printf("(1.6) Index after the fun_values = %zu\n",
                       index);
                printf("(1.7) Values_Index after the fun_values = %zu\n",
                       values_index);
                /*******************/
                
                /*******************/
                //DEBUG: CHECK IF VALUES ARE FILLED CORRECTLY
                putchar('\n');
                printf("(2) ");
                for (size_t j = 0; j < values_index; j++)
                    printf("%d ", array_values[line_number_values-1][j]);
                putchar('\n');
                /*******************/
                
            }
            else
            {
                printf("The function_values failed\n");
                return EXIT_FAILURE;
            }

        }
        if (ferror(fp))
        {
            puts("Something went wrong with the provided file\n");
            return EXIT_FAILURE;
        }
        fclose(fp);
    }
    //Couldn't open the file
    else
    {
        perror(data_file);
    }
    return 0;
}

int fill_row_values(char *buffer, char array_values[][50],
                    size_t *line_number_values, size_t *index,
                                        size_t *values_index)
{
    char *ptr_buffer = NULL;
    ptr_buffer = &buffer[*index];
    size_t values_column_number;
    
    /*******************/
    //DEBUG: LINE_NUMBER & INDEX
    printf("(1.2) Line number passed to fun_values = %zu\n",
           *line_number_values);
    printf("(1.3) Index number passed to fun_values = %zu\n",
           *index);
    //DEBUG: CHECK PTR_BUFFER
    printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
    /*******************/

    
    //Parse each line's comma-separated values into 'array_values'
    for ( values_column_number = 0; *ptr_buffer != '\0';
          values_column_number++, ptr_buffer++, (*index)++)
    {
        array_values[*line_number_values][values_column_number] =
                          (int)strtol(ptr_buffer, &ptr_buffer,10);
        (*values_index)++;

/////////// With each iteration of the for loop, the strtol function
looks for numerical values in ptr_buffer, converts them into 
integers, and stops at the first non-numerical character, 
comma in this case, storing the pointer to the unconverted 
string in ptr_buffer; the loop moves ptr_buffer to the next 
address after the comma, where the next numerical character
is; this process goes on until the *ptr_buffer is '\0'//////////////

    }
    putchar('\n');
    //Check if conversion was successful
    if(*ptr_buffer)
    {
        printf("Conversion failed; not converted string: %s\n",
               ptr_buffer);
        return EXIT_FAILURE;
    }
    
    return EXIT_SUCCESS;
}

Thank you!
0
Alla
12/21/2016 8:12:58 AM
comp.lang.c 30656 articles. 5 followers. spinoza1111 (3246) is leader. Post Follow

37 Replies
905 Views

Similar Articles

[PageSpeed] 10

[First things first: I've found your problem. Well, okay, I've found at 
least one problem, and it's a doozie. Read on.]

On 21/12/16 08:12, Alla _ wrote:
>
> Please, do me a favor and do not comment on the overall approach;

I will somewhat reluctantly agree to that on this occasion, apart from 
one moan (see below).

> This test piece demonstrates a function that should take only those
> parts of the line, which contain numerical characters
> and turn them into integers. I am using the same for loop I have already
> used, with the strtol function. I have added my understanding of the
> way the loop works within the function separated by //////    //////
> to distinguish these lines from all other comments.

Here's the moan. Single-line comments // work for single lines.

// They don't work
for multiple lines,
not even a little bit.

/*
      If you have to add a multi-line comment into C source
      (and it does happen from time to time), then this is
      how you do it.
  */

> INPUT
> Years,2011,2012,2013,2014,2015
> Sales,1062,1252,1587,1934,2519
> Cost of Goods Sold,654,814,1009,1190,1499
>   Gross Profit,408,438,578,744,1020
> "Selling, General, and Admin Exp",254,271,364,454,576
>   Operating Income before Depr,154,167,214,290,444
> Depreciation and Amortization,25,31,38,52,70
>   Operating Profit,129,136,176,238,374
> Interest Expense,4,3,3,1,4
> Other Gains and Losses,0,7,10,0,-1
>   Pretax Income,125,126,163,237,371
> Income Tax Expense,55,52,65,92,141
>   Net Income,70,74,98,145,230

For me, this is test5.csv:

.... 476 Dec 15 13:40 test1.csv
.... 492 Dec 15 13:40 test2.csv
.... 502 Dec 15 19:20 test3.csv
.... 516 Dec 16 11:25 test4.csv
.... 492 Dec 21 08:52 test5.csv

and a diff shows that it's identical to test2.csv. I have no problem 
with the test data at this stage.

> int fill_row_values(char *buffer, char array_values[][50],
>                     size_t *line_number_values, size_t *index,
>                                         size_t *values_index)

Let's start here. char array_values[][50]. Not the way I would have done 
it, but okay, it's the way /you/ are doing it. But let's bear in mind 
that we have storage for 50 rows of 50 chars.

A char is a value in the range CHAR_MIN to CHAR_MAX. If you try to 
store, in a char, a value that is not in that range, then at the very 
least you're probably not going to get the results you expect.

CHAR_MIN on modern desktop systems is probably -127 or -128, and 
CHAR_MAX is probably 127. But in any event, we can pick up those values 
from <limits.h>. (Just watch for now. You'll see in a minute how this is 
relevant.)

>     //Parse each line's comma-separated values into 'array_values'
>     for ( values_column_number = 0; *ptr_buffer != '\0';
>           values_column_number++, ptr_buffer++, (*index)++)
>     {
>         array_values[*line_number_values][values_column_number] =
>                           (int)strtol(ptr_buffer, &ptr_buffer,10);
>         (*values_index)++;

Okay, the first thing I worried about was bounds violation. So I added 
some code to the above loop, turning it into this:

       fprintf(stderr, "CHECK A: values_column_number in bounds\n");
       assert(values_column_number >= 0 && values_column_number < 50);
       fprintf(stderr, "CHECK A: passed\n");

(I needed to add the <assert.h> header, of course.)

The program passed this test for every line of data in the input file.

The next thing I worried about was that you were trying to store a long 
int in a char. That is, you were trying to store the result of strtol in 
a single byte. There are circumstances where you might want to do that, 
but I didn't think this was one of them. So I checked:

       fprintf(stderr, "CHECK B: converted value fits in a char\n");
       {
         char *endptr = NULL;
         long int num = strtol(ptr_buffer, &endptr, 10);
         assert(num >= CHAR_MIN && num < CHAR_MAX);
       }
       fprintf(stderr, "CHECK B: passed\n");

The { opens a local scope, so that I could temporarily define new 
objects without mucking about at the top of the function. It occurred to 
me later that we're using C99 so I didn't have to do this, but old 
habits die hard. Well, at least the {} reminds me of which bit I added!

Anyway, the point is that this test FAILED.

$ ./alla test5.csv

(1) BUFFER:: Years,2011,2012,2013,2014,2015
(1.2) Line number passed to fun_values = 0
(1.3) Index number passed to fun_values = 6
(1.4) Ptr_buffer:: 2011,2012,2013,2014,2015

CHECK A: values_column_number in bounds
CHECK A: passed
CHECK B: converted value fits in a char
alla: alla.c:130: fill_row_values: Assertion `num >= (-127 - 1) && num < 
127' failed.
Aborted (core dumped)

So let's find out exactly what number we were trying to convert:

       fprintf(stderr, "CHECK B: converted value fits in a char\n");
       {
         char *endptr = NULL;
         long int num = strtol(ptr_buffer, &endptr, 10);
         fprintf(stderr, "CHECK B: converted value is: %ld\n", num);
         assert(num >= CHAR_MIN && num < CHAR_MAX);
       }
       fprintf(stderr, "CHECK B: passed\n");

When we run this, we find:

CHECK A: values_column_number in bounds
CHECK A: passed
CHECK B: converted value fits in a char
CHECK B: converted value is: 2011
alla: alla.c:131: fill_row_values: Assertion `num >= (-127 - 1) && num < 
127' failed.
Aborted (core dumped)

So you're trying to fit the value 2011 into an 8-bit char. That is 
/never/ going to work, is it? There simply isn't room. With the best 
will in the world, you're not going to be able to represent 2011 in 
fewer than about 12 bits.

So the question is why you are trying to store a number like 2011 in an 
array of arrays of char.

> /////////// With each iteration of the for loop, the strtol function
> looks for numerical values in ptr_buffer, converts them into
> integers, and stops at the first non-numerical character,
> comma in this case, storing the pointer to the unconverted
> string in ptr_buffer; the loop moves ptr_buffer to the next
> address after the comma, where the next numerical character
> is; this process goes on until the *ptr_buffer is '\0'//////////////

I know I promised not to deconstruct your code, but I think I'd be very 
wary about using the same pointer to do both jobs in the same line. I'd 
prefer to see a structure such as this:

   n = strtol(p, &q, 10);
   if(q > p)
   {
     /* q is not p, so we got some data, so we can: */
     x[y] = n; /* (a) use n, AND: */
     if(*q != '\0')
     {
       p = q + 1; /* (b) move p on past the comma */
     }
   }
} /* (c) and go round our parse loop again. */

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 9:31:15 AM
On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
> [First things first: I've found your problem. Well, okay, I've found at 
> least one problem, and it's a doozie. Read on.]
> 
)
> On 21/12/16 08:12, Alla _ wrote:
> >
> > Please, do me a favor and do not comment on the overall approach;
> 
> I will somewhat reluctantly agree to that on this occasion, apart from 
> one moan (see below).
> 
> > This test piece demonstrates a function that should take only those
> > parts of the line, which contain numerical characters
> > and turn them into integers. I am using the same for loop I have already
> > used, with the strtol function. I have added my understanding of the
> > way the loop works within the function separated by //////    //////
> > to distinguish these lines from all other comments.
> 
> Here's the moan. Single-line comments // work for single lines.
> 
Oh, I know that; would never imagine having multi line comment with //
Are you referring to the "sort of comment" I have posted within 
the for loop in the function? Well, it is not really a comment, and it is 
definitely not part of my function; I have written that piece for this post
and it exists only here )

> // They don't work
> for multiple lines,
> not even a little bit.
> 
> /*
>       If you have to add a multi-line comment into C source
>       (and it does happen from time to time), then this is
>       how you do it.
>   */
> 
<snip>
0
Alla
12/21/2016 9:41:27 AM
On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
> [First things first: I've found your problem. Well, okay, I've found at 
> least one problem, and it's a doozie. Read on.]
> 
> On 21/12/16 08:12, Alla _ wrote:
> >
> > Please, do me a favor and do not comment on the overall approach;
> 
> I will somewhat reluctantly agree to that on this occasion, apart from 
> one moan (see below).
> 
> > This test piece demonstrates a function that should take only those
> > parts of the line, which contain numerical characters
> > and turn them into integers. I am using the same for loop I have already
> > used, with the strtol function. I have added my understanding of the
> > way the loop works within the function separated by //////    //////
> > to distinguish these lines from all other comments.
> 
> Here's the moan. Single-line comments // work for single lines.
> 
> // They don't work
> for multiple lines,
> not even a little bit.
> 
> /*
>       If you have to add a multi-line comment into C source
>       (and it does happen from time to time), then this is
>       how you do it.
>   */
> 
> > INPUT
> > Years,2011,2012,2013,2014,2015
> > Sales,1062,1252,1587,1934,2519
> > Cost of Goods Sold,654,814,1009,1190,1499
> >   Gross Profit,408,438,578,744,1020
> > "Selling, General, and Admin Exp",254,271,364,454,576
> >   Operating Income before Depr,154,167,214,290,444
> > Depreciation and Amortization,25,31,38,52,70
> >   Operating Profit,129,136,176,238,374
> > Interest Expense,4,3,3,1,4
> > Other Gains and Losses,0,7,10,0,-1
> >   Pretax Income,125,126,163,237,371
> > Income Tax Expense,55,52,65,92,141
> >   Net Income,70,74,98,145,230
> 
> For me, this is test5.csv:
> 
> ... 476 Dec 15 13:40 test1.csv
> ... 492 Dec 15 13:40 test2.csv
> ... 502 Dec 15 19:20 test3.csv
> ... 516 Dec 16 11:25 test4.csv
> ... 492 Dec 21 08:52 test5.csv
> 
> and a diff shows that it's identical to test2.csv. I have no problem 
> with the test data at this stage.
> 
> > int fill_row_values(char *buffer, char array_values[][50],
> >                     size_t *line_number_values, size_t *index,
> >                                         size_t *values_index)
> 
> Let's start here. char array_values[][50]. Not the way I would have done 
> it, but okay, it's the way /you/ are doing it. But let's bear in mind 
> that we have storage for 50 rows of 50 chars.
> 
I have not yet read the whole post till the end, and, oh oh oh, char * array_values!
No, I could not have missed that. How could I have not changed that into 
int or other types of the sort... A few days staring at the function, working 
with it, writing out every single step, and not spotting this char thing ) Oh.

> A char is a value in the range CHAR_MIN to CHAR_MAX. If you try to 
> store, in a char, a value that is not in that range, then at the very 
> least you're probably not going to get the results you expect.
> 
> CHAR_MIN on modern desktop systems is probably -127 or -128, and 
> CHAR_MAX is probably 127. But in any event, we can pick up those values 
> from <limits.h>. (Just watch for now. You'll see in a minute how this is 
> relevant.)
> 
> >     //Parse each line's comma-separated values into 'array_values'
> >     for ( values_column_number = 0; *ptr_buffer != '\0';
> >           values_column_number++, ptr_buffer++, (*index)++)
> >     {
> >         array_values[*line_number_values][values_column_number] =
> >                           (int)strtol(ptr_buffer, &ptr_buffer,10);
> >         (*values_index)++;
> 
> Okay, the first thing I worried about was bounds violation. So I added 
> some code to the above loop, turning it into this:
> 
>        fprintf(stderr, "CHECK A: values_column_number in bounds\n");
>        assert(values_column_number >= 0 && values_column_number < 50);
>        fprintf(stderr, "CHECK A: passed\n");
> 
> (I needed to add the <assert.h> header, of course.)
> 
> The program passed this test for every line of data in the input file.
> 
> The next thing I worried about was that you were trying to store a long 
> int in a char. That is, you were trying to store the result of strtol in 
> a single byte. There are circumstances where you might want to do that, 
> but I didn't think this was one of them. So I checked:
> 
>        fprintf(stderr, "CHECK B: converted value fits in a char\n");
>        {
>          char *endptr = NULL;
>          long int num = strtol(ptr_buffer, &endptr, 10);
>          assert(num >= CHAR_MIN && num < CHAR_MAX);
>        }
>        fprintf(stderr, "CHECK B: passed\n");
> 
> The { opens a local scope, so that I could temporarily define new 
> objects without mucking about at the top of the function. It occurred to 
> me later that we're using C99 so I didn't have to do this, but old 
> habits die hard. Well, at least the {} reminds me of which bit I added!
> 
> Anyway, the point is that this test FAILED.
> 
> $ ./alla test5.csv
> 
> (1) BUFFER:: Years,2011,2012,2013,2014,2015
> (1.2) Line number passed to fun_values = 0
> (1.3) Index number passed to fun_values = 6
> (1.4) Ptr_buffer:: 2011,2012,2013,2014,2015
> 
> CHECK A: values_column_number in bounds
> CHECK A: passed
> CHECK B: converted value fits in a char
> alla: alla.c:130: fill_row_values: Assertion `num >= (-127 - 1) && num < 
> 127' failed.
> Aborted (core dumped)
> 
> So let's find out exactly what number we were trying to convert:
> 
>        fprintf(stderr, "CHECK B: converted value fits in a char\n");
>        {
>          char *endptr = NULL;
>          long int num = strtol(ptr_buffer, &endptr, 10);
>          fprintf(stderr, "CHECK B: converted value is: %ld\n", num);
>          assert(num >= CHAR_MIN && num < CHAR_MAX);
>        }
>        fprintf(stderr, "CHECK B: passed\n");
> 
> When we run this, we find:
> 
> CHECK A: values_column_number in bounds
> CHECK A: passed
> CHECK B: converted value fits in a char
> CHECK B: converted value is: 2011
> alla: alla.c:131: fill_row_values: Assertion `num >= (-127 - 1) && num < 
> 127' failed.
> Aborted (core dumped)
> 
> So you're trying to fit the value 2011 into an 8-bit char. That is 
> /never/ going to work, is it? There simply isn't room. With the best 
> will in the world, you're not going to be able to represent 2011 in 
> fewer than about 12 bits.
> 
> So the question is why you are trying to store a number like 2011 in an 
> array of arrays of char.
> 
> > /////////// With each iteration of the for loop, the strtol function
> > looks for numerical values in ptr_buffer, converts them into
> > integers, and stops at the first non-numerical character,
> > comma in this case, storing the pointer to the unconverted
> > string in ptr_buffer; the loop moves ptr_buffer to the next
> > address after the comma, where the next numerical character
> > is; this process goes on until the *ptr_buffer is '\0'//////////////
> 
> I know I promised not to deconstruct your code, but I think I'd be very 
> wary about using the same pointer to do both jobs in the same line. I'd 
> prefer to see a structure such as this:
> 
>    n = strtol(p, &q, 10);
>    if(q > p)
>    {
>      /* q is not p, so we got some data, so we can: */
>      x[y] = n; /* (a) use n, AND: */
>      if(*q != '\0')
>      {
>        p = q + 1; /* (b) move p on past the comma */
>      }
>    }
> } /* (c) and go round our parse loop again. */
> 
> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within
0
Alla
12/21/2016 9:44:31 AM
On 21/12/16 09:41, Alla _ wrote:
> On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
>>
>> Here's the moan. Single-line comments // work for single lines.
>>
> Oh, I know that; would never imagine having multi line comment with //
> Are you referring to the "sort of comment" I have posted within
> the for loop in the function? Well, it is not really a comment, and it is
> definitely not part of my function; I have written that piece for this post
> and it exists only here )

Well, it stopped the code from compiling. It was of course a minor 
inconvenience, but it was still an inconvenience.

I see that you've posted another reply, presumably about the actual 
problem. Moving on...

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 9:52:33 AM
On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
> [First things first: I've found your problem. Well, okay, I've found at 
> least one problem, and it's a doozie. Read on.]
> 
> On 21/12/16 08:12, Alla _ wrote:
> >
> > Please, do me a favor and do not comment on the overall approach;
> 
> I will somewhat reluctantly agree to that on this occasion, apart from 
> one moan (see below).
> 
> > This test piece demonstrates a function that should take only those
> > parts of the line, which contain numerical characters
> > and turn them into integers. I am using the same for loop I have already
> > used, with the strtol function. I have added my understanding of the
> > way the loop works within the function separated by //////    //////
> > to distinguish these lines from all other comments.
> 
> Here's the moan. Single-line comments // work for single lines.
> 
> // They don't work
> for multiple lines,
> not even a little bit.
> 
> /*
>       If you have to add a multi-line comment into C source
>       (and it does happen from time to time), then this is
>       how you do it.
>   */
> 
> > INPUT
> > Years,2011,2012,2013,2014,2015
> > Sales,1062,1252,1587,1934,2519
> > Cost of Goods Sold,654,814,1009,1190,1499
> >   Gross Profit,408,438,578,744,1020
> > "Selling, General, and Admin Exp",254,271,364,454,576
> >   Operating Income before Depr,154,167,214,290,444
> > Depreciation and Amortization,25,31,38,52,70
> >   Operating Profit,129,136,176,238,374
> > Interest Expense,4,3,3,1,4
> > Other Gains and Losses,0,7,10,0,-1
> >   Pretax Income,125,126,163,237,371
> > Income Tax Expense,55,52,65,92,141
> >   Net Income,70,74,98,145,230
> 
> For me, this is test5.csv:
> 
> ... 476 Dec 15 13:40 test1.csv
> ... 492 Dec 15 13:40 test2.csv
> ... 502 Dec 15 19:20 test3.csv
> ... 516 Dec 16 11:25 test4.csv
> ... 492 Dec 21 08:52 test5.csv
> 
> and a diff shows that it's identical to test2.csv. I have no problem 
> with the test data at this stage.
> 
> > int fill_row_values(char *buffer, char array_values[][50],
> >                     size_t *line_number_values, size_t *index,
> >                                         size_t *values_index)
> 
> Let's start here. char array_values[][50]. Not the way I would have done 
> it, but okay, it's the way /you/ are doing it. But let's bear in mind 
> that we have storage for 50 rows of 50 chars.
> 
> A char is a value in the range CHAR_MIN to CHAR_MAX. If you try to 
> store, in a char, a value that is not in that range, then at the very 
> least you're probably not going to get the results you expect.
> 
It works now. I can't believe how much time I have spent not 
being able to see my mistake. As usual, there are at least two 
positive and useful points: 1) I have read a lot about strtol, have deepened
my understanding of a few C issues, and hopeful advanced forward 
a bit 2) allowed myself a lot of sugar, and came up with a great 
candy recipe, thinking that I do need some sweet support during 
these days )
Thank you! I did try my best not to post questions, but this one truly
wore me out )  
I am continue reading your answer )
As to my array[][50] declaration, yes, as lots of other moments, I will
be happy to correct them, but first I would like to concentrate on 
"big" strokes. 
> CHAR_MIN on modern desktop systems is probably -127 or -128, and 
> CHAR_MAX is probably 127. But in any event, we can pick up those values 
> from <limits.h>. (Just watch for now. You'll see in a minute how this is 
> relevant.)
> 
> >     //Parse each line's comma-separated values into 'array_values'
> >     for ( values_column_number = 0; *ptr_buffer != '\0';
> >           values_column_number++, ptr_buffer++, (*index)++)
> >     {
> >         array_values[*line_number_values][values_column_number] =
> >                           (int)strtol(ptr_buffer, &ptr_buffer,10);
> >         (*values_index)++;
> 
> Okay, the first thing I worried about was bounds violation. So I added 
> some code to the above loop, turning it into this:
> 
>        fprintf(stderr, "CHECK A: values_column_number in bounds\n");
>        assert(values_column_number >= 0 && values_column_number < 50);
>        fprintf(stderr, "CHECK A: passed\n");
> 
> (I needed to add the <assert.h> header, of course.)
> 
> The program passed this test for every line of data in the input file.
> 
> The next thing I worried about was that you were trying to store a long 
> int in a char. That is, you were trying to store the result of strtol in 
> a single byte. There are circumstances where you might want to do that, 
> but I didn't think this was one of them. So I checked:
> 
>        fprintf(stderr, "CHECK B: converted value fits in a char\n");
>        {
>          char *endptr = NULL;
>          long int num = strtol(ptr_buffer, &endptr, 10);
>          assert(num >= CHAR_MIN && num < CHAR_MAX);
>        }
>        fprintf(stderr, "CHECK B: passed\n");
> 
> The { opens a local scope, so that I could temporarily define new 
> objects without mucking about at the top of the function. It occurred to 
> me later that we're using C99 so I didn't have to do this, but old 
> habits die hard. Well, at least the {} reminds me of which bit I added!
> 
> Anyway, the point is that this test FAILED.
> 
> $ ./alla test5.csv
> 
> (1) BUFFER:: Years,2011,2012,2013,2014,2015
> (1.2) Line number passed to fun_values = 0
> (1.3) Index number passed to fun_values = 6
> (1.4) Ptr_buffer:: 2011,2012,2013,2014,2015
> 
> CHECK A: values_column_number in bounds
> CHECK A: passed
> CHECK B: converted value fits in a char
> alla: alla.c:130: fill_row_values: Assertion `num >= (-127 - 1) && num < 
> 127' failed.
> Aborted (core dumped)
> 
> So let's find out exactly what number we were trying to convert:
> 
>        fprintf(stderr, "CHECK B: converted value fits in a char\n");
>        {
>          char *endptr = NULL;
>          long int num = strtol(ptr_buffer, &endptr, 10);
>          fprintf(stderr, "CHECK B: converted value is: %ld\n", num);
>          assert(num >= CHAR_MIN && num < CHAR_MAX);
>        }
>        fprintf(stderr, "CHECK B: passed\n");
> 
> When we run this, we find:
> 
> CHECK A: values_column_number in bounds
> CHECK A: passed
> CHECK B: converted value fits in a char
> CHECK B: converted value is: 2011
> alla: alla.c:131: fill_row_values: Assertion `num >= (-127 - 1) && num < 
> 127' failed.
> Aborted (core dumped)
> 
> So you're trying to fit the value 2011 into an 8-bit char. That is 
> /never/ going to work, is it? There simply isn't room. With the best 
> will in the world, you're not going to be able to represent 2011 in 
> fewer than about 12 bits.
> 
> So the question is why you are trying to store a number like 2011 in an 
> array of arrays of char.
> 
> > /////////// With each iteration of the for loop, the strtol function
> > looks for numerical values in ptr_buffer, converts them into
> > integers, and stops at the first non-numerical character,
> > comma in this case, storing the pointer to the unconverted
> > string in ptr_buffer; the loop moves ptr_buffer to the next
> > address after the comma, where the next numerical character
> > is; this process goes on until the *ptr_buffer is '\0'//////////////
> 
> I know I promised not to deconstruct your code, but I think I'd be very 
> wary about using the same pointer to do both jobs in the same line. I'd 
> prefer to see a structure such as this:
> 
>    n = strtol(p, &q, 10);
>    if(q > p)
>    {
>      /* q is not p, so we got some data, so we can: */
>      x[y] = n; /* (a) use n, AND: */
>      if(*q != '\0')
>      {
>        p = q + 1; /* (b) move p on past the comma */
>      }
>    }
> } /* (c) and go round our parse loop again. */
> 
> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within
0
Alla
12/21/2016 9:54:12 AM
On 21/12/16 09:44, Alla _ wrote:
> On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
>> On 21/12/16 08:12, Alla _ wrote:
<snip>
>>
>>> int fill_row_values(char *buffer, char array_values[][50],
>>>                     size_t *line_number_values, size_t *index,
>>>                                         size_t *values_index)
>>
>> Let's start here. char array_values[][50]. Not the way I would have done
>> it, but okay, it's the way /you/ are doing it. But let's bear in mind
>> that we have storage for 50 rows of 50 chars.
>>
> I have not yet read the whole post till the end, and, oh oh oh, char * array_values!
> No, I could not have missed that. How could I have not changed that into
> int or other types of the sort... A few days staring at the function, working
> with it, writing out every single step, and not spotting this char thing ) Oh.

Lesson: ask early, ask often. By all means try to work it out for 
yourself (and if you didn't, many of us would soon lose patience with 
you!), but don't spend hours, let alone days, banging your head against 
a brick wall. Sometimes you have to keep an eye on the clock and adopt a 
pragmatic attitude.

I hope, though, that you do find time to look at my alternative 
suggestion for the tokenisation loop. I think you'll find it to be 
clearer, easier to understand, and less likely to break.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 10:00:50 AM
On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
> [First things first: I've found your problem. Well, okay, I've found at 
> least one problem, and it's a doozie. Read on.]
> 
> On 21/12/16 08:12, Alla _ wrote:
> >
> > Please, do me a favor and do not comment on the overall approach;
> 
> I will somewhat reluctantly agree to that on this occasion, apart from 
> one moan (see below).
> 
> > This test piece demonstrates a function that should take only those
> > parts of the line, which contain numerical characters
> > and turn them into integers. I am using the same for loop I have already
> > used, with the strtol function. I have added my understanding of the
> > way the loop works within the function separated by //////    //////
> > to distinguish these lines from all other comments.
> 
> Here's the moan. Single-line comments // work for single lines.
> 
> // They don't work
> for multiple lines,
> not even a little bit.
> 
> /*
>       If you have to add a multi-line comment into C source
>       (and it does happen from time to time), then this is
>       how you do it.
>   */
> 
> > INPUT
> > Years,2011,2012,2013,2014,2015
> > Sales,1062,1252,1587,1934,2519
> > Cost of Goods Sold,654,814,1009,1190,1499
> >   Gross Profit,408,438,578,744,1020
> > "Selling, General, and Admin Exp",254,271,364,454,576
> >   Operating Income before Depr,154,167,214,290,444
> > Depreciation and Amortization,25,31,38,52,70
> >   Operating Profit,129,136,176,238,374
> > Interest Expense,4,3,3,1,4
> > Other Gains and Losses,0,7,10,0,-1
> >   Pretax Income,125,126,163,237,371
> > Income Tax Expense,55,52,65,92,141
> >   Net Income,70,74,98,145,230
> 
> For me, this is test5.csv:
> 
> ... 476 Dec 15 13:40 test1.csv
> ... 492 Dec 15 13:40 test2.csv
> ... 502 Dec 15 19:20 test3.csv
> ... 516 Dec 16 11:25 test4.csv
> ... 492 Dec 21 08:52 test5.csv
> 
> and a diff shows that it's identical to test2.csv. I have no problem 
> with the test data at this stage.
> 
> > int fill_row_values(char *buffer, char array_values[][50],
> >                     size_t *line_number_values, size_t *index,
> >                                         size_t *values_index)
> 
> Let's start here. char array_values[][50]. Not the way I would have done 
> it, but okay, it's the way /you/ are doing it. But let's bear in mind 
> that we have storage for 50 rows of 50 chars.
> 
> A char is a value in the range CHAR_MIN to CHAR_MAX. If you try to 
> store, in a char, a value that is not in that range, then at the very 
> least you're probably not going to get the results you expect.
> 
> CHAR_MIN on modern desktop systems is probably -127 or -128, and 
> CHAR_MAX is probably 127. But in any event, we can pick up those values 
> from <limits.h>. (Just watch for now. You'll see in a minute how this is 
> relevant.)
> 
> >     //Parse each line's comma-separated values into 'array_values'
> >     for ( values_column_number = 0; *ptr_buffer != '\0';
> >           values_column_number++, ptr_buffer++, (*index)++)
> >     {
> >         array_values[*line_number_values][values_column_number] =
> >                           (int)strtol(ptr_buffer, &ptr_buffer,10);
> >         (*values_index)++;
> 
> Okay, the first thing I worried about was bounds violation. So I added 
> some code to the above loop, turning it into this:
> 
>        fprintf(stderr, "CHECK A: values_column_number in bounds\n");
>        assert(values_column_number >= 0 && values_column_number < 50);
>        fprintf(stderr, "CHECK A: passed\n");
> 
> (I needed to add the <assert.h> header, of course.)
> 
> The program passed this test for every line of data in the input file.
> 
> The next thing I worried about was that you were trying to store a long 
> int in a char. That is, you were trying to store the result of strtol in 
> a single byte. There are circumstances where you might want to do that, 
> but I didn't think this was one of them. So I checked:
> 
>        fprintf(stderr, "CHECK B: converted value fits in a char\n");
>        {
>          char *endptr = NULL;
>          long int num = strtol(ptr_buffer, &endptr, 10);
>          assert(num >= CHAR_MIN && num < CHAR_MAX);
>        }
>        fprintf(stderr, "CHECK B: passed\n");
> 
> The { opens a local scope, so that I could temporarily define new 
> objects without mucking about at the top of the function. It occurred to 
> me later that we're using C99 so I didn't have to do this, but old 
> habits die hard. Well, at least the {} reminds me of which bit I added!
> 
> Anyway, the point is that this test FAILED.
> 
> $ ./alla test5.csv
> 
> (1) BUFFER:: Years,2011,2012,2013,2014,2015
> (1.2) Line number passed to fun_values = 0
> (1.3) Index number passed to fun_values = 6
> (1.4) Ptr_buffer:: 2011,2012,2013,2014,2015
> 
> CHECK A: values_column_number in bounds
> CHECK A: passed
> CHECK B: converted value fits in a char
> alla: alla.c:130: fill_row_values: Assertion `num >= (-127 - 1) && num < 
> 127' failed.
> Aborted (core dumped)
> 
> So let's find out exactly what number we were trying to convert:
> 
>        fprintf(stderr, "CHECK B: converted value fits in a char\n");
>        {
>          char *endptr = NULL;
>          long int num = strtol(ptr_buffer, &endptr, 10);
>          fprintf(stderr, "CHECK B: converted value is: %ld\n", num);
>          assert(num >= CHAR_MIN && num < CHAR_MAX);
>        }
>        fprintf(stderr, "CHECK B: passed\n");
> 
> When we run this, we find:
> 
> CHECK A: values_column_number in bounds
> CHECK A: passed
> CHECK B: converted value fits in a char
> CHECK B: converted value is: 2011
> alla: alla.c:131: fill_row_values: Assertion `num >= (-127 - 1) && num < 
> 127' failed.
> Aborted (core dumped)
> 
> So you're trying to fit the value 2011 into an 8-bit char. That is 
> /never/ going to work, is it? There simply isn't room. With the best 
> will in the world, you're not going to be able to represent 2011 in 
> fewer than about 12 bits.
> 
> So the question is why you are trying to store a number like 2011 in an 
> array of arrays of char.
It's a very easy question to answer: this is a typo, unintentional mistake;
I have  intended to use int, and was sure that the array has the correct 
type; being confident at least in using correct corresponding types of 
variables, I have allowed this mistake to slip into the code.  The reason
I have this typo is due to copying the function declaration I used to
fill row_names array, and then correcting the name of the array, 
column values, but missing to correct the array type. 

Thank you very much! Sorry for this.
> 
> > /////////// With each iteration of the for loop, the strtol function
> > looks for numerical values in ptr_buffer, converts them into
> > integers, and stops at the first non-numerical character,
> > comma in this case, storing the pointer to the unconverted
> > string in ptr_buffer; the loop moves ptr_buffer to the next
> > address after the comma, where the next numerical character
> > is; this process goes on until the *ptr_buffer is '\0'//////////////
> 
> I know I promised not to deconstruct your code, but I think I'd be very 
> wary about using the same pointer to do both jobs in the same line. I'd 
> prefer to see a structure such as this:
> 
>    n = strtol(p, &q, 10);
>    if(q > p)
>    {
>      /* q is not p, so we got some data, so we can: */
>      x[y] = n; /* (a) use n, AND: */
>      if(*q != '\0')
>      {
>        p = q + 1; /* (b) move p on past the comma */
>      }
>    }
> } /* (c) and go round our parse loop again. */
> 
> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within
0
Alla
12/21/2016 10:06:19 AM
<snip>
> I know I promised not to deconstruct your code, but I think I'd be very 
> wary about using the same pointer to do both jobs in the same line. I'd 
> prefer to see a structure such as this:
> 
>    n = strtol(p, &q, 10);
>    if(q > p)
>    {
>      /* q is not p, so we got some data, so we can: */
>      x[y] = n; /* (a) use n, AND: */
>      if(*q != '\0')
>      {
>        p = q + 1; /* (b) move p on past the comma */
>      }
>    }
> } /* (c) and go round our parse loop again. */
> 
Thank you! Yes, I have one of the versions that has a similar approach;
I called my end string 'not_converted' for clarity. I have finally decided 
to use the same pointer, i.e. ptr_buffer. I will correct my primary code
now to implement these changes, as you suggest. 
<snip>
0
Alla
12/21/2016 10:12:08 AM
On 21/12/16 10:12, Alla _ wrote:
<snip>
> I have finally decided
> to use the same pointer, i.e. ptr_buffer.

Context: a strtol call of the form n = strtol(p, &p, 10);

Alla, I think that's a big mistake. I am not as well-informed as I 
should be about the restrict keyword that was introduced in C99 and 
which has been tacked onto strtol's first two parameter declarations, so 
perhaps others would like to comment on its relevance here.

But, even /without aliasing/ considerations, writing the code that way 
means you lose an important ability:

n = strtol(p, &q, 10);

allows you to do this:

if(q > p)
{
   you know that some data was converted.

If you overwrite your pointer, you can't do that.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 10:37:09 AM
On Wed, 21 Dec 2016 00:12:58 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

<snip>

I'm confused

>INPUT 
>Years,2011,2012,2013,2014,2015

<snip>

>OUTPUT (skipping the middle part to save the space)
>(1) BUFFER:: Years,2011,2012,2013,2014,2015,

<snip>

>int main(int argc, char *argv[])
>{
>    //Check for correct number of arguments
>    if(argc > 2)
>    {
>        fputs("Sorry, the program processes only one file.\n", stderr);
>        return EXIT_FAILURE;
>    }
>    //Determine a file to use
>    const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
>    
>    FILE *fp = fopen(data_file, "r");
>    
>    if ( fp )
>    {
>        char buffer[BUFFER_SIZE] = "";
>        char array_values[50][50] = {{0}};
>        int function_values_success;
>        size_t line_number_values = 0;
>        
>        //Read each line from the file, store in the buffer
>        while(fgets(buffer, sizeof(buffer), fp) != NULL)

This should have read the first line of your input.  The last
character in the line before the '\n' is '5'.

>        {
>            /*******************/
>            //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
>            putchar('\n');
>            printf("(1) BUFFER:: %s", buffer);

This prints out that exact line.  WHY DOES YOU OUTPUT CONTAIN A
TRAILING COMMA?

-- 
Remove del for email
0
Barry
12/21/2016 10:43:59 AM
Alla _ <modelling.data@gmail.com> writes:
<snip>
> INPUT 
> Years,2011,2012,2013,2014,2015
<snip>

> OUTPUT (skipping the middle part to save the space)
> (1) BUFFER:: Years,2011,2012,2013,2014,2015,

I can't see how this could be the output from the input shown.  Are you
100% sure that the input, output and program are all in sync?  I.e. that
this output is from the posted program given the input above?

Here's why:

>         while(fgets(buffer, sizeof(buffer), fp) != NULL)
>         {
>             /*******************/
>             //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
>             putchar('\n');
>             printf("(1) BUFFER:: %s", buffer);

How can this produce a line ending with a comma given the input shown?

<snip>
-- 
Ben.
0
Ben
12/21/2016 10:46:23 AM
On Wed, 21 Dec 2016 01:44:31 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

>On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
>> [First things first: I've found your problem. Well, okay, I've found at 
>> least one problem, and it's a doozie. Read on.]
>> 
>> On 21/12/16 08:12, Alla _ wrote:
>> >
>> > Please, do me a favor and do not comment on the overall approach;
>> 
>> I will somewhat reluctantly agree to that on this occasion, apart from 
>> one moan (see below).
>> 
>> > This test piece demonstrates a function that should take only those
>> > parts of the line, which contain numerical characters
>> > and turn them into integers. I am using the same for loop I have already
>> > used, with the strtol function. I have added my understanding of the
>> > way the loop works within the function separated by //////    //////
>> > to distinguish these lines from all other comments.
>> 
>> Here's the moan. Single-line comments // work for single lines.
>> 
>> // They don't work
>> for multiple lines,
>> not even a little bit.
>> 
>> /*
>>       If you have to add a multi-line comment into C source
>>       (and it does happen from time to time), then this is
>>       how you do it.
>>   */
>> 
>> > INPUT
>> > Years,2011,2012,2013,2014,2015
>> > Sales,1062,1252,1587,1934,2519
>> > Cost of Goods Sold,654,814,1009,1190,1499
>> >   Gross Profit,408,438,578,744,1020
>> > "Selling, General, and Admin Exp",254,271,364,454,576
>> >   Operating Income before Depr,154,167,214,290,444
>> > Depreciation and Amortization,25,31,38,52,70
>> >   Operating Profit,129,136,176,238,374
>> > Interest Expense,4,3,3,1,4
>> > Other Gains and Losses,0,7,10,0,-1
>> >   Pretax Income,125,126,163,237,371
>> > Income Tax Expense,55,52,65,92,141
>> >   Net Income,70,74,98,145,230
>> 
>> For me, this is test5.csv:
>> 
>> ... 476 Dec 15 13:40 test1.csv
>> ... 492 Dec 15 13:40 test2.csv
>> ... 502 Dec 15 19:20 test3.csv
>> ... 516 Dec 16 11:25 test4.csv
>> ... 492 Dec 21 08:52 test5.csv
>> 
>> and a diff shows that it's identical to test2.csv. I have no problem 
>> with the test data at this stage.
>> 
>> > int fill_row_values(char *buffer, char array_values[][50],
>> >                     size_t *line_number_values, size_t *index,
>> >                                         size_t *values_index)
>> 
>> Let's start here. char array_values[][50]. Not the way I would have done 
>> it, but okay, it's the way /you/ are doing it. But let's bear in mind 
>> that we have storage for 50 rows of 50 chars.
>> 
>I have not yet read the whole post till the end, and, oh oh oh, char * array_values!
>No, I could not have missed that. How could I have not changed that into 
>int or other types of the sort... A few days staring at the function, working 
>with it, writing out every single step, and not spotting this char thing ) Oh.

Please learn to trim your posts.  There were 127 more quoted lines
from Richard that had nothing to do with your response.  In fact, you
claimed to have not even read them.

-- 
Remove del for email
0
Barry
12/21/2016 10:49:34 AM
On Wednesday, December 21, 2016 at 1:46:32 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
> <snip>
> > INPUT 
> > Years,2011,2012,2013,2014,2015
> <snip>
> 
> > OUTPUT (skipping the middle part to save the space)
> > (1) BUFFER:: Years,2011,2012,2013,2014,2015,
> 
> I can't see how this could be the output from the input shown.  Are you
> 100% sure that the input, output and program are all in sync?  I.e. that
> this output is from the posted program given the input above?
> 
> Here's why:
> 
> >         while(fgets(buffer, sizeof(buffer), fp) != NULL)
> >         {
> >             /*******************/
> >             //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
> >             putchar('\n');
> >             printf("(1) BUFFER:: %s", buffer);
> 
> How can this produce a line ending with a comma given the input shown?
> 
Oh, I am sorry. Indeed. I have opened an identical file, but the one, in which
I have eliminated trailing commas. Sorry. Names and numbers are all the same.
I am sorry. 
> <snip>
> -- 
> Ben.
0
Alla
12/21/2016 10:50:13 AM
On Wednesday, December 21, 2016 at 1:49:41 PM UTC+3, Barry Schwarz wrote:
> On Wed, 21 Dec 2016 01:44:31 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
> 
> >On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
> >> [First things first: I've found your problem. Well, okay, I've found at 
> >> least one problem, and it's a doozie. Read on.]
> >> 
> >> On 21/12/16 08:12, Alla _ wrote:
><snip>
> Please learn to trim your posts.  There were 127 more quoted lines
> from Richard that had nothing to do with your response.  In fact, you
> claimed to have not even read them.
> 
Yes, I do my best. I have been asked to do this many times, and there
are times I fail in doing this. Truly sorry, and will do my best not to cause
this annoyance again. 
> -- 
> Remove del for email
0
Alla
12/21/2016 10:51:59 AM
On Wed, 21 Dec 2016 10:37:09 +0000, Richard Heathfield wrote:
> On 21/12/16 10:12, Alla _ wrote:
> <snip>
>> I have finally decided
>> to use the same pointer, i.e. ptr_buffer.
> 
> Context: a strtol call of the form n = strtol(p, &p, 10);
> 
> Alla, I think that's a big mistake. I am not as well-informed as I 
> should be about the restrict keyword that was introduced in C99 and 
> which has been tacked onto strtol's first two parameter declarations, so 
> perhaps others would like to comment on its relevance here.

There is no aliasing problem here, at least as far as strtol's use of
'restrict' is concerned.

There are two restrict-qualified pointers in strtol's prototype:

  char * restrict str, char ** restrict endptr

Essentially this says that, inside the strtol call, the object(s)
accessed using the first pointer's value (the 'char's that make up
the the string processed by strtol) must must not be the same as
the object accesed using the second pointer's value (a 'char *').

Going back to the original example:

  strtol(p, &p, 10)

This would only be a problem from the 'restrict' perspective if p points
to its own object representation (and therefore the two arguments point
to overlapping objects).
0
Nick
12/21/2016 7:58:10 PM
On 21/12/16 19:58, Nick Bowler wrote:
> On Wed, 21 Dec 2016 10:37:09 +0000, Richard Heathfield wrote:
>> On 21/12/16 10:12, Alla _ wrote:
>> <snip>
>>> I have finally decided
>>> to use the same pointer, i.e. ptr_buffer.
>>
>> Context: a strtol call of the form n = strtol(p, &p, 10);
>>
>> Alla, I think that's a big mistake. I am not as well-informed as I
>> should be about the restrict keyword that was introduced in C99 and
>> which has been tacked onto strtol's first two parameter declarations, so
>> perhaps others would like to comment on its relevance here.
>
> There is no aliasing problem here, at least as far as strtol's use of
> 'restrict' is concerned.
>
> There are two restrict-qualified pointers in strtol's prototype:
>
>   char * restrict str, char ** restrict endptr
>
> Essentially this says that, inside the strtol call, the object(s)
> accessed using the first pointer's value (the 'char's that make up
> the the string processed by strtol) must must not be the same as
> the object accesed using the second pointer's value (a 'char *').
>
> Going back to the original example:
>
>   strtol(p, &p, 10)
>
> This would only be a problem from the 'restrict' perspective if p points
> to its own object representation (and therefore the two arguments point
> to overlapping objects).

Thank you, Nick, for that summary.

Of course, this still leaves the /other/ reason for avoiding the 
construct, which is that using two separate pointers makes it possible 
to compare their values after the call.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/21/2016 8:14:59 PM
On Wednesday, December 21, 2016 at 12:31:25 PM UTC+3, Richard Heathfield wrote:
> [First things first: I've found your problem. Well, okay, I've found at 
> least one problem, and it's a doozie. Read on.]
> 
> On 21/12/16 08:12, Alla _ wrote:
> >
<snip>
> I know I promised not to deconstruct your code, but I think I'd be very 
> wary about using the same pointer to do both jobs in the same line. I'd 
> prefer to see a structure such as this:
> 
>    n = strtol(p, &q, 10);
>    if(q > p)
>    {
>      /* q is not p, so we got some data, so we can: */
>      x[y] = n; /* (a) use n, AND: */
>      if(*q != '\0')
>      {
>        p = q + 1; /* (b) move p on past the comma */
>      }
>    }
> } /* (c) and go round our parse loop again. */
> 
As I have promised I am getting back to this part because it doesn't 
work the way expected. Please, take a look at the code below -
I comment on what is happening within the for loop. I have commented
out the part that doesn't work and my explanation. Interesting that 
ptr_buffer is not moved upon call to strtol. Why is that? 
For example: 
ptr_buffer is 2011,2012,2013,2014,2015 before call to strtol
and it is the same after the strtol, while not_converted is 
exactly as it should be ,2012,2013,2014,2015 after the call.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define BUFFER_SIZE 100
#define INCOME_STATEMENT "files/income_test.csv"

int fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index);

int main(int argc, char *argv[])
{
    //Check for correct number of arguments
    if(argc > 2)
    {
        fputs("Sorry, the program processes only one file.\n", stderr);
        return EXIT_FAILURE;
    }
    //Determine a file to use
    const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
    
    FILE *fp = fopen(data_file, "r");
    
    if ( fp )
    {
        char buffer[BUFFER_SIZE] = "";
        int array_values[50][50] = {{0}};
        int function_values_success;
        size_t line_values = 0;
        
        //Read each line from the file, store in the buffer
        while(fgets(buffer, sizeof(buffer), fp) != NULL)
        {
            /*******************/
            //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
            putchar('\n');
            printf("(1) BUFFER:: %s", buffer);
            /*******************/
            
            size_t index = 0;

            while(!isdigit(buffer[index++]));
            index--;
            size_t values_index = 0;
            
            if((function_values_success = fill_row_values(buffer, array_values, &line_values, &index, &values_index)) == EXIT_SUCCESS)
            {
                line_values++;
                
                /*******************/
                //DEBUG: LINE_NUMBER_VALUES && INDEXES
                printf("(1.7) Line number values after the fun_values = %zu\n",
                       line_values);
                printf("(1.8) Index after the fun_values = %zu\n",
                       index);
                printf("(1.9) Values_Index after the fun_values = %zu\n",
                       values_index);
                /*******************/
                
                /*******************/
                //DEBUG: CHECK IF VALUES ARE FILLED CORRECTLY
                putchar('\n');
                printf("(2) ");
                for (size_t j = 0; j < values_index; j++)
                    printf("%d ", array_values[line_values-1][j]);
                putchar('\n');
                /*******************/
                
            }
            else
            {
                printf("The function_values failed\n");
                return EXIT_FAILURE;
            }
        }
        if (ferror(fp))
        {
            puts("Something went wrong with the provided file\n");
            return EXIT_FAILURE;
        }
        fclose(fp);
    }
    //Couldn't open the file
    else
    {
        perror(data_file);
    }
    return 0;
}

int fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
{
    char *ptr_buffer = NULL;
    char *not_converted = NULL;
    ptr_buffer = &buffer[*index];
    size_t values_column;
    int values;
    
    /*******************/
    //DEBUG: LINE_NUMBER & INDEX
    printf("(1.2) Line number passed to fun_values = %zu\n",
           *line_values);
    printf("(1.3) Index number passed to fun_values = %zu\n",
           *index);
    //DEBUG: CHECK PTR_BUFFER
    printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
    /*******************/

    
    //Parse each line's comma-separated values into 'array_values'
    for ( values_column = 0; *ptr_buffer != '\0';
         values_column++, /**ptr_buffer++,**/ (*index)++)
    {
        values = (int)strtol(ptr_buffer, &not_converted, 10);
        
        /*******************/
        //DEBUG: LENGTH OF PTR_BUF, NOT_CONVERTED, AND THEIR CONTENT
        //printf("(1.5) ptr_buf len = %lu and not_converted len = %lu\n", strlen(ptr_buffer), strlen(not_converted));
        //printf("(1.6) Ptr_buf:: %s\n Not_converted:: %s\n Values = %d\n", ptr_buffer, not_converted, values);
        /*******************/
        
        /****
         Test if(not_converted > ptr_buffer) doesn't work at 
         this stage because ptr_buffer still points at the 
         location before the integer was converted; hence
         ptr_buffer > not_converted
         ****/
         /****
         if(not_converted > ptr_buffer)
        {
            array_values[*line_values][values_column] = values;
            if(*not_converted != '\0')
                ptr_buffer = not_converted + 1;
        }
          ****/
        
        array_values[*line_values][values_column] = values;
        if(*not_converted != '\0')
            ptr_buffer = not_converted + 1;
        
        (*values_index)++;
    }
    putchar('\n');
    //Check if conversion was successful
    if(*ptr_buffer)
    {
        printf("Conversion failed; not converted string: %s\n",
               ptr_buffer);
        return EXIT_FAILURE;
    }
    
    return EXIT_SUCCESS;
}


> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within
0
Alla
12/23/2016 4:30:09 PM
On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

<snip>

>As I have promised I am getting back to this part because it doesn't 
>work the way expected. Please, take a look at the code below -
>I comment on what is happening within the for loop. I have commented
>out the part that doesn't work and my explanation. Interesting that 
>ptr_buffer is not moved upon call to strtol. Why is that? 
>For example: 
>ptr_buffer is 2011,2012,2013,2014,2015 before call to strtol
>and it is the same after the strtol, while not_converted is 
>exactly as it should be ,2012,2013,2014,2015 after the call.
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <ctype.h>
>#include <string.h>

<snip 85 lines unrelated to the question>

>int fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
>{
>    char *ptr_buffer = NULL;
>    char *not_converted = NULL;
>    ptr_buffer = &buffer[*index];
>    size_t values_column;
>    int values;
>    
>    /*******************/
>    //DEBUG: LINE_NUMBER & INDEX
>    printf("(1.2) Line number passed to fun_values = %zu\n",
>           *line_values);
>    printf("(1.3) Index number passed to fun_values = %zu\n",
>           *index);
>    //DEBUG: CHECK PTR_BUFFER
>    printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
>    /*******************/
>
>    
>    //Parse each line's comma-separated values into 'array_values'
>    for ( values_column = 0; *ptr_buffer != '\0';
>         values_column++, /**ptr_buffer++,**/ (*index)++)
>    {
>        values = (int)strtol(ptr_buffer, &not_converted, 10);
>        
>        /*******************/
>        //DEBUG: LENGTH OF PTR_BUF, NOT_CONVERTED, AND THEIR CONTENT
>        //printf("(1.5) ptr_buf len = %lu and not_converted len = %lu\n", strlen(ptr_buffer), strlen(not_converted));
>        //printf("(1.6) Ptr_buf:: %s\n Not_converted:: %s\n Values = %d\n", ptr_buffer, not_converted, values);
>        /*******************/
>        
>        /****
>         Test if(not_converted > ptr_buffer) doesn't work at 
>         this stage because ptr_buffer still points at the 
>         location before the integer was converted; hence
>         ptr_buffer > not_converted

How can you possibly come to such an absurd conclusion?
     ptr_buffer is passed by value so strtol cannot change its
contents.
     strtol will always store something in not_converted so its value
will always be updated
     The value stored in not_converted must be one of two possible
addresses:
          If strtol did not convert any value, it will store the
address contained in ptr_buffer.
          If strtol did convert some portion of the buffer, it will
store the address of the first character that did not participate in
the conversion.  This character must have a higher address than the
one contained in prt_buffer.
     Therefore, there is no way ptr_buffer can be greater than
not_converted.  When no data is converted, the two pointers will be
equal.  In all cases, ptr_buffer <= not_converted.

>         ****/
>         /****
>         if(not_converted > ptr_buffer)
>        {
>            array_values[*line_values][values_column] = values;
>            if(*not_converted != '\0')
>                ptr_buffer = not_converted + 1;
>        }
>          ****/
>        
>        array_values[*line_values][values_column] = values;
>        if(*not_converted != '\0')
>            ptr_buffer = not_converted + 1;
>        
>        (*values_index)++;
>    }

Why present us with your fallback code that doesn't do what you want.
Richard gave you a solution to the problem that required you to do
little more than change some variable names.  You should attempt to
implement that solution.  If you implementation doesn't do what you
want, post it and ask questions.  

When you post, we don't need a long dissertation on what you don't
want comments on nor do we need a bunch of functions unrelated to your
specific question.  Show us the function, its input (in this case one
line is sufficient), the actual output if any, and how this differs
from the desired output.

>    putchar('\n');
>    //Check if conversion was successful
>    if(*ptr_buffer)
>    {
>        printf("Conversion failed; not converted string: %s\n",
>               ptr_buffer);
>        return EXIT_FAILURE;
>    }
>    
>    return EXIT_SUCCESS;
>}

I also suggest that you stop trying to build the entire program at
once.  Design, develop, code, and test one function till it does what
you want.  Then move on to the next.  It will also be easier for you
and us if the functions were in separate source modules.

-- 
Remove del for email
0
Barry
12/23/2016 11:16:55 PM
On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
> 
> <snip>
> 
> >As I have promised I am getting back to this part because it doesn't 
> >work the way expected. Please, take a look at the code below -
> >I comment on what is happening within the for loop. I have commented
> >out the part that doesn't work and my explanation. Interesting that 
> >ptr_buffer is not moved upon call to strtol. Why is that? 
> >For example: 
> >ptr_buffer is 2011,2012,2013,2014,2015 before call to strtol
> >and it is the same after the strtol, while not_converted is 
> >exactly as it should be ,2012,2013,2014,2015 after the call.
> >
> >#include <stdio.h>
> >#include <stdlib.h>
> >#include <ctype.h>
> >#include <string.h>
> 
> <snip 85 lines unrelated to the question>
> 
> >int fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
> >{
> >    char *ptr_buffer = NULL;
> >    char *not_converted = NULL;
> >    ptr_buffer = &buffer[*index];
> >    size_t values_column;
> >    int values;
> >    
> >    /*******************/
> >    //DEBUG: LINE_NUMBER & INDEX
> >    printf("(1.2) Line number passed to fun_values = %zu\n",
> >           *line_values);
> >    printf("(1.3) Index number passed to fun_values = %zu\n",
> >           *index);
> >    //DEBUG: CHECK PTR_BUFFER
> >    printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
> >    /*******************/
> >
> >    
> >    //Parse each line's comma-separated values into 'array_values'
> >    for ( values_column = 0; *ptr_buffer != '\0';
> >         values_column++, /**ptr_buffer++,**/ (*index)++)
> >    {
> >        values = (int)strtol(ptr_buffer, &not_converted, 10);
> >        
> >        /*******************/
> >        //DEBUG: LENGTH OF PTR_BUF, NOT_CONVERTED, AND THEIR CONTENT
> >        //printf("(1.5) ptr_buf len = %lu and not_converted len = %lu\n", strlen(ptr_buffer), strlen(not_converted));
> >        //printf("(1.6) Ptr_buf:: %s\n Not_converted:: %s\n Values = %d\n", ptr_buffer, not_converted, values);
> >        /*******************/
> >        
> >        /****
> >         Test if(not_converted > ptr_buffer) doesn't work at 
> >         this stage because ptr_buffer still points at the 
> >         location before the integer was converted; hence
> >         ptr_buffer > not_converted
> 
> How can you possibly come to such an absurd conclusion?
>      ptr_buffer is passed by value so strtol cannot change its
> contents.
Have I used an incorrect wording again? I didn't mean that strtol
changes the contents of ptr_buffer, but moves the pointer to
the address, at which the first non numerical value is stored, 
comma in this case.  
<snip>
0
Alla
12/24/2016 6:36:21 AM
On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
> 
<snip>
> How can you possibly come to such an absurd conclusion?
>      ptr_buffer is passed by value so strtol cannot change its
> contents.
>      strtol will always store something in not_converted so its value
> will always be updated
>      The value stored in not_converted must be one of two possible
> addresses:
>           If strtol did not convert any value, it will store the
> address contained in ptr_buffer.
>           If strtol did convert some portion of the buffer, it will
> store the address of the first character that did not participate in
> the conversion.  This character must have a higher address than the
> one contained in prt_buffer.
"higher address" I see. Indeed. 
>      Therefore, there is no way ptr_buffer can be greater than
> not_converted.  When no data is converted, the two pointers will be
> equal.  In all cases, ptr_buffer <= not_converted.
> 
> >         ****/
> >         /****
> >         if(not_converted > ptr_buffer)
> >        {
> >            array_values[*line_values][values_column] = values;
> >            if(*not_converted != '\0')
> >                ptr_buffer = not_converted + 1;
> >        }
> >          ****/
> >        
> >        array_values[*line_values][values_column] = values;
> >        if(*not_converted != '\0')
> >            ptr_buffer = not_converted + 1;
> >        
> >        (*values_index)++;
> >    }
> 
> Why present us with your fallback code that doesn't do what you want.
> Richard gave you a solution to the problem that required you to do
> little more than change some variable names.  You should attempt to
> implement that solution.  If you implementation doesn't do what you
> want, post it and ask questions.  
> 
> When you post, we don't need a long dissertation on what you don't
> want comments on nor do we need a bunch of functions unrelated to your
> specific question.  Show us the function, its input (in this case one
> line is sufficient), the actual output if any, and how this differs
> from the desired output.
You are absolutely right. I have degraded into too much verbiage. 
Will do my best to correct that. Bear with me, if it is still possible.

<snip>
> I also suggest that you stop trying to build the entire program at
> once.  Design, develop, code, and test one function till it does what
> you want.  Then move on to the next.  It will also be easier for you
> and us if the functions were in separate source modules.
> 
Yes, this is exactly what I did. I should have posted them separately,
like I did here, before posting the entire piece as I did in another thread. 
> -- 
> Remove del for email
0
Alla
12/24/2016 6:45:26 AM
On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
> 
> <snip>
<snip>
Please, take a look at this function (I post it accompanied by the main 
function). I have found one mistake I made, but I still can't cope with 
the suggested version - it doesn't do the job, see below why.

The previous version (I post it below the new one), in which I don't use
if(*not_converted != '\0')
                ptr_buffer = not_converted + 1;
within the for loop, instead use ptr_buffer++ as a loop's increment,
I get the desired result.

The new version has the following fault, but not because of C,
but because of the input the function gets. 
Please, skim through my explanation. I will be grateful for your
comments and opinion.
I use the fist line of the input as an example.

## when the for loop starts, values_column = 0, and 
ptr_buffer points at 2011,2012,2013,2014,2015
and has the address ptr_buf = 0x7fff50897b46
(on my machine)
## strtol converts 2011 to an integer, stops at 
ptr_buffer pointing at ','; now not_converted points at
,2012,2013,2014,2015,
and not_converted has the address 0x7fff50897b4a,
which is bigger than the address of ptr_buffer, as 
expected by 5 (address ended with ..6 points at 2, 
address ended with ...a points at comma);

## upon assigning the integer value to the array[row][column],
the program moves ptr_buffer to point to the next numerical
value after the comma by  ptr_buffer = not_converted + 1;
so now the address of ptr_buffer is 0x7fff50897b4b (was ..4a, 
now ..4b, all good); and ptr_buffer now points at 2, and the 
next loop iteration starts with ptr_buffer pointing at 
2012,2013,2014,2015

## on and on it goes, until ptr_buffer points at the last numeric 
character 5 and values, after call to strtol, = 2015; this is where 
the problem starts because not_converted is still bigger than 
ptr_buffer *if* the line contains some trailing garbage:

ptr_buffer = 0x7fff53fefb5a
not_converted = 0x7fff53fefb5e (that is the address of the 
trailing thing); 

so not_converted points to that trailing garbage, hence 
'not_converted > ptr_buffer' is true; and the value of that 
trailing thing is not '\0';

therefore ptr_buffer = not_converted + 1 still holds, and at
this point ptr_buffer = 0x7fff53fefb5f and that might be
the address of '\0', or of some other, next, trailing garbage;

therefore, next iteration of the loop starts with
ptr_buffer = 0x7fff53fefb5f, and if it doesn't point at '\0',
then this address contains neither numerical value,
nor '\0', but something else; hence not_converted has the 
same address as ptr_buffer upon call to strtol.
ptr_buffer == not_converted == 0x7fff53fefb5f

See the problem here? 
1) I could have returned True at this point, because 
the array is now filled with numbers;
2) but at the same time I can't return True here,
because the test ptr_buffer == not_converted
is a valuable one indicating that there is nothing to
convert, and is usually used to signal failure, not a 
success.
At the moment I return false here until I figure out
what to do with this issue.
Therefore, it seems that if(not_converted > ptr_buffer)
test is not suitable for purposes of this program,
until I resolve the issue of clearing all potential 
trailing garbage in line read from CSV files. 

Here is the program (there are lots of printf debugging):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>

#define BUFFER_SIZE 100
#define INCOME_STATEMENT "files/income_test.csv"

bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index);

int main(int argc, char *argv[])
{
    //Check for correct number of arguments
    if(argc > 2)
    {
        fputs("Sorry, the program processes only one file.\n", stderr);
        return EXIT_FAILURE;
    }
    //Determine a file to use
    const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
    
    FILE *fp = fopen(data_file, "r");
    
    if ( fp )
    {
        char buffer[BUFFER_SIZE] = "";
        int array_values[50][50] = {{0}};
        size_t line_values = 0;
        
        //Read each line from the file, store in the buffer
        while(fgets(buffer, sizeof(buffer), fp) != NULL)
        {
            /*******************/
            //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
            putchar('\n');
            printf("(1) BUFFER:: %s", buffer);
            /*******************/
            
            size_t index = 0;

            while(!isdigit(buffer[index++]));
            index--;
            size_t values_index = 0;
            
            if(fill_row_values(buffer, array_values, &line_values, &index, &values_index))
            {
                line_values++;
                
                /*******************/
                //DEBUG: LINE_NUMBER_VALUES && INDEXES
                printf("(1.8) Line values after the fun_values = %zu\n",
                       line_values);
                printf("(1.9) Index after the fun_values = %zu\n",
                       index);
                printf("(1.10) Values_Index after the fun_values = %zu\n",
                       values_index);
                /*******************/
                
                /*******************/
                //DEBUG: CHECK IF VALUES ARE FILLED CORRECTLY
                putchar('\n');
                printf("(2) ");
                for (size_t j = 0; j < values_index; j++)
                {
                    //Triple check
                    if(line_values != 0)
                        printf("%d ", array_values[line_values-1][j]);
                    else
                        puts("Line values were not incremented");
                }
                putchar('\n');
                /*******************/
                
            }
            else
            {
                printf("The function_values failed\n");
                return EXIT_FAILURE;
            }
        }
        if (ferror(fp))
        {
            puts("Something went wrong with the provided file\n");
            return EXIT_FAILURE;
        }
        fclose(fp);
    }
    //Couldn't open the file
    else
    {
        perror(data_file);
    }
    return EXIT_SUCCESS;
}

bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
{
    char *ptr_buffer = NULL;
    char *not_converted = NULL;
    ptr_buffer = &buffer[*index];
    size_t values_column;
    int values;
    
    /*******************/
    //DEBUG: LINE_NUMBER & INDEX
    printf("(1.2) Line number passed to fun_values = %zu\n",
           *line_values);
    printf("(1.3) Index number passed to fun_values = %zu\n",
           *index);
    //DEBUG: CHECK PTR_BUFFER
    printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
    /*******************/

    
    //Parse each line's comma-separated values into 'array_values'
    for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
    {
        /*******************/
        //DEBUG: PTR_BUFFER ADDRESS
        printf("(1.5) ptr_buf loop beg = %p\n", (void *)ptr_buffer);
        /*******************/
        
        values = (int)strtol(ptr_buffer, &not_converted, 10);
        
        /*******************/
        //DEBUG: PTR_BUFFER ADDRESS, NOT_CONVERTED ADDRESS
        printf("(1.5.1) ptr_buf = %p\n", (void *)ptr_buffer);
        printf("        not_converted = %p\n", (void *)not_converted);
        printf("(1.6)   Ptr_buf:: %s\n", ptr_buffer);
        printf("        Not_converted:: %s\n", not_converted);
        printf("        Values = %d\n", values);
        /*******************/
        
        if(not_converted > ptr_buffer)
        {
            array_values[*line_values][values_column] = values;
            if(*not_converted != '\0')
            {
                ptr_buffer = not_converted + 1;
                /*******************/
                //DEBUG: PTR_BUFFER ADDRESS
                printf("(1.6.1) ptr_buf loop end = %p\n", (void *)ptr_buffer);
                /*******************/
            }
        }
        else if(not_converted == ptr_buffer)
        {
            
            /*******************/
            //DEBUG: PTR_BUFFER ADDRESS, NOT_CONVERTED ADDRESS
            puts("         Not_conv = ptr_buf => conversion failed or ended correctly");
            printf("        ptr_buf = %p\n", (void *)ptr_buffer);
            printf("        not_converted = %p\n", (void *)not_converted);
            printf("        Ptr_buf:: %s\n", ptr_buffer);
            printf("        Not_converted:: %s\n", not_converted);
            printf("        Values = %d\n", values);
            /*******************/
            return false;
        }
        (*values_index)++;
        
        /*******************/
        //DEBUG: array values
        printf("(1.7) Array_values[%zu]: %d\n\n", values_column, array_values[*line_values][values_column]);
        /*******************/
    }
    putchar('\n');
    //Check if conversion was successful
    if(*ptr_buffer)
    {
        printf("Conversion failed; not converted string: %s\n",
               ptr_buffer);
        return false;
    }
    
    return true;
}

0
Alla
12/24/2016 10:23:32 AM
On 24/12/16 10:23, Alla _ wrote:
> On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
>> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
>> <modelling.data@gmail.com> wrote:
>>
>> <snip>
> <snip>
> Please, take a look at this function (I post it accompanied by the main
> function). I have found one mistake I made, but I still can't cope with
> the suggested version - it doesn't do the job, see below why.

I went to some considerable trouble yesterday to show you how to do this 
properly. And I have in the past shown you exactly how to use strtol.

What is the point of our helping you if you ignore the help and keep on 
asking the same questions?

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/24/2016 11:39:25 AM
On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heathfield wrote:
> On 24/12/16 10:23, Alla _ wrote:
> > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> >> <modelling.data@gmail.com> wrote:
> >>
> >> <snip>
> > <snip>
> > Please, take a look at this function (I post it accompanied by the main
> > function). I have found one mistake I made, but I still can't cope with
> > the suggested version - it doesn't do the job, see below why.
> 
> I went to some considerable trouble yesterday to show you how to do this 
> properly. And I have in the past shown you exactly how to use strtol.
> 
> What is the point of our helping you if you ignore the help and keep on 
> asking the same questions?
I don't understand this. I have tried to implement exactly what you have 
explained to me about strtol, and I show you why I fail to do that, and ask
what I am doing wrong. In response, you yet again say that I have ignored
something, and keep asking same questions. Am I? I have considerably 
analyzed every step of the for loop with strtol approach suggested by 
you to show why I can't implement it, and why I don't see my mistake. 

You know, I don't believe in words, only in facts, and therefore I do understand
how hard it is for you to believe, based only on my words, repeated many times,
how grateful I am for all huge efforts you make to help me. I also have many 
times admitted that I am silly when it comes to such technical issues as 
programming, and to some logical technical things as well, and I do know
that I have wasted 40 years of my life, and only now I am trying to make it 
up for myself and to learn essential staff.  It is up to you to continue helping me
to become more knowledgeable and smart person and to grow further, or quit on me. 
But, please, stop reminding me how dumb I am - I am perfectly aware of that,
and acknowledge that. 
me how dumb I am, I know that; and it is up to you to continue helping me
to improve and grow, or quit on me. 
0
Alla
12/24/2016 11:57:48 AM
On Saturday, December 24, 2016 at 2:58:05 PM UTC+3, Alla _ wrote:
> On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heathfield wrote:
> > On 24/12/16 10:23, Alla _ wrote:
> > > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> > >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > >> <modelling.data@gmail.com> wrote:
> > >>
> > >> <snip>
> > > <snip>
> > > Please, take a look at this function (I post it accompanied by the main
> > > function). I have found one mistake I made, but I still can't cope with
> > > the suggested version - it doesn't do the job, see below why.
> > 
> > I went to some considerable trouble yesterday to show you how to do this 
> > properly. And I have in the past shown you exactly how to use strtol.
> > 
> > What is the point of our helping you if you ignore the help and keep on 
> > asking the same questions?
> I don't understand this. I have tried to implement exactly what you have 
> explained to me about strtol, and I show you why I fail to do that, and ask
> what I am doing wrong. In response, you yet again say that I have ignored
> something, and keep asking same questions. Am I? I have considerably 
> analyzed every step of the for loop with strtol approach suggested by 
> you to show why I can't implement it, and why I don't see my mistake. 
> 
> You know, I don't believe in words, only in facts, and therefore I do understand
> how hard it is for you to believe, based only on my words, repeated many times,
> how grateful I am for all huge efforts you make to help me. I also have many 
> times admitted that I am silly when it comes to such technical issues as 
> programming, and to some logical technical things as well, and I do know
> that I have wasted 40 years of my life, and only now I am trying to make it 
> up for myself and to learn essential staff.  It is up to you to continue helping me
> to become more knowledgeable and smart person and to grow further, or quit on me. 
> But, please, stop reminding me how dumb I am - I am perfectly aware of that,
> and acknowledge that. 
Keyboard typoes, extra reaped line at the end. Please, ignore.
0
Alla
12/24/2016 12:01:56 PM
On Saturday, December 24, 2016 at 1:23:40 PM UTC+3, Alla _ wrote:
> On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> > On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > <modelling.data@gmail.com> wrote:
> > 
> > <snip>
> <snip>
> Please, take a look at this function (I post it accompanied by the main 
> function). I have found one mistake I made, but I still can't cope with 
> the suggested version - it doesn't do the job, see below why.
> 
> The previous version (I post it below the new one), in which I don't use
> if(*not_converted != '\0')
>                 ptr_buffer = not_converted + 1;
> within the for loop, instead use ptr_buffer++ as a loop's increment,
> I get the desired result.
> 
> The new version has the following fault, but not because of C,
> but because of the input the function gets. 
> Please, skim through my explanation. I will be grateful for your
> comments and opinion.
> I use the fist line of the input as an example.
> 
> ## when the for loop starts, values_column = 0, and 
> ptr_buffer points at 2011,2012,2013,2014,2015
> and has the address ptr_buf = 0x7fff50897b46
> (on my machine)
> ## strtol converts 2011 to an integer, stops at 
> ptr_buffer pointing at ','; now not_converted points at
> ,2012,2013,2014,2015,
> and not_converted has the address 0x7fff50897b4a,
> which is bigger than the address of ptr_buffer, as 
> expected by 5 (address ended with ..6 points at 2, 
> address ended with ...a points at comma);
> 
> ## upon assigning the integer value to the array[row][column],
> the program moves ptr_buffer to point to the next numerical
> value after the comma by  ptr_buffer = not_converted + 1;
> so now the address of ptr_buffer is 0x7fff50897b4b (was ..4a, 
> now ..4b, all good); and ptr_buffer now points at 2, and the 
> next loop iteration starts with ptr_buffer pointing at 
> 2012,2013,2014,2015
> 
> ## on and on it goes, until ptr_buffer points at the last numeric 
> character 5 and values, after call to strtol, = 2015; this is where 
> the problem starts because not_converted is still bigger than 
> ptr_buffer *if* the line contains some trailing garbage:
> 
> ptr_buffer = 0x7fff53fefb5a
> not_converted = 0x7fff53fefb5e (that is the address of the 
> trailing thing); 
> 
> so not_converted points to that trailing garbage, hence 
> 'not_converted > ptr_buffer' is true; and the value of that 
> trailing thing is not '\0';
> 
> therefore ptr_buffer = not_converted + 1 still holds, and at
> this point ptr_buffer = 0x7fff53fefb5f and that might be
> the address of '\0', or of some other, next, trailing garbage;
> 
> therefore, next iteration of the loop starts with
> ptr_buffer = 0x7fff53fefb5f, and if it doesn't point at '\0',
> then this address contains neither numerical value,
> nor '\0', but something else; hence not_converted has the 
> same address as ptr_buffer upon call to strtol.
> ptr_buffer == not_converted == 0x7fff53fefb5f
> 
> See the problem here? 
> 1) I could have returned True at this point, because 
> the array is now filled with numbers;
> 2) but at the same time I can't return True here,
> because the test ptr_buffer == not_converted
> is a valuable one indicating that there is nothing to
> convert, and is usually used to signal failure, not a 
> success.
> At the moment I return false here until I figure out
> what to do with this issue.
> Therefore, it seems that if(not_converted > ptr_buffer)
> test is not suitable for purposes of this program,
> until I resolve the issue of clearing all potential 
> trailing garbage in line read from CSV files. 
> 
> Here is the program (there are lots of printf debugging):
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <ctype.h>
> #include <string.h>
> #include <stdbool.h>
> 
> #define BUFFER_SIZE 100
> #define INCOME_STATEMENT "files/income_test.csv"
> 
> bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index);
> 
> int main(int argc, char *argv[])
> {
>     //Check for correct number of arguments
>     if(argc > 2)
>     {
>         fputs("Sorry, the program processes only one file.\n", stderr);
>         return EXIT_FAILURE;
>     }
>     //Determine a file to use
>     const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
>     
>     FILE *fp = fopen(data_file, "r");
>     
>     if ( fp )
>     {
>         char buffer[BUFFER_SIZE] = "";
>         int array_values[50][50] = {{0}};
>         size_t line_values = 0;
>         
>         //Read each line from the file, store in the buffer
>         while(fgets(buffer, sizeof(buffer), fp) != NULL)
>         {
>             /*******************/
>             //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
>             putchar('\n');
>             printf("(1) BUFFER:: %s", buffer);
>             /*******************/
>             
>             size_t index = 0;
> 
>             while(!isdigit(buffer[index++]));
>             index--;
>             size_t values_index = 0;
>             
>             if(fill_row_values(buffer, array_values, &line_values, &index, &values_index))
>             {
>                 line_values++;
>                 
>                 /*******************/
>                 //DEBUG: LINE_NUMBER_VALUES && INDEXES
>                 printf("(1.8) Line values after the fun_values = %zu\n",
>                        line_values);
>                 printf("(1.9) Index after the fun_values = %zu\n",
>                        index);
>                 printf("(1.10) Values_Index after the fun_values = %zu\n",
>                        values_index);
>                 /*******************/
>                 
>                 /*******************/
>                 //DEBUG: CHECK IF VALUES ARE FILLED CORRECTLY
>                 putchar('\n');
>                 printf("(2) ");
>                 for (size_t j = 0; j < values_index; j++)
>                 {
>                     //Triple check
>                     if(line_values != 0)
>                         printf("%d ", array_values[line_values-1][j]);
>                     else
>                         puts("Line values were not incremented");
>                 }
>                 putchar('\n');
>                 /*******************/
>                 
>             }
>             else
>             {
>                 printf("The function_values failed\n");
>                 return EXIT_FAILURE;
>             }
>         }
>         if (ferror(fp))
>         {
>             puts("Something went wrong with the provided file\n");
>             return EXIT_FAILURE;
>         }
>         fclose(fp);
>     }
>     //Couldn't open the file
>     else
>     {
>         perror(data_file);
>     }
>     return EXIT_SUCCESS;
> }
> 
> bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
> {
>     char *ptr_buffer = NULL;
>     char *not_converted = NULL;
>     ptr_buffer = &buffer[*index];
>     size_t values_column;
>     int values;
>     
>     /*******************/
>     //DEBUG: LINE_NUMBER & INDEX
>     printf("(1.2) Line number passed to fun_values = %zu\n",
>            *line_values);
>     printf("(1.3) Index number passed to fun_values = %zu\n",
>            *index);
>     //DEBUG: CHECK PTR_BUFFER
>     printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
>     /*******************/
> 
>     
>     //Parse each line's comma-separated values into 'array_values'
>     for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
>     {
>         /*******************/
>         //DEBUG: PTR_BUFFER ADDRESS
>         printf("(1.5) ptr_buf loop beg = %p\n", (void *)ptr_buffer);
>         /*******************/
>         
>         values = (int)strtol(ptr_buffer, &not_converted, 10);
>         
>         /*******************/
>         //DEBUG: PTR_BUFFER ADDRESS, NOT_CONVERTED ADDRESS
>         printf("(1.5.1) ptr_buf = %p\n", (void *)ptr_buffer);
>         printf("        not_converted = %p\n", (void *)not_converted);
>         printf("(1.6)   Ptr_buf:: %s\n", ptr_buffer);
>         printf("        Not_converted:: %s\n", not_converted);
>         printf("        Values = %d\n", values);
>         /*******************/
>         
>         if(not_converted > ptr_buffer)
>         {
>             array_values[*line_values][values_column] = values;
>             if(*not_converted != '\0')
>             {
>                 ptr_buffer = not_converted + 1;
>                 /*******************/
>                 //DEBUG: PTR_BUFFER ADDRESS
>                 printf("(1.6.1) ptr_buf loop end = %p\n", (void *)ptr_buffer);
>                 /*******************/
>             }
>         }
>         else if(not_converted == ptr_buffer)
>         {
>             
>             /*******************/
>             //DEBUG: PTR_BUFFER ADDRESS, NOT_CONVERTED ADDRESS
>             puts("         Not_conv = ptr_buf => conversion failed or ended correctly");
>             printf("        ptr_buf = %p\n", (void *)ptr_buffer);
>             printf("        not_converted = %p\n", (void *)not_converted);
>             printf("        Ptr_buf:: %s\n", ptr_buffer);
>             printf("        Not_converted:: %s\n", not_converted);
>             printf("        Values = %d\n", values);
>             /*******************/
>             return false;
>         }
>         (*values_index)++;
>         
>         /*******************/
>         //DEBUG: array values
>         printf("(1.7) Array_values[%zu]: %d\n\n", values_column, array_values[*line_values][values_column]);
>         /*******************/
>     }
>     putchar('\n');
       return true;
> }

Deleted extra ending lines, which were leftovers from the previous version.
0
Alla
12/24/2016 12:04:10 PM
On 24/12/16 12:04, Alla _ wrote:
<250 lines snipped>
>
> Deleted extra ending lines, which were leftovers from the previous version.


So, in addition to the 250 plus however-many lines there were in the 
previous article, you posted an EXTRA 250 lines. Why? To save space on 
the server? How does posting 250 lines twice count as deleting /anything/?

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/24/2016 12:14:12 PM
W dniu sobota, 24 grudnia 2016 12:58:05 UTC+1 u=C5=BCytkownik Alla _ napisa=
=C5=82:
> On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heathfield wr=
ote:
> > On 24/12/16 10:23, Alla _ wrote:
> > > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wro=
te:
> > >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > >> <modelling.data@gmail.com> wrote:
> > >>
> > >> <snip>
> > > <snip>
> > > Please, take a look at this function (I post it accompanied by the ma=
in
> > > function). I have found one mistake I made, but I still can't cope wi=
th
> > > the suggested version - it doesn't do the job, see below why.
> >=20
> > I went to some considerable trouble yesterday to show you how to do thi=
s=20
> > properly. And I have in the past shown you exactly how to use strtol.
> >=20
> > What is the point of our helping you if you ignore the help and keep on=
=20
> > asking the same questions?
> I don't understand this. I have tried to implement exactly what you have=
=20
> explained to me about strtol, and I show you why I fail to do that, and a=
sk
> what I am doing wrong. In response, you yet again say that I have ignored
> something, and keep asking same questions. Am I? I have considerably=20
> analyzed every step of the for loop with strtol approach suggested by=20
> you to show why I can't implement it, and why I don't see my mistake.=20
>=20
> You know, I don't believe in words, only in facts, and therefore I do und=
erstand
> how hard it is for you to believe, based only on my words, repeated many =
times,
> how grateful I am for all huge efforts you make to help me. I also have m=
any=20
> times admitted that I am silly when it comes to such technical issues as=
=20
> programming, and to some logical technical things as well, and I do know
> that I have wasted 40 years of my life, and only now I am trying to make =
it=20
> up for myself and to learn essential staff.  It is up to you to continue =
helping me
> to become more knowledgeable and smart person and to grow further, or qui=
t on me.=20
> But, please, stop reminding me how dumb I am - I am perfectly aware of th=
at,
> and acknowledge that.=20
> me how dumb I am, I know that; and it is up to you to continue helping me
> to improve and grow, or quit on me.

tell how old u are.. are you forty? it very depends on age if someone can b=
e "moderately succesfull programer" or if no - starting coding past 30 is p=
robably not much bad idea as in coding one needs usually 10 years to becoma=
 "average"
(or even "average weak") - esp if past 40 i think people learn much slower,=
 and yet there is a fact that later-on programing becomes harder imo not ea=
sier
(thise are maybe some vague statements and may be not=20
strictly true in anycases but mostly it lloks like that i sadly think)
0
fir
12/24/2016 12:20:53 PM
On Saturday, December 24, 2016 at 3:04:17 PM UTC+3, Alla _ wrote:
> On Saturday, December 24, 2016 at 1:23:40 PM UTC+3, Alla _ wrote:
> > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
> > > On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > > <modelling.data@gmail.com> wrote:
<snip>
In this version I have achieved the result and have at least partially solved
the issue with the incorrect input and thus not being able to use the test
if (not_converted > ptr_buffer). What do you think?
INPUT
Years,2011,2012,2013,2014,2015
Sales,1062,1252,1587,1934,2519
Cost of Goods Sold,654,814,1009,1190,1499
  Gross Profit,408,438,578,744,1020
"Selling, General, and Admin Exp",254,271,364,454,576
  Operating Income before Depr,154,167,214,290,444
Depreciation and Amortization,25,31,38,52,70
  Operating Profit,129,136,176,238,374
Interest Expense,4,3,3,1,4
Other Gains and Losses,0,7,10,0,-1
  Pretax Income,125,126,163,237,371
Income Tax Expense,55,52,65,92,141
  Net Income,70,74,98,145,230

OUTPUT (for only two lines)
(1) BUFFER:: Years,2011,2012,2013,2014,2015
(1.2) Line number passed to fun_values = 0
(1.3) Index number passed to fun_values = 6
(1.4) Ptr_buffer:: 2011,2012,2013,2014,2015

(1.5) ptr_buf loop beg = 0x7fff504ecb06
(1.5.1) ptr_buf = 0x7fff504ecb06
        not_converted = 0x7fff504ecb0a
(1.6)   Ptr_buf:: 2011,2012,2013,2014,2015

        Not_converted:: ,2012,2013,2014,2015

        Values = 2011
(1.6.1) ptr_buf loop end = 0x7fff504ecb0b
(1.5) ptr_buf loop beg = 0x7fff504ecb0b
(1.5.1) ptr_buf = 0x7fff504ecb0b
        not_converted = 0x7fff504ecb0f
(1.6)   Ptr_buf:: 2012,2013,2014,2015

        Not_converted:: ,2013,2014,2015

        Values = 2012
(1.6.1) ptr_buf loop end = 0x7fff504ecb10
(1.5) ptr_buf loop beg = 0x7fff504ecb10
(1.5.1) ptr_buf = 0x7fff504ecb10
        not_converted = 0x7fff504ecb14
(1.6)   Ptr_buf:: 2013,2014,2015

        Not_converted:: ,2014,2015

        Values = 2013
(1.6.1) ptr_buf loop end = 0x7fff504ecb15
(1.5) ptr_buf loop beg = 0x7fff504ecb15
(1.5.1) ptr_buf = 0x7fff504ecb15
        not_converted = 0x7fff504ecb19
(1.6)   Ptr_buf:: 2014,2015

        Not_converted:: ,2015

        Values = 2014
(1.6.1) ptr_buf loop end = 0x7fff504ecb1a
(1.5) ptr_buf loop beg = 0x7fff504ecb1a
(1.5.1) ptr_buf = 0x7fff504ecb1a
        not_converted = 0x7fff504ecb1e
(1.6)   Ptr_buf:: 2015

        Not_converted:: 

        Values = 2015
(1.7) Array_values[5]: 0


(1.8) Line values after the fun_values = 1
(1.9) Index after the fun_values = 11
(1.10) Values_Index after the fun_values = 5

(2) 2011 2012 2013 2014 2015 

(1) BUFFER:: Sales,1062,1252,1587,1934,2519
(1.2) Line number passed to fun_values = 1
(1.3) Index number passed to fun_values = 6
(1.4) Ptr_buffer:: 1062,1252,1587,1934,2519

(1.5) ptr_buf loop beg = 0x7fff504ecb06
(1.5.1) ptr_buf = 0x7fff504ecb06
        not_converted = 0x7fff504ecb0a
(1.6)   Ptr_buf:: 1062,1252,1587,1934,2519

        Not_converted:: ,1252,1587,1934,2519

        Values = 1062
(1.6.1) ptr_buf loop end = 0x7fff504ecb0b
(1.5) ptr_buf loop beg = 0x7fff504ecb0b
(1.5.1) ptr_buf = 0x7fff504ecb0b
        not_converted = 0x7fff504ecb0f
(1.6)   Ptr_buf:: 1252,1587,1934,2519

        Not_converted:: ,1587,1934,2519

        Values = 1252
(1.6.1) ptr_buf loop end = 0x7fff504ecb10
(1.5) ptr_buf loop beg = 0x7fff504ecb10
(1.5.1) ptr_buf = 0x7fff504ecb10
        not_converted = 0x7fff504ecb14
(1.6)   Ptr_buf:: 1587,1934,2519

        Not_converted:: ,1934,2519

        Values = 1587
(1.6.1) ptr_buf loop end = 0x7fff504ecb15
(1.5) ptr_buf loop beg = 0x7fff504ecb15
(1.5.1) ptr_buf = 0x7fff504ecb15
        not_converted = 0x7fff504ecb19
(1.6)   Ptr_buf:: 1934,2519

        Not_converted:: ,2519

        Values = 1934
(1.6.1) ptr_buf loop end = 0x7fff504ecb1a
(1.5) ptr_buf loop beg = 0x7fff504ecb1a
(1.5.1) ptr_buf = 0x7fff504ecb1a
        not_converted = 0x7fff504ecb1e
(1.6)   Ptr_buf:: 2519

        Not_converted:: 

        Values = 2519
(1.7) Array_values[5]: 0


(1.8) Line values after the fun_values = 2
(1.9) Index after the fun_values = 11
(1.10) Values_Index after the fun_values = 5

(2) 1062 1252 1587 1934 2519 

Same output I get with a more corrupt csv file.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>

#define BUFFER_SIZE 100
#define INCOME_STATEMENT "files/income_test.csv"

bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index);

int main(int argc, char *argv[])
{
    //Check for correct number of arguments
    if(argc > 2)
    {
        fputs("Sorry, the program processes only one file.\n", stderr);
        return EXIT_FAILURE;
    }
    //Determine a file to use
    const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
    
    FILE *fp = fopen(data_file, "r");
    
    if ( fp )
    {
        char buffer[BUFFER_SIZE] = "";
        int array_values[50][50] = {{0}};
        size_t line_values = 0;
        
        //Read each line from the file, store in the buffer
        while(fgets(buffer, sizeof(buffer), fp) != NULL)
        {
            /*******************/
            //DEBUG: CHECK IF BUFFER IS FILLED CORRECTLY
            putchar('\n');
            printf("(1) BUFFER:: %s", buffer);
            /*******************/
            
            size_t index = 0;

            while(!isdigit(buffer[index++]));
            index--;
            size_t values_index = 0;
            
            if(fill_row_values(buffer, array_values, &line_values, &index, &values_index))
            {
                line_values++;
                
                /*******************/
                //DEBUG: LINE_NUMBER_VALUES && INDEXES
                printf("(1.8) Line values after the fun_values = %zu\n",
                       line_values);
                printf("(1.9) Index after the fun_values = %zu\n",
                       index);
                printf("(1.10) Values_Index after the fun_values = %zu\n",
                       values_index);
                /*******************/
                
                /*******************/
                //DEBUG: CHECK IF VALUES ARE FILLED CORRECTLY
                putchar('\n');
                printf("(2) ");
                for (size_t j = 0; j < values_index; j++)
                {
                    //Triple check
                    if(line_values != 0)
                        printf("%d ", array_values[line_values-1][j]);
                    else
                        puts("Line values were not incremented");
                }
                putchar('\n');
                /*******************/
                
            }
            else
            {
                printf("The function_values failed\n");
                return EXIT_FAILURE;
            }
        }
        if (ferror(fp))
        {
            puts("Something went wrong with the provided file\n");
            return EXIT_FAILURE;
        }
        fclose(fp);
    }
    //Couldn't open the file
    else
    {
        perror(data_file);
    }
    return EXIT_SUCCESS;
}

bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
{
    char *ptr_buffer = NULL;
    char *not_converted = NULL;
    ptr_buffer = &buffer[*index];
    size_t values_column;
    int values;
    
    /*******************/
    //DEBUG: LINE_NUMBER & INDEX
    printf("(1.2) Line number passed to fun_values = %zu\n",
           *line_values);
    printf("(1.3) Index number passed to fun_values = %zu\n",
           *index);
    //DEBUG: CHECK PTR_BUFFER
    printf("(1.4) Ptr_buffer:: %s\n", ptr_buffer);
    /*******************/

    
    //Parse each line's comma-separated values into 'array_values'
    for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
    {
        /*******************/
        //DEBUG: PTR_BUFFER ADDRESS
        printf("(1.5) ptr_buf loop beg = %p\n", (void *)ptr_buffer);
        /*******************/
        
        values = (int)strtol(ptr_buffer, &not_converted, 10);
        
        /*******************/
        //DEBUG: PTR_BUFFER ADDRESS, NOT_CONVERTED ADDRESS
        printf("(1.5.1) ptr_buf = %p\n", (void *)ptr_buffer);
        printf("        not_converted = %p\n", (void *)not_converted);
        printf("(1.6)   Ptr_buf:: %s\n", ptr_buffer);
        printf("        Not_converted:: %s\n", not_converted);
        printf("        Values = %d\n", values);
        /*******************/
        
        array_values[*line_values][values_column] = values;
        
        if(not_converted > ptr_buffer && *not_converted != '\0')
        {
            if(isdigit(*(not_converted + 1)))
            {
              ptr_buffer = not_converted + 1;
                
              /*******************/
              //DEBUG: PTR_BUFFER ADDRESS
              printf("(1.6.1) ptr_buf loop end = %p\n", (void *)ptr_buffer);
              /*******************/
            }
            else
                *ptr_buffer = '\0';
        }
        
        if(not_converted == ptr_buffer)
        {
            /*******************/
            //DEBUG: PTR_BUFFER ADDRESS, NOT_CONVERTED ADDRESS
            puts("         Not_conv = ptr_buf => conversion failed or ended correctly");
            printf("        ptr_buf = %p\n", (void *)ptr_buffer);
            printf("        not_converted = %p\n", (void *)not_converted);
            printf("        Ptr_buf:: %s\n", ptr_buffer);
            printf("        Not_converted:: %s\n", not_converted);
            printf("        Values = %d\n", values);
            /*******************/
            return false;
       }
        (*values_index)++;
    }
    
    
        /*******************/
        //DEBUG: array values
        printf("(1.7) Array_values[%zu]: %d\n\n", values_column, array_values[*line_values][values_column]);
        /*******************/
    putchar('\n');
    return true;
}

0
Alla
12/24/2016 12:32:01 PM
On Saturday, December 24, 2016 at 3:21:00 PM UTC+3, fir wrote:
> W dniu sobota, 24 grudnia 2016 12:58:05 UTC+1 u=C5=BCytkownik Alla _ napi=
sa=C5=82:
> > On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heathfield =
wrote:
> > > On 24/12/16 10:23, Alla _ wrote:
> > > > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz w=
rote:
> > > >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > > >> <modelling.data@gmail.com> wrote:
> > > >>
> > > >> <snip>
> > > > <snip>
> > > > Please, take a look at this function (I post it accompanied by the =
main
> > > > function). I have found one mistake I made, but I still can't cope =
with
> > > > the suggested version - it doesn't do the job, see below why.
> > >=20
> > > I went to some considerable trouble yesterday to show you how to do t=
his=20
> > > properly. And I have in the past shown you exactly how to use strtol.
> > >=20
> > > What is the point of our helping you if you ignore the help and keep =
on=20
> > > asking the same questions?
> > I don't understand this. I have tried to implement exactly what you hav=
e=20
> > explained to me about strtol, and I show you why I fail to do that, and=
 ask
> > what I am doing wrong. In response, you yet again say that I have ignor=
ed
> > something, and keep asking same questions. Am I? I have considerably=20
> > analyzed every step of the for loop with strtol approach suggested by=
=20
> > you to show why I can't implement it, and why I don't see my mistake.=
=20
> >=20
> > You know, I don't believe in words, only in facts, and therefore I do u=
nderstand
> > how hard it is for you to believe, based only on my words, repeated man=
y times,
> > how grateful I am for all huge efforts you make to help me. I also have=
 many=20
> > times admitted that I am silly when it comes to such technical issues a=
s=20
> > programming, and to some logical technical things as well, and I do kno=
w
> > that I have wasted 40 years of my life, and only now I am trying to mak=
e it=20
> > up for myself and to learn essential staff.  It is up to you to continu=
e helping me
> > to become more knowledgeable and smart person and to grow further, or q=
uit on me.=20
> > But, please, stop reminding me how dumb I am - I am perfectly aware of =
that,
> > and acknowledge that.=20
> > me how dumb I am, I know that; and it is up to you to continue helping =
me
> > to improve and grow, or quit on me.
>=20
> tell how old u are.. are you forty? it very depends on age if someone can=
 be "moderately succesfull programer" or if no - starting coding past 30 is=
 probably not much bad idea as in coding one needs usually 10 years to beco=
ma "average"
> (or even "average weak") - esp if past 40 i think people learn much slowe=
r, and yet there is a fact that later-on programing becomes harder imo not =
easier
> (thise are maybe some vague statements and may be not=20
> strictly true in anycases but mostly it lloks like that i sadly think)

Trust me age is nothing; one can do and learn anything at any age -=20
all depends on one's set of mind, capability, desire, motivation and overal=
l=20
attitude. People constrain themselves with too many fake boundaries, and=20
that what hampers the development of the majority of population.
0
Alla
12/24/2016 12:34:43 PM
W dniu sobota, 24 grudnia 2016 13:34:51 UTC+1 u=C5=BCytkownik Alla _ napisa=
=C5=82:
> On Saturday, December 24, 2016 at 3:21:00 PM UTC+3, fir wrote:
> > W dniu sobota, 24 grudnia 2016 12:58:05 UTC+1 u=C5=BCytkownik Alla _ na=
pisa=C5=82:
> > > On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heathfiel=
d wrote:
> > > > On 24/12/16 10:23, Alla _ wrote:
> > > > > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz=
 wrote:
> > > > >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > > > >> <modelling.data@gmail.com> wrote:
> > > > >>
> > > > >> <snip>
> > > > > <snip>
> > > > > Please, take a look at this function (I post it accompanied by th=
e main
> > > > > function). I have found one mistake I made, but I still can't cop=
e with
> > > > > the suggested version - it doesn't do the job, see below why.
> > > >=20
> > > > I went to some considerable trouble yesterday to show you how to do=
 this=20
> > > > properly. And I have in the past shown you exactly how to use strto=
l.
> > > >=20
> > > > What is the point of our helping you if you ignore the help and kee=
p on=20
> > > > asking the same questions?
> > > I don't understand this. I have tried to implement exactly what you h=
ave=20
> > > explained to me about strtol, and I show you why I fail to do that, a=
nd ask
> > > what I am doing wrong. In response, you yet again say that I have ign=
ored
> > > something, and keep asking same questions. Am I? I have considerably=
=20
> > > analyzed every step of the for loop with strtol approach suggested by=
=20
> > > you to show why I can't implement it, and why I don't see my mistake.=
=20
> > >=20
> > > You know, I don't believe in words, only in facts, and therefore I do=
 understand
> > > how hard it is for you to believe, based only on my words, repeated m=
any times,
> > > how grateful I am for all huge efforts you make to help me. I also ha=
ve many=20
> > > times admitted that I am silly when it comes to such technical issues=
 as=20
> > > programming, and to some logical technical things as well, and I do k=
now
> > > that I have wasted 40 years of my life, and only now I am trying to m=
ake it=20
> > > up for myself and to learn essential staff.  It is up to you to conti=
nue helping me
> > > to become more knowledgeable and smart person and to grow further, or=
 quit on me.=20
> > > But, please, stop reminding me how dumb I am - I am perfectly aware o=
f that,
> > > and acknowledge that.=20
> > > me how dumb I am, I know that; and it is up to you to continue helpin=
g me
> > > to improve and grow, or quit on me.
> >=20
> > tell how old u are.. are you forty? it very depends on age if someone c=
an be "moderately succesfull programer" or if no - starting coding past 30 =
is probably not much bad idea as in coding one needs usually 10 years to be=
coma "average"
> > (or even "average weak") - esp if past 40 i think people learn much slo=
wer, and yet there is a fact that later-on programing becomes harder imo no=
t easier
> > (thise are maybe some vague statements and may be not=20
> > strictly true in anycases but mostly it lloks like that i sadly think)
>=20
> Trust me age is nothing; one can do and learn anything at any age -=20
> all depends on one's set of mind, capability, desire, motivation and over=
all=20
> attitude. People constrain themselves with too many fake boundaries, and=
=20
> that what hampers the development of the majority of population.

trust me youre sayin bulshit - if no why you (dont know after year of writi=
ng here) youre sticking with preposterous basics ? (its hard to strictly co=
mpare but silled 16-yo could possibly do it 10 faster than you)

nevbies always dream that they learn coding in 5 years
and be great coders when in reality after 30 years in coding they are still=
 average

this "trust me age is nothing" sounds like hodgin,  so many insane people h=
ere
0
fir
12/24/2016 1:10:22 PM
W dniu sobota, 24 grudnia 2016 14:10:31 UTC+1 u=C5=BCytkownik fir napisa=C5=
=82:
> W dniu sobota, 24 grudnia 2016 13:34:51 UTC+1 u=C5=BCytkownik Alla _ napi=
sa=C5=82:
> > On Saturday, December 24, 2016 at 3:21:00 PM UTC+3, fir wrote:
> > > W dniu sobota, 24 grudnia 2016 12:58:05 UTC+1 u=C5=BCytkownik Alla _ =
napisa=C5=82:
> > > > On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heathfi=
eld wrote:
> > > > > On 24/12/16 10:23, Alla _ wrote:
> > > > > > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwa=
rz wrote:
> > > > > >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > > > > >> <modelling.data@gmail.com> wrote:
> > > > > >>
> > > > > >> <snip>
> > > > > > <snip>
> > > > > > Please, take a look at this function (I post it accompanied by =
the main
> > > > > > function). I have found one mistake I made, but I still can't c=
ope with
> > > > > > the suggested version - it doesn't do the job, see below why.
> > > > >=20
> > > > > I went to some considerable trouble yesterday to show you how to =
do this=20
> > > > > properly. And I have in the past shown you exactly how to use str=
tol.
> > > > >=20
> > > > > What is the point of our helping you if you ignore the help and k=
eep on=20
> > > > > asking the same questions?
> > > > I don't understand this. I have tried to implement exactly what you=
 have=20
> > > > explained to me about strtol, and I show you why I fail to do that,=
 and ask
> > > > what I am doing wrong. In response, you yet again say that I have i=
gnored
> > > > something, and keep asking same questions. Am I? I have considerabl=
y=20
> > > > analyzed every step of the for loop with strtol approach suggested =
by=20
> > > > you to show why I can't implement it, and why I don't see my mistak=
e.=20
> > > >=20
> > > > You know, I don't believe in words, only in facts, and therefore I =
do understand
> > > > how hard it is for you to believe, based only on my words, repeated=
 many times,
> > > > how grateful I am for all huge efforts you make to help me. I also =
have many=20
> > > > times admitted that I am silly when it comes to such technical issu=
es as=20
> > > > programming, and to some logical technical things as well, and I do=
 know
> > > > that I have wasted 40 years of my life, and only now I am trying to=
 make it=20
> > > > up for myself and to learn essential staff.  It is up to you to con=
tinue helping me
> > > > to become more knowledgeable and smart person and to grow further, =
or quit on me.=20
> > > > But, please, stop reminding me how dumb I am - I am perfectly aware=
 of that,
> > > > and acknowledge that.=20
> > > > me how dumb I am, I know that; and it is up to you to continue help=
ing me
> > > > to improve and grow, or quit on me.
> > >=20
> > > tell how old u are.. are you forty? it very depends on age if someone=
 can be "moderately succesfull programer" or if no - starting coding past 3=
0 is probably not much bad idea as in coding one needs usually 10 years to =
becoma "average"
> > > (or even "average weak") - esp if past 40 i think people learn much s=
lower, and yet there is a fact that later-on programing becomes harder imo =
not easier
> > > (thise are maybe some vague statements and may be not=20
> > > strictly true in anycases but mostly it lloks like that i sadly think=
)
> >=20
> > Trust me age is nothing; one can do and learn anything at any age -=20
> > all depends on one's set of mind, capability, desire, motivation and ov=
erall=20
> > attitude. People constrain themselves with too many fake boundaries, an=
d=20
> > that what hampers the development of the majority of population.
>=20
> trust me youre sayin bulshit - if no why you (dont know after year of wri=
ting here) youre sticking with preposterous basics ? (its hard to strictly =
compare but silled 16-yo could possibly do it 10 faster than you)
>=20
> nevbies always dream that they learn coding in 5 years
> and be great coders when in reality after 30 years in coding they are sti=
ll average
>=20
> this "trust me age is nothing" sounds like hodgin,  so many insane people=
 here

may add that if you in next 29 years will do 29 times than in this year you=
 will still be nowhere - then tell "trust me age is nothing" (reall agrevia=
ting here is not "age is nothing" which is stupid but normal - more prepost=
erous here is this "trust me") =20

tell how old you are
0
fir
12/24/2016 1:32:15 PM
On 12/24/2016 11:23 AM, Alla _ wrote:
>
> See the problem here?
> 1) I could have returned True at this point, because
> the array is now filled with numbers;
> 2) but at the same time I can't return True here,
> because the test ptr_buffer == not_converted
> is a valuable one indicating that there is nothing to
> convert, and is usually used to signal failure, not a
> success.
> At the moment I return false here until I figure out
> what to do with this issue.
> Therefore, it seems that if(not_converted > ptr_buffer)
> test is not suitable for purposes of this program,
> until I resolve the issue of clearing all potential
> trailing garbage in line read from CSV files.
>
I didn't check all of your last code, but based your previous posts 
(where this problem was already there) I think you managed to correctly 
identify this problem.

I think this problem has 2 aspects:

Aspect 1) Trailing comma in your input. This is probably due to the fact 
that your spreadsheet considers an extra column to be active, i.e. 
present and containing zero-length data.
This aspect leaves you to a situation where you have an empty field at 
the end of the rows the CSV file. You have to make a decision here: 
either you decide to ignore extra columns after you successfully read 
the ones you expect, or you require the CSV file to contain only the 
columns that are specified, and fix the spreadsheet.
Try to delete the column(s) (with the "delete column" command, not the 
"del" key) immediately after the ones that actually contain some data 
before exporting to CSV, even if the look empty.

Aspect 2) extra \r in the last field; as you have already identified, 
this comes from Microsoft (they love to spread \r\n wherever they can).
What I would do is to consider this as 'extra trailing whitespace in a 
field', and skip it. More in detail:
After you successfully convert a number with strtol, check if 
not_converted points to a whitespace (with isspace) and increment 
not_converted as long as this condition holds. This additional loop will 
stop at the real end of the line, or at the next comma in case there is 
some extra space within an intermediate field.

0
Manfred
12/24/2016 2:58:11 PM
W dniu sobota, 24 grudnia 2016 14:32:29 UTC+1 u=C5=BCytkownik fir napisa=C5=
=82:
> W dniu sobota, 24 grudnia 2016 14:10:31 UTC+1 u=C5=BCytkownik fir napisa=
=C5=82:
> > W dniu sobota, 24 grudnia 2016 13:34:51 UTC+1 u=C5=BCytkownik Alla _ na=
pisa=C5=82:
> > > On Saturday, December 24, 2016 at 3:21:00 PM UTC+3, fir wrote:
> > > > W dniu sobota, 24 grudnia 2016 12:58:05 UTC+1 u=C5=BCytkownik Alla =
_ napisa=C5=82:
> > > > > On Saturday, December 24, 2016 at 2:39:33 PM UTC+3, Richard Heath=
field wrote:
> > > > > > On 24/12/16 10:23, Alla _ wrote:
> > > > > > > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Sch=
warz wrote:
> > > > > > >> On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
> > > > > > >> <modelling.data@gmail.com> wrote:
> > > > > > >>
> > > > > > >> <snip>
> > > > > > > <snip>
> > > > > > > Please, take a look at this function (I post it accompanied b=
y the main
> > > > > > > function). I have found one mistake I made, but I still can't=
 cope with
> > > > > > > the suggested version - it doesn't do the job, see below why.
> > > > > >=20
> > > > > > I went to some considerable trouble yesterday to show you how t=
o do this=20
> > > > > > properly. And I have in the past shown you exactly how to use s=
trtol.
> > > > > >=20
> > > > > > What is the point of our helping you if you ignore the help and=
 keep on=20
> > > > > > asking the same questions?
> > > > > I don't understand this. I have tried to implement exactly what y=
ou have=20
> > > > > explained to me about strtol, and I show you why I fail to do tha=
t, and ask
> > > > > what I am doing wrong. In response, you yet again say that I have=
 ignored
> > > > > something, and keep asking same questions. Am I? I have considera=
bly=20
> > > > > analyzed every step of the for loop with strtol approach suggeste=
d by=20
> > > > > you to show why I can't implement it, and why I don't see my mist=
ake.=20
> > > > >=20
> > > > > You know, I don't believe in words, only in facts, and therefore =
I do understand
> > > > > how hard it is for you to believe, based only on my words, repeat=
ed many times,
> > > > > how grateful I am for all huge efforts you make to help me. I als=
o have many=20
> > > > > times admitted that I am silly when it comes to such technical is=
sues as=20
> > > > > programming, and to some logical technical things as well, and I =
do know
> > > > > that I have wasted 40 years of my life, and only now I am trying =
to make it=20
> > > > > up for myself and to learn essential staff.  It is up to you to c=
ontinue helping me
> > > > > to become more knowledgeable and smart person and to grow further=
, or quit on me.=20
> > > > > But, please, stop reminding me how dumb I am - I am perfectly awa=
re of that,
> > > > > and acknowledge that.=20
> > > > > me how dumb I am, I know that; and it is up to you to continue he=
lping me
> > > > > to improve and grow, or quit on me.
> > > >=20
> > > > tell how old u are.. are you forty? it very depends on age if someo=
ne can be "moderately succesfull programer" or if no - starting coding past=
 30 is probably not much bad idea as in coding one needs usually 10 years t=
o becoma "average"
> > > > (or even "average weak") - esp if past 40 i think people learn much=
 slower, and yet there is a fact that later-on programing becomes harder im=
o not easier
> > > > (thise are maybe some vague statements and may be not=20
> > > > strictly true in anycases but mostly it lloks like that i sadly thi=
nk)
> > >=20
> > > Trust me age is nothing; one can do and learn anything at any age -=
=20
> > > all depends on one's set of mind, capability, desire, motivation and =
overall=20
> > > attitude. People constrain themselves with too many fake boundaries, =
and=20
> > > that what hampers the development of the majority of population.
> >=20
> > trust me youre sayin bulshit - if no why you (dont know after year of w=
riting here) youre sticking with preposterous basics ? (its hard to strictl=
y compare but silled 16-yo could possibly do it 10 faster than you)
> >=20
> > nevbies always dream that they learn coding in 5 years
> > and be great coders when in reality after 30 years in coding they are s=
till average
> >=20
> > this "trust me age is nothing" sounds like hodgin,  so many insane peop=
le here
>=20
> may add that if you in next 29 years will do 29 times than in this year y=
ou will still be nowhere - then tell "trust me age is nothing" (reall agrev=
iating here is not "age is nothing" which is stupid but normal - more prepo=
sterous here is this "trust me") =20
>=20
> tell how old you are

if one are 20 or so one imo can gave some chance to be 'normal' programmer =
(not that it is the happiest way to spemd a life of youth :C) =20
if 30 imo it could be much less chance (can probably be a programmer too bu=
t when he will learn basics and start career he will be then oldboy a bit)
if 40 imo this is not much chance at all

well maybe im wrong here (this is not to much comact logic proving that),  =
but im just well aware what one need to know to be average or decent of goo=
d coder, and it is a lot ) (some kickers though seem to have special tallen=
t in this but alla is not such kicker (i am also not btw ) )
0
fir
12/24/2016 4:41:14 PM
On Saturday, December 24, 2016 at 5:58:22 PM UTC+3, Manfred wrote:
> On 12/24/2016 11:23 AM, Alla _ wrote:
> >
<snip>
> I think this problem has 2 aspects:
> 
> Aspect 1) Trailing comma in your input. This is probably due to the fact 
> that your spreadsheet considers an extra column to be active, i.e. 
> present and containing zero-length data.
> This aspect leaves you to a situation where you have an empty field at 
> the end of the rows the CSV file. You have to make a decision here: 
> either you decide to ignore extra columns after you successfully read 
> the ones you expect, or you require the CSV file to contain only the 
> columns that are specified, and fix the spreadsheet.
> Try to delete the column(s) (with the "delete column" command, not the 
> "del" key) immediately after the ones that actually contain some data 
> before exporting to CSV, even if the look empty.
> 
> Aspect 2) extra \r in the last field; as you have already identified, 
> this comes from Microsoft (they love to spread \r\n wherever they can).
> What I would do is to consider this as 'extra trailing whitespace in a 
> field', and skip it. More in detail:
> After you successfully convert a number with strtol, check if 
> not_converted points to a whitespace (with isspace) and increment 
> not_converted as long as this condition holds. This additional loop will 
> stop at the real end of the line, or at the next comma in case there is 
> some extra space within an intermediate field.

Thank you very much. Yes, indeed it is a good way out. I have 
implemented a bit easier version, assuming that the data in the
provided csv file doesn't contain any special characters before
and after numerical ones (no currency symbols), so the following
is a rough measure, which I hope to correct later when I extend 
conditions of processing CSV file to include much more possible
nuances:
- here I test if not_converted is bigger than ptr_buffer and if yes,
then check if the value at not_converted + 1 is a numerical one;
if so, then ptr_buffer = not_converted + 1; if not, I simply finish
the loop by *ptr_buffer = '\0', assuming that the numerical
data can be separated only by commas in CSV file with no 
additional characters (there should be an initial condition to 
the data to be free from all currency symbols)

//Parse each line's comma-separated values into 'array_values'
    for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
    {
        values = (int)strtol(ptr_buffer, &not_converted, 10);
       
        array_values[*line_values][values_column] = values;
        
        if(not_converted > ptr_buffer)
        {
            if(isdigit(*(not_converted + 1)))
              ptr_buffer = not_converted + 1;

            else
                *ptr_buffer = '\0';
        }
        
        if(not_converted == ptr_buffer)  
            return false;
    
        (*values_index)++;
    }
    
0
Alla
12/24/2016 4:49:40 PM
On Saturday, December 24, 2016 at 7:49:47 PM UTC+3, Alla _ wrote:
> On Saturday, December 24, 2016 at 5:58:22 PM UTC+3, Manfred wrote:
> > On 12/24/2016 11:23 AM, Alla _ wrote:
> > >
> <snip>
<snip>
Sorry, I have found a significant mistake in the previous part I posted.
Here is a corrected version:
//Function to parse and convert numerical values from the line
bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
{
    char *ptr_buffer = NULL;
    char *not_converted = NULL;
    ptr_buffer = &buffer[*index];
    size_t values_column;
    int values;
    
    /*******************/
    //DEBUG: LINE_NUMBER & INDEX
    printf("(1.7V) Line number passed to fun_values = %zu\n",
           *line_values);
    printf("(1.8V) Index number passed to fun_values = %zu\n",
           *index);
    //DEBUG: CHECK PTR_BUFFER
    printf("(1.9V) Ptr_buffer_values:: %s\n", ptr_buffer);
    /*******************/
    
    
    //Parse each line's comma-separated values into 'array_values'
    for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
    {
        values = (int)strtol(ptr_buffer, &not_converted, 10);
        
        if(not_converted > ptr_buffer && isdigit(*(not_converted -1)))
        {
            array_values[*line_values][values_column] = values;

            if(isdigit(*(not_converted + 1)))
                ptr_buffer = not_converted + 1;
       
            else
                *ptr_buffer = '\0';
        }
        
        if(not_converted == ptr_buffer)
            return false;
       
        (*values_index)++;
    }
    
    putchar('\n');
    return true;
}
0
Alla
12/24/2016 5:38:34 PM
On Sat, 24 Dec 2016 04:32:01 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

>On Saturday, December 24, 2016 at 3:04:17 PM UTC+3, Alla _ wrote:
>> On Saturday, December 24, 2016 at 1:23:40 PM UTC+3, Alla _ wrote:
>> > On Saturday, December 24, 2016 at 2:17:00 AM UTC+3, Barry Schwarz wrote:
>> > > On Fri, 23 Dec 2016 08:30:09 -0800 (PST), Alla _
>> > > <modelling.data@gmail.com> wrote:
><snip>
>In this version I have achieved the result and have at least partially solved
>the issue with the incorrect input and thus not being able to use the test
>if (not_converted > ptr_buffer). What do you think?

I think including three extra attribution lines when you quote nothing
from any of those messages means you are rushing again and not taking
the time to think things through.

>INPUT
>Years,2011,2012,2013,2014,2015

<snip>

>#include <stdio.h>
>#include <stdlib.h>
>#include <ctype.h>
>#include <string.h>
>#include <stdbool.h>
>
>#define BUFFER_SIZE 100
>#define INCOME_STATEMENT "files/income_test.csv"
>
>bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index);
>
>int main(int argc, char *argv[])
>{
>    //Check for correct number of arguments
>    if(argc > 2)
>    {
>        fputs("Sorry, the program processes only one file.\n", stderr);
>        return EXIT_FAILURE;
>    }
>    //Determine a file to use
>    const char *data_file = (argc == 2)? argv[1] : INCOME_STATEMENT;
>    
>    FILE *fp = fopen(data_file, "r");
>    
>    if ( fp )
>    {
>        char buffer[BUFFER_SIZE] = "";
>        int array_values[50][50] = {{0}};
>        size_t line_values = 0;
>        
>        //Read each line from the file, store in the buffer
>        while(fgets(buffer, sizeof(buffer), fp) != NULL)

Consider the case where fgets does not include a '\n' at the end of
the line.  At this point, buffer contains "2011,...,2014,2015\0"

>        {

I deleted your debugging code just to avoid the clutter.

>            size_t index = 0;
>
>            while(!isdigit(buffer[index++]));
>            index--;

buffer[index] is the first '2'.

>            size_t values_index = 0;
>            
>            if(fill_row_values(buffer, array_values, &line_values, &index, &values_index))
>            {

<snip processing after fill_row_values returns>

>            }
>            else
>            {
>                printf("The function_values failed\n");
>                return EXIT_FAILURE;
>            }
>        }
>        if (ferror(fp))
>        {
>            puts("Something went wrong with the provided file\n");
>            return EXIT_FAILURE;
>        }
>        fclose(fp);
>    }
>    //Couldn't open the file
>    else
>    {
>        perror(data_file);

This line executes if the file fails to open.

>    }
>    return EXIT_SUCCESS;

Do you really want to return success if you could not open the file?

>}
>
>bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
>{
>    char *ptr_buffer = NULL;
>    char *not_converted = NULL;
>    ptr_buffer = &buffer[*index];

Is there some reason you decided not to put this assignment in the
initialization?  In any event, ptr_buffer points to "2011,...,2015\0".

>    size_t values_column;
>    int values;
>    
>    //Parse each line's comma-separated values into 'array_values'
>    for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
>    {
>        values = (int)strtol(ptr_buffer, &not_converted, 10);

In iteration 1:
     ptr_buffer points to "2011,...,2015\0"
     not_converted points to ",2012...,2015\0"
     values contains 2011

In iteration 2:
     ptr_buffer points to "2012,...,2015\0"
     not_converted points to ",2013,...,2015\0"
     values contains 2012

....

In iteration 5:
     ptr_buffer points to "2015\0"
     not_converted points to "\0"
     values contains 2015

In iteration 6:
     ptr_buffer still points to "2015\0"
     not_converted points to "\0" again
     values contains 2015 again

You  loop ad infinitum

        
>        array_values[*line_values][values_column] = values;
>        
>        if(not_converted > ptr_buffer && *not_converted != '\0')

The second expression is completely irrelevant.  Worse, it breaks your
code. 
     If the first expression is false, the second is not evaluated.
     If the first is true, strtol has performed a conversion and
not_converted points to the character that terminated the conversion.
There are four possibilities:
          That character is the comma separating two values.  The
second expression will be true.
          That character is the '\n' that terminates the line.  The
second expression will be true.
          The line is improperly formated and that character is a
superfluous comma, a superfluous blank, a superfluous '\x0a', etc. The
second expression will be true.
          The very last line of your text file does not have a
terminal '\n' or for some other reason fgets did not include a '\n' in
the string.  Your sample string terminates with "...,2015\0".  The
second expression will be false and you don't skip over the final
value.
     So when the second expression is true it contributes nothing to
the decision and when it is false it prevents you from processing data
you possibly should process.  It also creates an infinite loop.

In iteration 5, not_converted points to the '\0'.  The second
expression is false.  The if is false.  The following block does not
execute.

>        {
>            if(isdigit(*(not_converted + 1)))
>            {
>              ptr_buffer = not_converted + 1;
>            }
>            else
>                *ptr_buffer = '\0';
>        }
>        
>        if(not_converted == ptr_buffer)

Given the comments on the first if above, this should be a simple
else.  There are only two possibilities: not_converted is greater than
ptr_buffer or they are equal.

In iteration 5, this if is false.  The following block does not
execute.

>        {
>            return false;

You need a much better test before you can tell main that this
function failed.  In fact, this would usually be how a successful call
to this function terminates..

>       }
>        (*values_index)++;
>    }
>    return true;
>}

-- 
Remove del for email
0
Barry
12/24/2016 8:04:41 PM
On Sat, 24 Dec 2016 09:38:34 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

>On Saturday, December 24, 2016 at 7:49:47 PM UTC+3, Alla _ wrote:
>> On Saturday, December 24, 2016 at 5:58:22 PM UTC+3, Manfred wrote:
>> > On 12/24/2016 11:23 AM, Alla _ wrote:
>> > >
>> <snip>
><snip>
>Sorry, I have found a significant mistake in the previous part I posted.
>Here is a corrected version:
>//Function to parse and convert numerical values from the line
>bool fill_row_values(char *buffer, int array_values[][50], size_t *line_values, size_t *index, size_t *values_index)
>{
>    char *ptr_buffer = NULL;
>    char *not_converted = NULL;
>    ptr_buffer = &buffer[*index];
>    size_t values_column;
>    int values;
>    
>    /*******************/
>    //DEBUG: LINE_NUMBER & INDEX
>    printf("(1.7V) Line number passed to fun_values = %zu\n",
>           *line_values);
>    printf("(1.8V) Index number passed to fun_values = %zu\n",
>           *index);
>    //DEBUG: CHECK PTR_BUFFER
>    printf("(1.9V) Ptr_buffer_values:: %s\n", ptr_buffer);
>    /*******************/
>    
>    
>    //Parse each line's comma-separated values into 'array_values'
>    for ( values_column = 0; *ptr_buffer != '\0'; values_column++, (*index)++)
>    {
>        values = (int)strtol(ptr_buffer, &not_converted, 10);
>        
>        if(not_converted > ptr_buffer && isdigit(*(not_converted -1)))

Is this an effort to deal with the problem of two commas in a row?

>        {
>            array_values[*line_values][values_column] = values;
>
>            if(isdigit(*(not_converted + 1)))

Are you aware that your CSV might have data of the form "2011, 2012"
or "123,-456", both of which will be processed properly by strtol if
you let it.

>                ptr_buffer = not_converted + 1;
>       
>            else
>                *ptr_buffer = '\0';
>        }
>        
>        if(not_converted == ptr_buffer)
>            return false;
>       
>        (*values_index)++;

I don't see the benefit of having both index and values_index.  Is
there any?  At the end of each for loop iteration, they have the same
value.

>    }
>    
>    putchar('\n');
>    return true;
>}

-- 
Remove del for email
0
Barry
12/24/2016 11:15:24 PM
Reply: