0

I am self teaching C programming. I am trying to count number of int present in given string which are separated by space.

exp: input str = "1 2 11 84384 0 212" output should be: 1, 2, 11, 84384, 0, 212 total int = 6

When I try. It gives me all the digits as output which make sense since I am not using a right approach here.

I know in python I can use str.split (" ") function which can do my job very quickly.

But I want to try something similar in C. Trying to create my own split method.

#include <stdio.h>
#include <string.h>
void count_get_ints(const char *data) {
    int buf[10000];
    int cnt = 0, j=0;
    for (int i=0; i<strlen(data); i++) {
        if (isspace(data[i] == false)
            buf[j] = data[i]-'0';
            j++;
    }
    printf("%d", j);

}

// when I check the buffer it includes all the digits of the numbers.
// i.e for my example.
// buf = {1,2,1,1,8,4,3,8,4,0,2,1,2} 
// I want buf to be following 
// buf = {1,2,11,84384,0,212}

I know this is not a right approach to solve this problem. One way to keep track of prev and dynamically create a memory using number of non space digits encountered. But I am not sure if that approach helps.

kkard
  • 79
  • 3
  • 10
  • your approach might work if you have 1-number integer, but you have integers which span several symbols. As a hint, you need to find out a position when the integer starts in the string. Then you can use the `strtol` function to convert the portion of the string at its start into an integer. – Serge Aug 02 '17 at 00:20

6 Answers6

2

You want to build your number incrementally until you hit a space, then put that into the array. You can do this by multiplying by 10 then adding the next digit each time.

void count_get_ints(const char *data) {
    int buf[10000];
    int j = 0;
    int current_number = 0;

    // Move this outside the loop to eliminate recalculating the length each time
    int total_length = strlen(data); 
    for (int i=0; i <= total_length; i++) {
        // Go up to 1 character past the length so you 
        //   capture the last number as well
        if (i == total_length || isspace(data[i])) {
            // Save the number, and reset it
            buf[j++] = current_number;
            current_number = 0;
        }
        else {
            current_number *= 10;
            current_number += data[i] - '0';
        }
    }
}
Felix Guo
  • 2,700
  • 14
  • 20
2

I think strtok will provide a cleaner solution, unless you really want to iterate over every char in the string. It has been a while since I did C, so please excuse any errors in the code below, hopefully it will give you the right idea.

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

int main() {
    char str[19] = "1 2 11 84384 0 212";
    const char s[2] = " ";
    char *token;
    int total;

    total = 0;
    token = strtok(str, s);

    while (token != NULL) {
        printf("%s\n", token);
        total += atoi(token);
        token = strtok(NULL, s);
    }
    printf("%d\n", total);

    return 0;
}
Fjotten
  • 347
  • 3
  • 13
0

You can check the ascii value of each character by doing c-'0'. If it's between [0,9], then it's an integer. By having a state variable, when you're inside an integer by checking if a given character is a number of space, you can keep track of the count by ignoring white space. Plus you don't need a buffer, what happens if data is larger than 10,000, and you write pass the end of the buffer?, undefined behavior will happen. This solution doesn't require a buffer.

Edit, the solution now prints the integers that are in the string

void count_get_ints(const char *data) {
   int count = 0;
   int state = 0;
   int start = 0;
   int end = 0;
   for(int i = 0; i<strlen(data); i++){
      int ascii = data[i]-'0';
      if(ascii >= 0 && ascii <= 9){
         if(state == 0){
            start = i;
         }
         state = 1;
      }else{
         //Detected a whitespace
         if(state == 1){
            count++;
            state = 0;
            end = i;
            //Print the integer from the start to end spot in data
            for(int j = start; j<end; j++){
                printf("%c",data[j]);
            }
            printf(" ");
         }
      }
   }
   //Check end
   if(state == 1){
      count++;
      for(int j = start; j<strlen(data); j++){
          printf("%c",data[j]);
      }
      printf(" ");
   }
   printf("Number of integers %d\n",count);
}
Miket25
  • 1,895
  • 3
  • 15
  • 29
0

I believe the standard way of doing this would be using sscanf using the %n format specifier to keep track of how much of the string is read.

You can start with a large array to read into -

int array[100];

Then you can keep reading integers from the string till you can't read anymore or you are done reading 100.

int total = 0;
int cont = 0;
int ret = 1;
while(ret == 1 && total < 100) {
    ret = sscanf(input, "%d%n", &array[total++], &cont);
    input += cont;
}
total--;
printf("Total read = %d\n", total);

and array contains all the numbers read.

Here is the DEMO

Ajay Brahmakshatriya
  • 8,993
  • 3
  • 26
  • 49
0

Example using strtol

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>

int count_get_ints(int output[], int output_size, const char *input) {
    const char *p = input;
    int cnt;

    for(cnt = 0; cnt < output_size && *p; ++cnt){
        char *endp;
        long n;
        errno = 0;
        n = strtol(p, &endp, 10);
        if(errno == 0 && (isspace((unsigned char)*endp) || !*endp) && INT_MIN <= n && n <= INT_MAX){
            output[cnt] = n;
            while(isspace((unsigned char)*endp))
                ++endp;//skip spaces
            p = endp;//next parse point
        } else {
            fprintf(stderr, "invalid input '%s' in %s\n", p, __func__);
            break;
        }
    }
    return cnt;
}

int main(void) {
    const char *input = "1 2 11 84384 0 212";
    int data[10000];
    int n = sizeof(data)/sizeof(*data);//number of elements of data

    n = count_get_ints(data, n, input);
    for(int i = 0; i < n; ++i){
        if(i)
            printf(", ");
        printf("%d", data[i]);
    }
    puts("");
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
-1

Assuming you don't have any non-numbers in your string, you can just count the number of spaces + 1 to find the number of integers in the string like so in this pseudo code:

for(i = 0; i < length of string; i++) {
   if (string x[i] == " ") {
      Add y to the list of strings
      string y = "";
      counter++;
   }

   string y += string x[i]
}

numberOfIntegers =  counter + 1;

Also, this reads the data between the white spaces. Keep in mind this is pseudo code, so the syntax is different.

Devin L.
  • 437
  • 2
  • 12