not converting to int

Discussion in 'Mac Programming' started by dougphd, Nov 15, 2016.

  1. dougphd macrumors member

    Joined:
    Apr 28, 2016
    #1
    here's the code

    Code:
    void main
    char num[10], cmd[75];
    int files;
    char *end;
    strcpy(cmd, "ls ");
    strcat(cmd,scan_data_home);
    strcat(cmd," | wc -l");
    fp = popen(cmd, "r");
    while (fgets(num, sizeof(num)-1, fp) != NULL)
          printf("%s\n",num);
    files = (int) strtol(num, &end, 10);
    printf("%d\n", files);
    printf("1 %c\n", num[0]);
    printf("2 %c\n", num[1]);
    printf("3 %c\n", num[2]);
    printf("4 %c\n", num[3]);
    printf("5 %c\n", num[4]);
    printf("6 %c\n", num[5]);
    printf("7 %c\n", num[6]);
    printf("8 %c\n", num[7]);
     /[code]
    
    
    here's the output. I tried to duplicate the actual line spacing
    [code]
    [B]              3739[/B]
    
    
    
    0
    [B]1 [/B]
    
    [B]2 
    3  
    4  
    5 3
    6 7
    7 3
    8 9[/B]
    /[code]
    
    What gives and how to I convert the string to an int.
     
  2. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #2
    I tested this on my Linux machine and there it works. Note that your code is full of potential buffer overflows and magic numbers. Maybe the data path is longer than you expected?

    Do you really, really need to do all your work in C?
     
  3. dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #3
    Yes. And in this case, I have been asked to use it specifically for it's speed. As far as the overflows and magic numbers, this code snippet is merely to demonstrate an example of 3-D modeling. Better comes later, although I am not above improving this. Thanks for your help. The work is done on a MAC. Do you have any suggestions as what to do.

    If you use a language with a run time complier, how do to avoid crashing after the code has run for three hours because of a typo?
    --- Post Merged, Nov 16, 2016 ---
    Works on my machine too. Must be something in the input which is read from a csv file.

    Code:
    char test1[10], test2[10];
    strcpy(test1,"3797");
    files = (int) strtol(test1, &end, 10);
    printf("%d\n", files);
    strcpy(test2,"00003797");
    files = (int) strtol(test2, &end, 10);
    printf("%d\n", files);
    strcpy(test3,"    3797");
    files = (int) strtol(test3, &end, 10);
    printf("%d\n", files);
    /[code]
     
  4. robvas, Nov 16, 2016
    Last edited: Nov 16, 2016

    robvas macrumors 68020

    Joined:
    Mar 29, 2009
    Location:
    USA
    #4
    Again, you posted a mass of code that is full of syntax errors and missing what is needed to run the code to see why it doesn't work.

    I also noticed that you almost always screw up your code tags. You enter them as /[code_tag] instead of [/code_tag]

    This tells me two things:

    1 - You don't pay attention to the message you entered which makes me thing you don't pay attention to the code you enter
    2 - You don't bother to look at your posted message to see if it's clear to others, you would instantly notice the formatting is off

    You can still test your code. You'd be amazed at how many web sites run on Ruby, Python, etc which are 'interpreted' languages (not 'run-time compiled'). Most forums run PHP which is interpreted!

    --- Post Merged, Nov 16, 2016 ---
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void main (void)
    {
      char num[10] = "iiiiiiiii\n";
      char cmd[75];
      int files;
      FILE *fp;
      char *scan_data_home = "~";
      char *end;
    
      strcpy (cmd, "ls ");
      strcat (cmd, scan_data_home);
      strcat (cmd, " | wc -l");
      fp = popen (cmd, "r");
    
      while (fgets (num, sizeof (num) - 1, fp) != NULL) {
          printf ("\nValue of the char array 'num': %s\n", num);
      }
    
      files = (int) strtol (num, &end, 10);
    
      printf ("Value of 'int files': %d\n", files);
      printf ("Each value of the num char array:\n");
      printf ("num[0] %x\n", num[0]);
      printf ("num[1] %x\n", num[1]);
      printf ("num[2] %x\n", num[2]);
      printf ("num[3] %x\n", num[3]);
      printf ("num[4] %x\n", num[4]);
      printf ("num[5] %x\n", num[5]);
      printf ("num[6] %x\n", num[6]);
      printf ("num[7] %x\n", num[7]);
    }
    
    Code:
    $ ./a.out
    
    While loop output: 10
    
    10
    num[0] 31
    num[1] 30
    num[2] a
    num[3] 0
    num[4] 69
    num[5] 69
    num[6] 69
    num[7] 69
    
    If you look at an ASCII chart you'll see each value (in hex) of the num array

    [​IMG]

    So you see the string that contains '10' ends up really holding

    '1', '0', '\n', NULL, 'i', 'i', 'i', 'i'

    The i's are left there so you can see they aren't overwritten (I set char num[] to 'iiiiiiii' at the beginning of the code. But C sees the NULL it doesn't care and quits processing the array as a string.
     
  5. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #5
    How do you avoid crashing when your program is run on a data directory several levels deep, leading to longer path names than you expected?

    Note that nowhere I said you should use a run time (interpreted) language, as this is exactly my beef with these. But there is a middle ground too. I highly doubt that the performance bottleneck in your app is in counting the number of files in a directory. Whether this takes 99ms or 101ms won't make the difference.

    In fact, in most cases the actual processing is performed in libraries which were written in a compiled-to-native language (probably C or C++) and your "run time language" is just used as glue. This lets you focus on the important stuff.
     
  6. robvas macrumors 68020

    Joined:
    Mar 29, 2009
    Location:
    USA
    #6
    This is the part I'm curious about
     
  7. dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #7
    yes i have trouble paying attention to detail and maybe a bit
    yes i have trouble paying attention to detail and may be a bit dyslexic. sorry for not previewing my post this morning i was in a rush.
    --- Post Merged, Nov 16, 2016 ---
    thanks for that clarification. yes there will be lots of data reduction and process.
     
  8. Toutou macrumors 6502a

    Toutou

    Joined:
    Jan 6, 2015
    Location:
    Prague, Czech Republic
    #8
    You'd be better off just using C++ and an ifstream object, even if speed is an issue.

    And as speed is almost never an issue when parsing a file, I say use Python and stop reinventing the wheel.
     
  9. dougphd, Nov 16, 2016
    Last edited: Nov 16, 2016

    dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #9
    yes i have trouble paying attention to detail. i may be a bit dyslexic too. sorry not to have checked this this morning i was in a rush. i will check the rest of your response when i have more time.
    i've worked languages with runtime compilers and i hate them for the reason stated above. i have to do real time conversion of streams of data to real time images. my employer has already tried matlab and wants it done in c. if he wanted it in ruby somebody else would be doing it. finally i am never hired for my programming abilities. i'm hired because i can develop algorithms. a big difference. however this time i have put a big c book on my desk so i can improve and not bother the forum so much. your help is always appreciated

    Anyway the answer to my original question is that when matlab converts my .mat file to a csv file, it's doing strange things.
    --- Post Merged, Nov 16, 2016 ---
    What are you curious about? the modeling. Take two sets of data taken at the same time but at different points in time.
    Z(t) and X and Y (T)
    Extract certain spatial points from the first file. Line them up wth the time from the XY file and plot.
    --- Post Merged, Nov 16, 2016 ---
    Not matlab. that was silly.
    The problem is the system call with popen.
     
  10. dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #10
    Here's the solution

    Code:
    while (fgets(num, 10, fp) != NULL)
    printf("%s\n",num);
    num = strrchr(num,' ');
    files = (int) strtol(num, &end, 10);
    
     
  11. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #11
    Here's another solution (no other changes to original):
    Code:
    char num[ 30 ], cmd[75];
    
    Explain the result.
     
  12. Senor Cuete macrumors regular

    Joined:
    Nov 9, 2011
    #12
    You won't learn to program in C by creating your own examples that are beyond your ability. The real way to do it is to read a learn to program in C book and do the examples. This is probably true in other languages as well. I learned by reading "A Book on C" by Kelly and Pohl.
     
  13. dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #13
    Thanks but it's worked so far.
    --- Post Merged, Nov 17, 2016 ---
    You want me to explain it? Do I get a hint? BTW 10 didn't work.
     
  14. chown33, Nov 17, 2016
    Last edited: Nov 17, 2016

    chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #14
    Yes.

    To understand exactly what the error in the original code is, you need to understand exactly why the single change I posted causes it to work. If you understand the reason, then an explanation will be simple and brief. If not, it won't.

    Here's a hint.

    Start with the original code (i.e. num[10]). Add the line shown below, in the place shown:
    Code:
    printf( "strtol will parse the string (%s)  with length %d\n", num, (int) strlen(num) );
    
    files = (int) strtol(num, &end, 10);
    
    Explain the result.

    If you can't explain the result with num[10], try it with num[30], or num[5] (yes, five; not a typo), and explain those results. You need a clear and accurate mental image of what's happening.
     
  15. dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #15
    --- Post Merged, Nov 17, 2016 ---
    num[5]
    ls /Users/douglasbrenner/Documents/Gaurav/a_scan_data/ | wc -l
    strtol will parse the string ( ) with length 3
    strtol will parse the string ( 37) with length 3
    strtol will parse the string (39
    ) with length 3
    3

    num[10]
    ls /Users/douglasbrenner/Documents/Gaurav/a_scan_data/ | wc -l
    strtol will parse the string ( 3739) with length 8
    strtol will parse the string (
    ) with length 1
    0

    num[30]
    ls /Users/douglasbrenner/Documents/Gaurav/a_scan_data/ | wc -l
    strtol will parse the string ( 3739
    ) with length 9
    3739

    First, it tells me what I already knew: that the system call puts in 4 leading zeros.
    Not sure why 10 won't work. 11 works.

    Can we take this discussion of the board. Might be easier.
     
  16. chown33, Nov 17, 2016
    Last edited: Nov 17, 2016

    chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #16
    You may already have known this, but it hasn't lead to an understanding of what happens.

    I asked you to explain the output. That is, why does 30 work?

    You're looking at the evidence (program output), but not seeing what it says.

    The system call isn't putting in any zeros. If you look more carefully at the data (hint: %x), it won't be zeros. This isn't directly related to the reason for failure, it's just a mistaken detail.

    If you understand why 11 works, then you should be able to work out why 10 doesn't work. If not, go smaller. For example, try 9. What happens? Try 8. Explain what happens as you decrease the size of num.

    Here's a command-line whose output shows the data:
    Code:
    ls /Users/douglasbrenner/Documents/Gaurav/a_scan_data/ | wc -l | hexdump -C
    
    Look at the data. Count it.

    Look at your original code. How are you reading the data? Exactly what values are being passed in?


    Finally, the printf I asked you to add should run exactly once. If it's in a loop, it's in the wrong place. That is, you should ADD the one printf given, outside the loop.

    If you're going to change the printf in the loop, make it tell you more, clearly:
    Code:
    while (fgets(num, sizeof(num)-1, fp) != NULL)
         printf( "fgets got (%s), len %d\n", num, (int) strlen(num) );
    
     
  17. mfram, Nov 17, 2016
    Last edited: Nov 18, 2016

    mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #17
    I want to point out to the O.P. that if all you want is the number of files in a directory, then you should be using the readdir() API to do that. It is the POSIX API that should be used to examine directories from C. In general, if you think you need to use system() to get some information about something on your computer, then that means there is some underlying API to get it. You should be using that API directly and not going through all this nonsense. It will be faster and less error-prone.
     
  18. dougphd thread starter macrumors member

    Joined:
    Apr 28, 2016
    #18
    I meant spaces. I did a hex dump earlier
     

Share This Page