How do I parse a string of numbers into a array of integers?












0














I have been struggling with this for a while and figured I might as well ask for help instead of banging my head harder into a wall.



So let's say you have the string "10 10 10 4 4 4 9 9 9 2"
and you want to go through it, take out the numbers one by one and add it to an array of integers to use.



I have prototyped A LOT and keep making more work for myself than is necessary. At first I was using strtok() but then people said that was deprecated and it would be easier to use strsep()



How would I go about doing this?



Any help would be greatly appreciated!



My function seems to always return an int array full of zeros. Why is this?



int *parse_line(char *line){
char sNumArray[MAX];
strcpy(sNumArray, line);
char *tokens = NULL;
int *numbers = malloc(sizeof(int) * MAX);
tokens = strtok(sNumArray, " ");
for(int i = 0; ; i++) {
numbers[i] = atoi(tokens);
printf("%d n", atoi(tokens));
tokens = strtok(NULL, " ");
if (tokens == NULL)
break;
}
return numbers;
}


These are my variables I define in the main and call my function with...



int *skyline;
skyline = parse_line(line);
for (int j = 0; j < 100 ; ++j) {
printf("%d n", skyline[j]);
}









share|improve this question




















  • 1




    strsep is not standard C; strtok is
    – Govind Parmar
    Nov 20 at 1:27










  • Can you post the code that you've tried, and any errors you're getting? I also suggest using strtok over strsep, as it's more widely used, and is of course standard C. In fact, you should be able to find a pretty simple tutorial for this online with strtok.
    – ahota
    Nov 20 at 1:33
















0














I have been struggling with this for a while and figured I might as well ask for help instead of banging my head harder into a wall.



So let's say you have the string "10 10 10 4 4 4 9 9 9 2"
and you want to go through it, take out the numbers one by one and add it to an array of integers to use.



I have prototyped A LOT and keep making more work for myself than is necessary. At first I was using strtok() but then people said that was deprecated and it would be easier to use strsep()



How would I go about doing this?



Any help would be greatly appreciated!



My function seems to always return an int array full of zeros. Why is this?



int *parse_line(char *line){
char sNumArray[MAX];
strcpy(sNumArray, line);
char *tokens = NULL;
int *numbers = malloc(sizeof(int) * MAX);
tokens = strtok(sNumArray, " ");
for(int i = 0; ; i++) {
numbers[i] = atoi(tokens);
printf("%d n", atoi(tokens));
tokens = strtok(NULL, " ");
if (tokens == NULL)
break;
}
return numbers;
}


These are my variables I define in the main and call my function with...



int *skyline;
skyline = parse_line(line);
for (int j = 0; j < 100 ; ++j) {
printf("%d n", skyline[j]);
}









share|improve this question




















  • 1




    strsep is not standard C; strtok is
    – Govind Parmar
    Nov 20 at 1:27










  • Can you post the code that you've tried, and any errors you're getting? I also suggest using strtok over strsep, as it's more widely used, and is of course standard C. In fact, you should be able to find a pretty simple tutorial for this online with strtok.
    – ahota
    Nov 20 at 1:33














0












0








0







I have been struggling with this for a while and figured I might as well ask for help instead of banging my head harder into a wall.



So let's say you have the string "10 10 10 4 4 4 9 9 9 2"
and you want to go through it, take out the numbers one by one and add it to an array of integers to use.



I have prototyped A LOT and keep making more work for myself than is necessary. At first I was using strtok() but then people said that was deprecated and it would be easier to use strsep()



How would I go about doing this?



Any help would be greatly appreciated!



My function seems to always return an int array full of zeros. Why is this?



int *parse_line(char *line){
char sNumArray[MAX];
strcpy(sNumArray, line);
char *tokens = NULL;
int *numbers = malloc(sizeof(int) * MAX);
tokens = strtok(sNumArray, " ");
for(int i = 0; ; i++) {
numbers[i] = atoi(tokens);
printf("%d n", atoi(tokens));
tokens = strtok(NULL, " ");
if (tokens == NULL)
break;
}
return numbers;
}


These are my variables I define in the main and call my function with...



int *skyline;
skyline = parse_line(line);
for (int j = 0; j < 100 ; ++j) {
printf("%d n", skyline[j]);
}









share|improve this question















I have been struggling with this for a while and figured I might as well ask for help instead of banging my head harder into a wall.



So let's say you have the string "10 10 10 4 4 4 9 9 9 2"
and you want to go through it, take out the numbers one by one and add it to an array of integers to use.



I have prototyped A LOT and keep making more work for myself than is necessary. At first I was using strtok() but then people said that was deprecated and it would be easier to use strsep()



How would I go about doing this?



Any help would be greatly appreciated!



My function seems to always return an int array full of zeros. Why is this?



int *parse_line(char *line){
char sNumArray[MAX];
strcpy(sNumArray, line);
char *tokens = NULL;
int *numbers = malloc(sizeof(int) * MAX);
tokens = strtok(sNumArray, " ");
for(int i = 0; ; i++) {
numbers[i] = atoi(tokens);
printf("%d n", atoi(tokens));
tokens = strtok(NULL, " ");
if (tokens == NULL)
break;
}
return numbers;
}


These are my variables I define in the main and call my function with...



int *skyline;
skyline = parse_line(line);
for (int j = 0; j < 100 ; ++j) {
printf("%d n", skyline[j]);
}






c arrays string parsing c99






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 3:59

























asked Nov 20 at 1:25









Jak

25




25








  • 1




    strsep is not standard C; strtok is
    – Govind Parmar
    Nov 20 at 1:27










  • Can you post the code that you've tried, and any errors you're getting? I also suggest using strtok over strsep, as it's more widely used, and is of course standard C. In fact, you should be able to find a pretty simple tutorial for this online with strtok.
    – ahota
    Nov 20 at 1:33














  • 1




    strsep is not standard C; strtok is
    – Govind Parmar
    Nov 20 at 1:27










  • Can you post the code that you've tried, and any errors you're getting? I also suggest using strtok over strsep, as it's more widely used, and is of course standard C. In fact, you should be able to find a pretty simple tutorial for this online with strtok.
    – ahota
    Nov 20 at 1:33








1




1




strsep is not standard C; strtok is
– Govind Parmar
Nov 20 at 1:27




strsep is not standard C; strtok is
– Govind Parmar
Nov 20 at 1:27












Can you post the code that you've tried, and any errors you're getting? I also suggest using strtok over strsep, as it's more widely used, and is of course standard C. In fact, you should be able to find a pretty simple tutorial for this online with strtok.
– ahota
Nov 20 at 1:33




Can you post the code that you've tried, and any errors you're getting? I also suggest using strtok over strsep, as it's more widely used, and is of course standard C. In fact, you should be able to find a pretty simple tutorial for this online with strtok.
– ahota
Nov 20 at 1:33












4 Answers
4






active

oldest

votes


















0














I think this will do what you want.



#include "stdafx.h"

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;

#define MAX 100

int *parse_line(char *line, int *numInts) {
char sNumArray[MAX];
strcpy(sNumArray, line);
int *numbers = (int *) malloc(sizeof(int) * MAX);
char *tokens = strtok(sNumArray, " ");
for (int i = 0; ; i++) {
numbers[i] = atoi(tokens);
tokens = strtok(NULL, " ");
if (tokens == NULL) {
*numInts = i+1;
break;
}
}

return numbers;
}

int main() {
char *line = "10 10 10 4 4 4 9 9 9 2";
int numIntsExtracted = 0;
int *skyline = parse_line(line, &numIntsExtracted);

for (int j = 0; j < numIntsExtracted; ++j) {
printf("%d n", skyline[j]);
}
return 0;
}


And the output I'm getting after running it.



10
10
10
4
4
4
9
9
9
2





share|improve this answer























  • You're the man, it worked perfectly!
    – Jak
    Nov 20 at 3:22










  • Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
    – Jak
    Nov 20 at 3:55










  • This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
    – chux
    Nov 20 at 4:06












  • @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
    – driftwood
    Nov 20 at 12:08












  • @driftwood I will try this and get back to you. Thank you for all your help
    – Jak
    Nov 20 at 16:22



















3














You have three primary options (1) use strtol in the manner it was intended, using the *endptr parameter to advance the current read position within the string to one past the last digit converted, or (2) pass to sscanf utilizing the "%n" specifier to report the number of characters used in the conversion to int (or whatever type) and using that value to advance the read position in the same manner; or (3) tokenizing the string with strtok and then using strtol (as atoi should not be used as it provides absolutely zero error checking). There really isn't any need to use both strtok and strtol as strtol already provides a way to advance past the digits converted. You are essentially duplicating what has already by done by strtol by using a call to strtok -- but it is a valid way to go.



For instance using strtol you could do something like the following:



#include <stdio.h>
#include <stdlib.h> /* for strtol */
#include <string.h> /* for strncpy */
#include <errno.h> /* for errno */

#define MAXC 1024 /* constant - max chars in line */

int main (void) {

char str[MAXC] = ""; /* str to hold line, initialized all zero */

while (fgets (str, MAXC, stdin)) { /* read each line of input */
char *p = str, /* pointer for strtol */
*endptr = NULL; /* end pointer for strtol */

while (*p) { /* work down str parsing integer or hex values */
long val = strtol (p, &endptr, 0); /* convert from p */

/* validate conversion */
if (p != endptr) { /* were digits converted? */
if (!errno) { /* if errno 0, successful conversion */
char ascii[MAXC] = ""; /* for string converted */

strncpy (ascii, p, endptr - p); /* copy to ascii */
ascii[endptr-p] = 0; /* nul-terminate ascii */

/* test whether string begins "0x" or "0X", output */
if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
printf ("hex conversion: %-10s %10lu 0x%lxn",
ascii, val, val);
else
printf ("int conversion: %-10s % ldn",
ascii, val);
}
p = endptr; /* advance p to 1-past end of converted string */
}

/* find start of next valid number in str, including (+/-) */
for (; *p; p++) {
if ('0' <= *p && *p <= '9') /* positive value */
break; /* explicitly signed value */
if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9')
break;
}
}
}

return 0;
}


Example Use/Output



$ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_strtol_any
int conversion: 10 10
int conversion: 10 10
int conversion: 10 10
int conversion: 4 4
int conversion: 4 4
int conversion: 4 4
int conversion: 9 9
int conversion: 9 9
int conversion: 9 9
int conversion: 2 2


or converting all the integers in a messy file, e.g.



Example Input File



$ cat dat/10intmess.txt
8572,;a -2213,;--a 6434,;
a- 16330,;a

- The Quick
Brown%3034 Fox
12346Jumps Over
A
4855,;*;Lazy 16985/,;a
Dog.
11250
1495


Example Use/Output



$ ./bin/fgets_strtol_any <dat/10intmess.txt
int conversion: 8572 8572
int conversion: -2213 -2213
int conversion: 6434 6434
int conversion: 16330 16330
int conversion: 3034 3034
int conversion: 12346 12346
int conversion: 4855 4855
int conversion: 16985 16985
int conversion: 11250 11250
int conversion: 1495 1495


Using sscanf



Similarly, you can use sscanf, but be mindful, it doesn't provide the level or degree of error handling -- meaning you can only know that it either successfully converted the text or it failed. No in between, no reporting of overflow or underflow through errno. But still, it along with strtok are other valid means of parsing integers from a line of text, e.g.



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

#define MAXC 1024

int main (int argc, char **argv) {

char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */
int nval = 0; /* total number of integers found */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.n", argv[1]);
return 1;
}

while (fgets (buf, MAXC, fp)) {

char *p = buf; /* pointer to line */
int val, /* int val parsed */
nchars = 0; /* number of chars read */

/* while chars remain in buf and a valid conversion to int takes place
* output the integer found and update p to point to the start of the
* next digit.
*/
while (*p) {
if (sscanf (p, "%d%n", &val, &nchars) == 1) {
printf (" %d", val);
if (++nval % 10 == 0) /* output 10 int per line */
putchar ('n');
}
p += nchars; /* move p nchars forward in buf */

/* find next number in buf */
for (; *p; p++) {
if (*p >= '0' && *p <= '9') /* positive value */
break;
if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */
break;
}
}
}
printf ("n %d integers found.n", nval);

if (fp != stdin) fclose (fp); /* close file if not stdin */

return 0;
}


Example Use/Output



$ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_sscanf_int_any_ex
10 10 10 4 4 4 9 9 9 2

10 integers found.


or with messy input



$ echo "1, 2 buckle my shoe, 3, 4..." | ./bin/fgets_sscanf_int_any_ex
1 2 3 4
4 integers found.


Using strtok would simply be a "front-end" to conversion with strtol shown in the first example (which provides its own way to tokenizing numeric values). You simply loop over your buffer calling strtok with delimiters of " n" (space newline) and then using strtol to convert the string pointed to. (here you are simply using endptr to validate digits were converted and ignoring its use to advance past the digits converted. Essentially, strtok duplicates what is already done by strtok, but if it makes it easier to understand, and you can live with the duplicate call, it's fine. You could do something like the following.



    while (fgets (buf, MAXC, fp)) {
char *p = buf; /* pointer to buf to use with strtok */
/* 1st call using buffer, all remaining calls using NULL */
for (p = strtok (p, " n"); p; p = strtok (NULL, " n")) {
errno = 0; /* reset errno */
char *endptr; /* end pointer */
long tmp = strtol (p, &endptr, 0); /* convert using long */
if (p != endptr) { /* validate digits converted */
/* now validate value within range of int */
if (!errno && INT_MIN <= tmp && tmp <= INT_MAX)
/* you have an integer! */
}
else if (tmp == 0)
/* no digits were converted */
}
}


Look things over and let me know if you have further questions.






share|improve this answer























  • for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
    – chux
    Nov 20 at 4:01












  • I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
    – chux
    Nov 20 at 4:04






  • 1




    Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
    – David C. Rankin
    Nov 20 at 4:27



















0














I like to use the function strtol() for this, because if you pass it a pointer, it will return the next point to continue parsing. There are also unsigned versions, e.g.: strtoul(). They are standard since C99. Also strtol() can parse hexadecimal, and handles errors somewhat better than older functions like atoi() (which returns 0 on error).



The important part of the code below is the result from strtol(). When next_number is un-changed after the call, there is no more input (or an error occurred). The variable ptr is used to keep track of where the parsing is up to in the string. It's given to strtol(), which changes next_number to point to the next element, so then ptr jumps forward - assigned to next_number (past the element just parsed), and the process repeats.



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

int main(void)
{
char *number_str = "10 10 10 4 4 4 9 9 9 2";
char *ptr;
char *next_number;
int numbers[1000];
int number_count = 0;
long num;

next_number = number_str;

do
{
ptr = next_number;
num = strtol(ptr, &next_number, 10);
if (ptr != next_number) // found one
{
numbers[number_count] = (int)num;
printf("Stored %3d into numbers[%d]n", numbers[number_count], number_count);
number_count += 1;
}
} while(ptr != next_number);

return 0;
}





share|improve this answer































    -5














    Just use scanf() to get each number one by one in for or while loop.



    for i = 0 to n
    scanf(“%d”, &num);


    Pls refer google or bing search online how it is done with many examples available.






    share|improve this answer





















    • This answer is not in C-syntax.
      – Kingsley
      Nov 20 at 2:57











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384946%2fhow-do-i-parse-a-string-of-numbers-into-a-array-of-integers%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    I think this will do what you want.



    #include "stdafx.h"

    #include <stdio.h>
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    using namespace std;

    #define MAX 100

    int *parse_line(char *line, int *numInts) {
    char sNumArray[MAX];
    strcpy(sNumArray, line);
    int *numbers = (int *) malloc(sizeof(int) * MAX);
    char *tokens = strtok(sNumArray, " ");
    for (int i = 0; ; i++) {
    numbers[i] = atoi(tokens);
    tokens = strtok(NULL, " ");
    if (tokens == NULL) {
    *numInts = i+1;
    break;
    }
    }

    return numbers;
    }

    int main() {
    char *line = "10 10 10 4 4 4 9 9 9 2";
    int numIntsExtracted = 0;
    int *skyline = parse_line(line, &numIntsExtracted);

    for (int j = 0; j < numIntsExtracted; ++j) {
    printf("%d n", skyline[j]);
    }
    return 0;
    }


    And the output I'm getting after running it.



    10
    10
    10
    4
    4
    4
    9
    9
    9
    2





    share|improve this answer























    • You're the man, it worked perfectly!
      – Jak
      Nov 20 at 3:22










    • Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
      – Jak
      Nov 20 at 3:55










    • This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
      – chux
      Nov 20 at 4:06












    • @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
      – driftwood
      Nov 20 at 12:08












    • @driftwood I will try this and get back to you. Thank you for all your help
      – Jak
      Nov 20 at 16:22
















    0














    I think this will do what you want.



    #include "stdafx.h"

    #include <stdio.h>
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    using namespace std;

    #define MAX 100

    int *parse_line(char *line, int *numInts) {
    char sNumArray[MAX];
    strcpy(sNumArray, line);
    int *numbers = (int *) malloc(sizeof(int) * MAX);
    char *tokens = strtok(sNumArray, " ");
    for (int i = 0; ; i++) {
    numbers[i] = atoi(tokens);
    tokens = strtok(NULL, " ");
    if (tokens == NULL) {
    *numInts = i+1;
    break;
    }
    }

    return numbers;
    }

    int main() {
    char *line = "10 10 10 4 4 4 9 9 9 2";
    int numIntsExtracted = 0;
    int *skyline = parse_line(line, &numIntsExtracted);

    for (int j = 0; j < numIntsExtracted; ++j) {
    printf("%d n", skyline[j]);
    }
    return 0;
    }


    And the output I'm getting after running it.



    10
    10
    10
    4
    4
    4
    9
    9
    9
    2





    share|improve this answer























    • You're the man, it worked perfectly!
      – Jak
      Nov 20 at 3:22










    • Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
      – Jak
      Nov 20 at 3:55










    • This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
      – chux
      Nov 20 at 4:06












    • @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
      – driftwood
      Nov 20 at 12:08












    • @driftwood I will try this and get back to you. Thank you for all your help
      – Jak
      Nov 20 at 16:22














    0












    0








    0






    I think this will do what you want.



    #include "stdafx.h"

    #include <stdio.h>
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    using namespace std;

    #define MAX 100

    int *parse_line(char *line, int *numInts) {
    char sNumArray[MAX];
    strcpy(sNumArray, line);
    int *numbers = (int *) malloc(sizeof(int) * MAX);
    char *tokens = strtok(sNumArray, " ");
    for (int i = 0; ; i++) {
    numbers[i] = atoi(tokens);
    tokens = strtok(NULL, " ");
    if (tokens == NULL) {
    *numInts = i+1;
    break;
    }
    }

    return numbers;
    }

    int main() {
    char *line = "10 10 10 4 4 4 9 9 9 2";
    int numIntsExtracted = 0;
    int *skyline = parse_line(line, &numIntsExtracted);

    for (int j = 0; j < numIntsExtracted; ++j) {
    printf("%d n", skyline[j]);
    }
    return 0;
    }


    And the output I'm getting after running it.



    10
    10
    10
    4
    4
    4
    9
    9
    9
    2





    share|improve this answer














    I think this will do what you want.



    #include "stdafx.h"

    #include <stdio.h>
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    using namespace std;

    #define MAX 100

    int *parse_line(char *line, int *numInts) {
    char sNumArray[MAX];
    strcpy(sNumArray, line);
    int *numbers = (int *) malloc(sizeof(int) * MAX);
    char *tokens = strtok(sNumArray, " ");
    for (int i = 0; ; i++) {
    numbers[i] = atoi(tokens);
    tokens = strtok(NULL, " ");
    if (tokens == NULL) {
    *numInts = i+1;
    break;
    }
    }

    return numbers;
    }

    int main() {
    char *line = "10 10 10 4 4 4 9 9 9 2";
    int numIntsExtracted = 0;
    int *skyline = parse_line(line, &numIntsExtracted);

    for (int j = 0; j < numIntsExtracted; ++j) {
    printf("%d n", skyline[j]);
    }
    return 0;
    }


    And the output I'm getting after running it.



    10
    10
    10
    4
    4
    4
    9
    9
    9
    2






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 20 at 23:24

























    answered Nov 20 at 2:57









    driftwood

    5091720




    5091720












    • You're the man, it worked perfectly!
      – Jak
      Nov 20 at 3:22










    • Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
      – Jak
      Nov 20 at 3:55










    • This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
      – chux
      Nov 20 at 4:06












    • @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
      – driftwood
      Nov 20 at 12:08












    • @driftwood I will try this and get back to you. Thank you for all your help
      – Jak
      Nov 20 at 16:22


















    • You're the man, it worked perfectly!
      – Jak
      Nov 20 at 3:22










    • Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
      – Jak
      Nov 20 at 3:55










    • This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
      – chux
      Nov 20 at 4:06












    • @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
      – driftwood
      Nov 20 at 12:08












    • @driftwood I will try this and get back to you. Thank you for all your help
      – Jak
      Nov 20 at 16:22
















    You're the man, it worked perfectly!
    – Jak
    Nov 20 at 3:22




    You're the man, it worked perfectly!
    – Jak
    Nov 20 at 3:22












    Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
    – Jak
    Nov 20 at 3:55




    Actually, I am having issues with this. When I print the int array is full of 0's I will update my code above
    – Jak
    Nov 20 at 3:55












    This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
    – chux
    Nov 20 at 4:06






    This fails then the first tokens == NULL. Suggest for(int i = 0; tokens; i++) { --> for(int i = 0; ; i++) { and drop the if (tokens == NULL) break;
    – chux
    Nov 20 at 4:06














    @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
    – driftwood
    Nov 20 at 12:08






    @Jak Its working except you don't see it because you are printing all 100 elements of skyline instead of the exact number you extracted. You need to store somewhere the exact number of integers you extracted. Depending on your needs you could store this in a global variable or pass it via output variable to parse_line.
    – driftwood
    Nov 20 at 12:08














    @driftwood I will try this and get back to you. Thank you for all your help
    – Jak
    Nov 20 at 16:22




    @driftwood I will try this and get back to you. Thank you for all your help
    – Jak
    Nov 20 at 16:22













    3














    You have three primary options (1) use strtol in the manner it was intended, using the *endptr parameter to advance the current read position within the string to one past the last digit converted, or (2) pass to sscanf utilizing the "%n" specifier to report the number of characters used in the conversion to int (or whatever type) and using that value to advance the read position in the same manner; or (3) tokenizing the string with strtok and then using strtol (as atoi should not be used as it provides absolutely zero error checking). There really isn't any need to use both strtok and strtol as strtol already provides a way to advance past the digits converted. You are essentially duplicating what has already by done by strtol by using a call to strtok -- but it is a valid way to go.



    For instance using strtol you could do something like the following:



    #include <stdio.h>
    #include <stdlib.h> /* for strtol */
    #include <string.h> /* for strncpy */
    #include <errno.h> /* for errno */

    #define MAXC 1024 /* constant - max chars in line */

    int main (void) {

    char str[MAXC] = ""; /* str to hold line, initialized all zero */

    while (fgets (str, MAXC, stdin)) { /* read each line of input */
    char *p = str, /* pointer for strtol */
    *endptr = NULL; /* end pointer for strtol */

    while (*p) { /* work down str parsing integer or hex values */
    long val = strtol (p, &endptr, 0); /* convert from p */

    /* validate conversion */
    if (p != endptr) { /* were digits converted? */
    if (!errno) { /* if errno 0, successful conversion */
    char ascii[MAXC] = ""; /* for string converted */

    strncpy (ascii, p, endptr - p); /* copy to ascii */
    ascii[endptr-p] = 0; /* nul-terminate ascii */

    /* test whether string begins "0x" or "0X", output */
    if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
    printf ("hex conversion: %-10s %10lu 0x%lxn",
    ascii, val, val);
    else
    printf ("int conversion: %-10s % ldn",
    ascii, val);
    }
    p = endptr; /* advance p to 1-past end of converted string */
    }

    /* find start of next valid number in str, including (+/-) */
    for (; *p; p++) {
    if ('0' <= *p && *p <= '9') /* positive value */
    break; /* explicitly signed value */
    if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9')
    break;
    }
    }
    }

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_strtol_any
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 2 2


    or converting all the integers in a messy file, e.g.



    Example Input File



    $ cat dat/10intmess.txt
    8572,;a -2213,;--a 6434,;
    a- 16330,;a

    - The Quick
    Brown%3034 Fox
    12346Jumps Over
    A
    4855,;*;Lazy 16985/,;a
    Dog.
    11250
    1495


    Example Use/Output



    $ ./bin/fgets_strtol_any <dat/10intmess.txt
    int conversion: 8572 8572
    int conversion: -2213 -2213
    int conversion: 6434 6434
    int conversion: 16330 16330
    int conversion: 3034 3034
    int conversion: 12346 12346
    int conversion: 4855 4855
    int conversion: 16985 16985
    int conversion: 11250 11250
    int conversion: 1495 1495


    Using sscanf



    Similarly, you can use sscanf, but be mindful, it doesn't provide the level or degree of error handling -- meaning you can only know that it either successfully converted the text or it failed. No in between, no reporting of overflow or underflow through errno. But still, it along with strtok are other valid means of parsing integers from a line of text, e.g.



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

    #define MAXC 1024

    int main (int argc, char **argv) {

    char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */
    int nval = 0; /* total number of integers found */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) { /* validate file open for reading */
    fprintf (stderr, "error: file open failed '%s'.n", argv[1]);
    return 1;
    }

    while (fgets (buf, MAXC, fp)) {

    char *p = buf; /* pointer to line */
    int val, /* int val parsed */
    nchars = 0; /* number of chars read */

    /* while chars remain in buf and a valid conversion to int takes place
    * output the integer found and update p to point to the start of the
    * next digit.
    */
    while (*p) {
    if (sscanf (p, "%d%n", &val, &nchars) == 1) {
    printf (" %d", val);
    if (++nval % 10 == 0) /* output 10 int per line */
    putchar ('n');
    }
    p += nchars; /* move p nchars forward in buf */

    /* find next number in buf */
    for (; *p; p++) {
    if (*p >= '0' && *p <= '9') /* positive value */
    break;
    if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */
    break;
    }
    }
    }
    printf ("n %d integers found.n", nval);

    if (fp != stdin) fclose (fp); /* close file if not stdin */

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_sscanf_int_any_ex
    10 10 10 4 4 4 9 9 9 2

    10 integers found.


    or with messy input



    $ echo "1, 2 buckle my shoe, 3, 4..." | ./bin/fgets_sscanf_int_any_ex
    1 2 3 4
    4 integers found.


    Using strtok would simply be a "front-end" to conversion with strtol shown in the first example (which provides its own way to tokenizing numeric values). You simply loop over your buffer calling strtok with delimiters of " n" (space newline) and then using strtol to convert the string pointed to. (here you are simply using endptr to validate digits were converted and ignoring its use to advance past the digits converted. Essentially, strtok duplicates what is already done by strtok, but if it makes it easier to understand, and you can live with the duplicate call, it's fine. You could do something like the following.



        while (fgets (buf, MAXC, fp)) {
    char *p = buf; /* pointer to buf to use with strtok */
    /* 1st call using buffer, all remaining calls using NULL */
    for (p = strtok (p, " n"); p; p = strtok (NULL, " n")) {
    errno = 0; /* reset errno */
    char *endptr; /* end pointer */
    long tmp = strtol (p, &endptr, 0); /* convert using long */
    if (p != endptr) { /* validate digits converted */
    /* now validate value within range of int */
    if (!errno && INT_MIN <= tmp && tmp <= INT_MAX)
    /* you have an integer! */
    }
    else if (tmp == 0)
    /* no digits were converted */
    }
    }


    Look things over and let me know if you have further questions.






    share|improve this answer























    • for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
      – chux
      Nov 20 at 4:01












    • I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
      – chux
      Nov 20 at 4:04






    • 1




      Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
      – David C. Rankin
      Nov 20 at 4:27
















    3














    You have three primary options (1) use strtol in the manner it was intended, using the *endptr parameter to advance the current read position within the string to one past the last digit converted, or (2) pass to sscanf utilizing the "%n" specifier to report the number of characters used in the conversion to int (or whatever type) and using that value to advance the read position in the same manner; or (3) tokenizing the string with strtok and then using strtol (as atoi should not be used as it provides absolutely zero error checking). There really isn't any need to use both strtok and strtol as strtol already provides a way to advance past the digits converted. You are essentially duplicating what has already by done by strtol by using a call to strtok -- but it is a valid way to go.



    For instance using strtol you could do something like the following:



    #include <stdio.h>
    #include <stdlib.h> /* for strtol */
    #include <string.h> /* for strncpy */
    #include <errno.h> /* for errno */

    #define MAXC 1024 /* constant - max chars in line */

    int main (void) {

    char str[MAXC] = ""; /* str to hold line, initialized all zero */

    while (fgets (str, MAXC, stdin)) { /* read each line of input */
    char *p = str, /* pointer for strtol */
    *endptr = NULL; /* end pointer for strtol */

    while (*p) { /* work down str parsing integer or hex values */
    long val = strtol (p, &endptr, 0); /* convert from p */

    /* validate conversion */
    if (p != endptr) { /* were digits converted? */
    if (!errno) { /* if errno 0, successful conversion */
    char ascii[MAXC] = ""; /* for string converted */

    strncpy (ascii, p, endptr - p); /* copy to ascii */
    ascii[endptr-p] = 0; /* nul-terminate ascii */

    /* test whether string begins "0x" or "0X", output */
    if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
    printf ("hex conversion: %-10s %10lu 0x%lxn",
    ascii, val, val);
    else
    printf ("int conversion: %-10s % ldn",
    ascii, val);
    }
    p = endptr; /* advance p to 1-past end of converted string */
    }

    /* find start of next valid number in str, including (+/-) */
    for (; *p; p++) {
    if ('0' <= *p && *p <= '9') /* positive value */
    break; /* explicitly signed value */
    if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9')
    break;
    }
    }
    }

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_strtol_any
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 2 2


    or converting all the integers in a messy file, e.g.



    Example Input File



    $ cat dat/10intmess.txt
    8572,;a -2213,;--a 6434,;
    a- 16330,;a

    - The Quick
    Brown%3034 Fox
    12346Jumps Over
    A
    4855,;*;Lazy 16985/,;a
    Dog.
    11250
    1495


    Example Use/Output



    $ ./bin/fgets_strtol_any <dat/10intmess.txt
    int conversion: 8572 8572
    int conversion: -2213 -2213
    int conversion: 6434 6434
    int conversion: 16330 16330
    int conversion: 3034 3034
    int conversion: 12346 12346
    int conversion: 4855 4855
    int conversion: 16985 16985
    int conversion: 11250 11250
    int conversion: 1495 1495


    Using sscanf



    Similarly, you can use sscanf, but be mindful, it doesn't provide the level or degree of error handling -- meaning you can only know that it either successfully converted the text or it failed. No in between, no reporting of overflow or underflow through errno. But still, it along with strtok are other valid means of parsing integers from a line of text, e.g.



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

    #define MAXC 1024

    int main (int argc, char **argv) {

    char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */
    int nval = 0; /* total number of integers found */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) { /* validate file open for reading */
    fprintf (stderr, "error: file open failed '%s'.n", argv[1]);
    return 1;
    }

    while (fgets (buf, MAXC, fp)) {

    char *p = buf; /* pointer to line */
    int val, /* int val parsed */
    nchars = 0; /* number of chars read */

    /* while chars remain in buf and a valid conversion to int takes place
    * output the integer found and update p to point to the start of the
    * next digit.
    */
    while (*p) {
    if (sscanf (p, "%d%n", &val, &nchars) == 1) {
    printf (" %d", val);
    if (++nval % 10 == 0) /* output 10 int per line */
    putchar ('n');
    }
    p += nchars; /* move p nchars forward in buf */

    /* find next number in buf */
    for (; *p; p++) {
    if (*p >= '0' && *p <= '9') /* positive value */
    break;
    if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */
    break;
    }
    }
    }
    printf ("n %d integers found.n", nval);

    if (fp != stdin) fclose (fp); /* close file if not stdin */

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_sscanf_int_any_ex
    10 10 10 4 4 4 9 9 9 2

    10 integers found.


    or with messy input



    $ echo "1, 2 buckle my shoe, 3, 4..." | ./bin/fgets_sscanf_int_any_ex
    1 2 3 4
    4 integers found.


    Using strtok would simply be a "front-end" to conversion with strtol shown in the first example (which provides its own way to tokenizing numeric values). You simply loop over your buffer calling strtok with delimiters of " n" (space newline) and then using strtol to convert the string pointed to. (here you are simply using endptr to validate digits were converted and ignoring its use to advance past the digits converted. Essentially, strtok duplicates what is already done by strtok, but if it makes it easier to understand, and you can live with the duplicate call, it's fine. You could do something like the following.



        while (fgets (buf, MAXC, fp)) {
    char *p = buf; /* pointer to buf to use with strtok */
    /* 1st call using buffer, all remaining calls using NULL */
    for (p = strtok (p, " n"); p; p = strtok (NULL, " n")) {
    errno = 0; /* reset errno */
    char *endptr; /* end pointer */
    long tmp = strtol (p, &endptr, 0); /* convert using long */
    if (p != endptr) { /* validate digits converted */
    /* now validate value within range of int */
    if (!errno && INT_MIN <= tmp && tmp <= INT_MAX)
    /* you have an integer! */
    }
    else if (tmp == 0)
    /* no digits were converted */
    }
    }


    Look things over and let me know if you have further questions.






    share|improve this answer























    • for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
      – chux
      Nov 20 at 4:01












    • I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
      – chux
      Nov 20 at 4:04






    • 1




      Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
      – David C. Rankin
      Nov 20 at 4:27














    3












    3








    3






    You have three primary options (1) use strtol in the manner it was intended, using the *endptr parameter to advance the current read position within the string to one past the last digit converted, or (2) pass to sscanf utilizing the "%n" specifier to report the number of characters used in the conversion to int (or whatever type) and using that value to advance the read position in the same manner; or (3) tokenizing the string with strtok and then using strtol (as atoi should not be used as it provides absolutely zero error checking). There really isn't any need to use both strtok and strtol as strtol already provides a way to advance past the digits converted. You are essentially duplicating what has already by done by strtol by using a call to strtok -- but it is a valid way to go.



    For instance using strtol you could do something like the following:



    #include <stdio.h>
    #include <stdlib.h> /* for strtol */
    #include <string.h> /* for strncpy */
    #include <errno.h> /* for errno */

    #define MAXC 1024 /* constant - max chars in line */

    int main (void) {

    char str[MAXC] = ""; /* str to hold line, initialized all zero */

    while (fgets (str, MAXC, stdin)) { /* read each line of input */
    char *p = str, /* pointer for strtol */
    *endptr = NULL; /* end pointer for strtol */

    while (*p) { /* work down str parsing integer or hex values */
    long val = strtol (p, &endptr, 0); /* convert from p */

    /* validate conversion */
    if (p != endptr) { /* were digits converted? */
    if (!errno) { /* if errno 0, successful conversion */
    char ascii[MAXC] = ""; /* for string converted */

    strncpy (ascii, p, endptr - p); /* copy to ascii */
    ascii[endptr-p] = 0; /* nul-terminate ascii */

    /* test whether string begins "0x" or "0X", output */
    if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
    printf ("hex conversion: %-10s %10lu 0x%lxn",
    ascii, val, val);
    else
    printf ("int conversion: %-10s % ldn",
    ascii, val);
    }
    p = endptr; /* advance p to 1-past end of converted string */
    }

    /* find start of next valid number in str, including (+/-) */
    for (; *p; p++) {
    if ('0' <= *p && *p <= '9') /* positive value */
    break; /* explicitly signed value */
    if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9')
    break;
    }
    }
    }

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_strtol_any
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 2 2


    or converting all the integers in a messy file, e.g.



    Example Input File



    $ cat dat/10intmess.txt
    8572,;a -2213,;--a 6434,;
    a- 16330,;a

    - The Quick
    Brown%3034 Fox
    12346Jumps Over
    A
    4855,;*;Lazy 16985/,;a
    Dog.
    11250
    1495


    Example Use/Output



    $ ./bin/fgets_strtol_any <dat/10intmess.txt
    int conversion: 8572 8572
    int conversion: -2213 -2213
    int conversion: 6434 6434
    int conversion: 16330 16330
    int conversion: 3034 3034
    int conversion: 12346 12346
    int conversion: 4855 4855
    int conversion: 16985 16985
    int conversion: 11250 11250
    int conversion: 1495 1495


    Using sscanf



    Similarly, you can use sscanf, but be mindful, it doesn't provide the level or degree of error handling -- meaning you can only know that it either successfully converted the text or it failed. No in between, no reporting of overflow or underflow through errno. But still, it along with strtok are other valid means of parsing integers from a line of text, e.g.



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

    #define MAXC 1024

    int main (int argc, char **argv) {

    char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */
    int nval = 0; /* total number of integers found */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) { /* validate file open for reading */
    fprintf (stderr, "error: file open failed '%s'.n", argv[1]);
    return 1;
    }

    while (fgets (buf, MAXC, fp)) {

    char *p = buf; /* pointer to line */
    int val, /* int val parsed */
    nchars = 0; /* number of chars read */

    /* while chars remain in buf and a valid conversion to int takes place
    * output the integer found and update p to point to the start of the
    * next digit.
    */
    while (*p) {
    if (sscanf (p, "%d%n", &val, &nchars) == 1) {
    printf (" %d", val);
    if (++nval % 10 == 0) /* output 10 int per line */
    putchar ('n');
    }
    p += nchars; /* move p nchars forward in buf */

    /* find next number in buf */
    for (; *p; p++) {
    if (*p >= '0' && *p <= '9') /* positive value */
    break;
    if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */
    break;
    }
    }
    }
    printf ("n %d integers found.n", nval);

    if (fp != stdin) fclose (fp); /* close file if not stdin */

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_sscanf_int_any_ex
    10 10 10 4 4 4 9 9 9 2

    10 integers found.


    or with messy input



    $ echo "1, 2 buckle my shoe, 3, 4..." | ./bin/fgets_sscanf_int_any_ex
    1 2 3 4
    4 integers found.


    Using strtok would simply be a "front-end" to conversion with strtol shown in the first example (which provides its own way to tokenizing numeric values). You simply loop over your buffer calling strtok with delimiters of " n" (space newline) and then using strtol to convert the string pointed to. (here you are simply using endptr to validate digits were converted and ignoring its use to advance past the digits converted. Essentially, strtok duplicates what is already done by strtok, but if it makes it easier to understand, and you can live with the duplicate call, it's fine. You could do something like the following.



        while (fgets (buf, MAXC, fp)) {
    char *p = buf; /* pointer to buf to use with strtok */
    /* 1st call using buffer, all remaining calls using NULL */
    for (p = strtok (p, " n"); p; p = strtok (NULL, " n")) {
    errno = 0; /* reset errno */
    char *endptr; /* end pointer */
    long tmp = strtol (p, &endptr, 0); /* convert using long */
    if (p != endptr) { /* validate digits converted */
    /* now validate value within range of int */
    if (!errno && INT_MIN <= tmp && tmp <= INT_MAX)
    /* you have an integer! */
    }
    else if (tmp == 0)
    /* no digits were converted */
    }
    }


    Look things over and let me know if you have further questions.






    share|improve this answer














    You have three primary options (1) use strtol in the manner it was intended, using the *endptr parameter to advance the current read position within the string to one past the last digit converted, or (2) pass to sscanf utilizing the "%n" specifier to report the number of characters used in the conversion to int (or whatever type) and using that value to advance the read position in the same manner; or (3) tokenizing the string with strtok and then using strtol (as atoi should not be used as it provides absolutely zero error checking). There really isn't any need to use both strtok and strtol as strtol already provides a way to advance past the digits converted. You are essentially duplicating what has already by done by strtol by using a call to strtok -- but it is a valid way to go.



    For instance using strtol you could do something like the following:



    #include <stdio.h>
    #include <stdlib.h> /* for strtol */
    #include <string.h> /* for strncpy */
    #include <errno.h> /* for errno */

    #define MAXC 1024 /* constant - max chars in line */

    int main (void) {

    char str[MAXC] = ""; /* str to hold line, initialized all zero */

    while (fgets (str, MAXC, stdin)) { /* read each line of input */
    char *p = str, /* pointer for strtol */
    *endptr = NULL; /* end pointer for strtol */

    while (*p) { /* work down str parsing integer or hex values */
    long val = strtol (p, &endptr, 0); /* convert from p */

    /* validate conversion */
    if (p != endptr) { /* were digits converted? */
    if (!errno) { /* if errno 0, successful conversion */
    char ascii[MAXC] = ""; /* for string converted */

    strncpy (ascii, p, endptr - p); /* copy to ascii */
    ascii[endptr-p] = 0; /* nul-terminate ascii */

    /* test whether string begins "0x" or "0X", output */
    if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
    printf ("hex conversion: %-10s %10lu 0x%lxn",
    ascii, val, val);
    else
    printf ("int conversion: %-10s % ldn",
    ascii, val);
    }
    p = endptr; /* advance p to 1-past end of converted string */
    }

    /* find start of next valid number in str, including (+/-) */
    for (; *p; p++) {
    if ('0' <= *p && *p <= '9') /* positive value */
    break; /* explicitly signed value */
    if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9')
    break;
    }
    }
    }

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_strtol_any
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 10 10
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 4 4
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 9 9
    int conversion: 2 2


    or converting all the integers in a messy file, e.g.



    Example Input File



    $ cat dat/10intmess.txt
    8572,;a -2213,;--a 6434,;
    a- 16330,;a

    - The Quick
    Brown%3034 Fox
    12346Jumps Over
    A
    4855,;*;Lazy 16985/,;a
    Dog.
    11250
    1495


    Example Use/Output



    $ ./bin/fgets_strtol_any <dat/10intmess.txt
    int conversion: 8572 8572
    int conversion: -2213 -2213
    int conversion: 6434 6434
    int conversion: 16330 16330
    int conversion: 3034 3034
    int conversion: 12346 12346
    int conversion: 4855 4855
    int conversion: 16985 16985
    int conversion: 11250 11250
    int conversion: 1495 1495


    Using sscanf



    Similarly, you can use sscanf, but be mindful, it doesn't provide the level or degree of error handling -- meaning you can only know that it either successfully converted the text or it failed. No in between, no reporting of overflow or underflow through errno. But still, it along with strtok are other valid means of parsing integers from a line of text, e.g.



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

    #define MAXC 1024

    int main (int argc, char **argv) {

    char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */
    int nval = 0; /* total number of integers found */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) { /* validate file open for reading */
    fprintf (stderr, "error: file open failed '%s'.n", argv[1]);
    return 1;
    }

    while (fgets (buf, MAXC, fp)) {

    char *p = buf; /* pointer to line */
    int val, /* int val parsed */
    nchars = 0; /* number of chars read */

    /* while chars remain in buf and a valid conversion to int takes place
    * output the integer found and update p to point to the start of the
    * next digit.
    */
    while (*p) {
    if (sscanf (p, "%d%n", &val, &nchars) == 1) {
    printf (" %d", val);
    if (++nval % 10 == 0) /* output 10 int per line */
    putchar ('n');
    }
    p += nchars; /* move p nchars forward in buf */

    /* find next number in buf */
    for (; *p; p++) {
    if (*p >= '0' && *p <= '9') /* positive value */
    break;
    if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */
    break;
    }
    }
    }
    printf ("n %d integers found.n", nval);

    if (fp != stdin) fclose (fp); /* close file if not stdin */

    return 0;
    }


    Example Use/Output



    $ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_sscanf_int_any_ex
    10 10 10 4 4 4 9 9 9 2

    10 integers found.


    or with messy input



    $ echo "1, 2 buckle my shoe, 3, 4..." | ./bin/fgets_sscanf_int_any_ex
    1 2 3 4
    4 integers found.


    Using strtok would simply be a "front-end" to conversion with strtol shown in the first example (which provides its own way to tokenizing numeric values). You simply loop over your buffer calling strtok with delimiters of " n" (space newline) and then using strtol to convert the string pointed to. (here you are simply using endptr to validate digits were converted and ignoring its use to advance past the digits converted. Essentially, strtok duplicates what is already done by strtok, but if it makes it easier to understand, and you can live with the duplicate call, it's fine. You could do something like the following.



        while (fgets (buf, MAXC, fp)) {
    char *p = buf; /* pointer to buf to use with strtok */
    /* 1st call using buffer, all remaining calls using NULL */
    for (p = strtok (p, " n"); p; p = strtok (NULL, " n")) {
    errno = 0; /* reset errno */
    char *endptr; /* end pointer */
    long tmp = strtol (p, &endptr, 0); /* convert using long */
    if (p != endptr) { /* validate digits converted */
    /* now validate value within range of int */
    if (!errno && INT_MIN <= tmp && tmp <= INT_MAX)
    /* you have an integer! */
    }
    else if (tmp == 0)
    /* no digits were converted */
    }
    }


    Look things over and let me know if you have further questions.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 20 at 3:48

























    answered Nov 20 at 3:37









    David C. Rankin

    40.1k32647




    40.1k32647












    • for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
      – chux
      Nov 20 at 4:01












    • I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
      – chux
      Nov 20 at 4:04






    • 1




      Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
      – David C. Rankin
      Nov 20 at 4:27


















    • for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
      – chux
      Nov 20 at 4:01












    • I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
      – chux
      Nov 20 at 4:04






    • 1




      Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
      – David C. Rankin
      Nov 20 at 4:27
















    for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
    – chux
    Nov 20 at 4:01






    for (; *p; p++) { if ('0' <= *p && *p <= '9') /* positive value */ break; /* explicitly signed value */ if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9') break; } could be replaced with } else { p++; }in first code.
    – chux
    Nov 20 at 4:01














    I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
    – chux
    Nov 20 at 4:04




    I found a space in "%d%n" --> "%d %n" nicely and quickly skips trailing spaces. Useful when looking for ''.
    – chux
    Nov 20 at 4:04




    1




    1




    Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
    – David C. Rankin
    Nov 20 at 4:27




    Ooh, that's a nice improvement. It would also cut down on iterating over whitespace searching for the next numeric value as well. Duly noted.
    – David C. Rankin
    Nov 20 at 4:27











    0














    I like to use the function strtol() for this, because if you pass it a pointer, it will return the next point to continue parsing. There are also unsigned versions, e.g.: strtoul(). They are standard since C99. Also strtol() can parse hexadecimal, and handles errors somewhat better than older functions like atoi() (which returns 0 on error).



    The important part of the code below is the result from strtol(). When next_number is un-changed after the call, there is no more input (or an error occurred). The variable ptr is used to keep track of where the parsing is up to in the string. It's given to strtol(), which changes next_number to point to the next element, so then ptr jumps forward - assigned to next_number (past the element just parsed), and the process repeats.



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

    int main(void)
    {
    char *number_str = "10 10 10 4 4 4 9 9 9 2";
    char *ptr;
    char *next_number;
    int numbers[1000];
    int number_count = 0;
    long num;

    next_number = number_str;

    do
    {
    ptr = next_number;
    num = strtol(ptr, &next_number, 10);
    if (ptr != next_number) // found one
    {
    numbers[number_count] = (int)num;
    printf("Stored %3d into numbers[%d]n", numbers[number_count], number_count);
    number_count += 1;
    }
    } while(ptr != next_number);

    return 0;
    }





    share|improve this answer




























      0














      I like to use the function strtol() for this, because if you pass it a pointer, it will return the next point to continue parsing. There are also unsigned versions, e.g.: strtoul(). They are standard since C99. Also strtol() can parse hexadecimal, and handles errors somewhat better than older functions like atoi() (which returns 0 on error).



      The important part of the code below is the result from strtol(). When next_number is un-changed after the call, there is no more input (or an error occurred). The variable ptr is used to keep track of where the parsing is up to in the string. It's given to strtol(), which changes next_number to point to the next element, so then ptr jumps forward - assigned to next_number (past the element just parsed), and the process repeats.



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

      int main(void)
      {
      char *number_str = "10 10 10 4 4 4 9 9 9 2";
      char *ptr;
      char *next_number;
      int numbers[1000];
      int number_count = 0;
      long num;

      next_number = number_str;

      do
      {
      ptr = next_number;
      num = strtol(ptr, &next_number, 10);
      if (ptr != next_number) // found one
      {
      numbers[number_count] = (int)num;
      printf("Stored %3d into numbers[%d]n", numbers[number_count], number_count);
      number_count += 1;
      }
      } while(ptr != next_number);

      return 0;
      }





      share|improve this answer


























        0












        0








        0






        I like to use the function strtol() for this, because if you pass it a pointer, it will return the next point to continue parsing. There are also unsigned versions, e.g.: strtoul(). They are standard since C99. Also strtol() can parse hexadecimal, and handles errors somewhat better than older functions like atoi() (which returns 0 on error).



        The important part of the code below is the result from strtol(). When next_number is un-changed after the call, there is no more input (or an error occurred). The variable ptr is used to keep track of where the parsing is up to in the string. It's given to strtol(), which changes next_number to point to the next element, so then ptr jumps forward - assigned to next_number (past the element just parsed), and the process repeats.



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

        int main(void)
        {
        char *number_str = "10 10 10 4 4 4 9 9 9 2";
        char *ptr;
        char *next_number;
        int numbers[1000];
        int number_count = 0;
        long num;

        next_number = number_str;

        do
        {
        ptr = next_number;
        num = strtol(ptr, &next_number, 10);
        if (ptr != next_number) // found one
        {
        numbers[number_count] = (int)num;
        printf("Stored %3d into numbers[%d]n", numbers[number_count], number_count);
        number_count += 1;
        }
        } while(ptr != next_number);

        return 0;
        }





        share|improve this answer














        I like to use the function strtol() for this, because if you pass it a pointer, it will return the next point to continue parsing. There are also unsigned versions, e.g.: strtoul(). They are standard since C99. Also strtol() can parse hexadecimal, and handles errors somewhat better than older functions like atoi() (which returns 0 on error).



        The important part of the code below is the result from strtol(). When next_number is un-changed after the call, there is no more input (or an error occurred). The variable ptr is used to keep track of where the parsing is up to in the string. It's given to strtol(), which changes next_number to point to the next element, so then ptr jumps forward - assigned to next_number (past the element just parsed), and the process repeats.



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

        int main(void)
        {
        char *number_str = "10 10 10 4 4 4 9 9 9 2";
        char *ptr;
        char *next_number;
        int numbers[1000];
        int number_count = 0;
        long num;

        next_number = number_str;

        do
        {
        ptr = next_number;
        num = strtol(ptr, &next_number, 10);
        if (ptr != next_number) // found one
        {
        numbers[number_count] = (int)num;
        printf("Stored %3d into numbers[%d]n", numbers[number_count], number_count);
        number_count += 1;
        }
        } while(ptr != next_number);

        return 0;
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 20 at 3:14

























        answered Nov 20 at 3:01









        Kingsley

        2,26711022




        2,26711022























            -5














            Just use scanf() to get each number one by one in for or while loop.



            for i = 0 to n
            scanf(“%d”, &num);


            Pls refer google or bing search online how it is done with many examples available.






            share|improve this answer





















            • This answer is not in C-syntax.
              – Kingsley
              Nov 20 at 2:57
















            -5














            Just use scanf() to get each number one by one in for or while loop.



            for i = 0 to n
            scanf(“%d”, &num);


            Pls refer google or bing search online how it is done with many examples available.






            share|improve this answer





















            • This answer is not in C-syntax.
              – Kingsley
              Nov 20 at 2:57














            -5












            -5








            -5






            Just use scanf() to get each number one by one in for or while loop.



            for i = 0 to n
            scanf(“%d”, &num);


            Pls refer google or bing search online how it is done with many examples available.






            share|improve this answer












            Just use scanf() to get each number one by one in for or while loop.



            for i = 0 to n
            scanf(“%d”, &num);


            Pls refer google or bing search online how it is done with many examples available.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 20 at 2:36









            anand

            802




            802












            • This answer is not in C-syntax.
              – Kingsley
              Nov 20 at 2:57


















            • This answer is not in C-syntax.
              – Kingsley
              Nov 20 at 2:57
















            This answer is not in C-syntax.
            – Kingsley
            Nov 20 at 2:57




            This answer is not in C-syntax.
            – Kingsley
            Nov 20 at 2:57


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384946%2fhow-do-i-parse-a-string-of-numbers-into-a-array-of-integers%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            If I really need a card on my start hand, how many mulligans make sense? [duplicate]

            Alcedinidae

            Can an atomic nucleus contain both particles and antiparticles? [duplicate]