-1

Learning C and checking the reference from the GNU reference manual. I don't understand how is the maximum size that can be allocated to a char array defined in an exact way. In my test program when the allocated size for a string array is "small" it works fine but when it is "large" the program start behaving erratically. The compiler throws no errors when it gets compiled but during runtime, it is affecting the correctness of my program that uses strtok(), missing some valid tokens in the result.

Taking as input (considering 5 an arbitrary "small" array size):

>> 5 
>> 19 65 41 65 56

The sum output is 246 so it works well

But taking as input (considering 53 an arbitrary "large" array size):

>> 53
>> 19 65 41 65 56 74 76 71 29 44 45 9 66 37 59 6 71 8 30 29 41 31 96 86 11 14 29 24 17 65 88 23 21 49 31 96 72 39 83 96 96 63 44 72 85 38 5 11 70 36 90 49 76

The sum output is 2247 which is wrong (correct is 2647). This incorrectness holds for any "large" number of array_size

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

int main(){
  /*Array size is the amount of integers that will be introduced later. E.g: 5 (introducting 5 integers next) -> 3 4 5 6 7*/
  /*The numbers are 1 <= n <= 1000 */
  int array_size;  
  scanf("%d", &array_size);
  printf("The array size you introduced is %d\n", array_size);  

  /* Given that the integers introduced can have at most 4 digits and they are separated by a whitespace character, array_size*5 is allocated */
  char sentence[array_size * 5];
  scanf("\n");
  scanf("%[^\n]%*c", sentence);

  char delimiter = ' ';
  char *token;
  token = strtok(sentence, &delimiter);
  int sumResult; 
  printf("The token %d is %s\n", 1, token);   
                     
  while (token != NULL) {                
    sumResult = sumResult + atoi(token);
    token = strtok(NULL, &delimiter);
    printf("The token is %s\n", token);
  }
  
  printf("%d\n", sumResult);
}
7
  • That doesn't solve it :( Commented Sep 9, 2022 at 18:20
  • @varinme This statement printf("The token is %s\n", token); can invoke undefined behavior. Commented Sep 9, 2022 at 18:23
  • Thanks, @VladfromMoscow can you point me to why is that? Do you mean I should dereference "token"? Commented Sep 9, 2022 at 18:34
  • @varinme You need to execute this statement only if token is not a null pointer. Commented Sep 9, 2022 at 18:35
  • @varinme see my answer - I have corrected your errors and it works fine Commented Sep 9, 2022 at 18:45

2 Answers 2

2

There are (at least) three errors in the program:

int sumResult; leaves sumResult uninitialized. It must be initialized to zero, as with int sumResult = 0;.

strtok(sentence, &delimiter) passes the address of a single character to strtok. For the second parameter, strtok expects a pointer to the first character of a string, meaning a sequence of characters terminating by a null character. Change the definition of delimeter to char delimiter[] = " "; and change both strtok calls to strtok(sentence, delimiter);.

printf("The token is %s\n", token); is executed once when token is a null pointer. For %s, printf should be passed a pointer to the first character of a string, not a null pointer. This can be remedied by moving this printf to be the first line in the while loop and deleting the prior printf("The token %d is %s\n", 1, token);.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for such a comprehensive explanation! I will be studying this in-depth!
Going over this again, I messed up with the second argument of strtok() and now I understand why. Thanks again!
1
int sumResult; 

When sumResult is not initialized, it does not have a determined value. In the language of the C standard, is value is indeterminate, meaning that the program may behave as if sumResult has no fixed value at all; it may appear to have different values at different times. Further, in this program, using it without it being initialized results in the entire behavior of the program not being defined by the C standard.

int sumResult = 0; 

In the C language object (variables) have different storage durations.

  1. Variables defined in the function scope have automatic storage duration and are not automatically initialized.
  2. Variables defined outside of any function (file scope) and variables defined in functions but declared as static have static storage duration and are automatically initialized (to zero or equivalent for their type) on program startup.

You can do it much easier:

int main(void)
{
/*Array size is the amount of integers that will be introduced later. E.g: 5 (introducting 5 integers next) -> 3 4 5 6 7*/
/*The numbers are 1 <= n <= 1000 */
    size_t array_size;  
    if(scanf("%zu",&array_size) != 1) {/* error handling */}
    printf("The array size you introduced is %zu\n", array_size);  
    int array[array_size];

    /* Given that the integers introduced can have at most 4 digits and they are separated by a whitespace character, array_size*5 is allocated */
    int sumResult = 0; 

    for(size_t num = 0; num < array_size; num++)
    {
        if(scanf("%d", array + num) != 1 ) {/* error handling */; break;}
        sumResult += array[num];
    }
    printf("%d\n", sumResult);
}

https://godbolt.org/z/zoWz1cjc7

Your code "repaired"

int main(){
  /*Array size is the amount of integers that will be introduced later. E.g: 5 (introducting 5 integers next) -> 3 4 5 6 7*/
  /*The numbers are 1 <= n <= 1000 */
  int array_size;  
  scanf("%d", &array_size);
  printf("The array size you introduced is %d\n", array_size);  

  /* Given that the integers introduced can have at most 4 digits and they are separated by a whitespace character, array_size*5 is allocated */
  char sentence[array_size * 5];
  scanf("\n");
  scanf("%[^\n]%*c", sentence);

  char delimiter[] = " ";
  char *token;
  token = strtok(sentence, delimiter);
  int sumResult = 0; 
  printf("The token %d is %s\n", atoi(token), token);   
                     
  while (token != NULL) {                
    sumResult = sumResult + atoi(token);
    printf("The token is %s %d\n", token, atoi(token));
    token = strtok(NULL, delimiter);
  }
  
  printf("%d\n", sumResult);
}

https://godbolt.org/z/1qj3acn55

5 Comments

Thanks but it doesn't solve it. It has to do with the size of the array not with the initialization of sumArray. It works consistently well for small sizes but breaks when the amount of numbers is large.
@varinme see more simple code
@varinme: When the value stored in an object is not controlled, because the program has not initialized it, it can be affected by other things, such as the size of some array that is created. So you cannot conclude merely from experiments showing that the program “works consistently well” for small sizes but not for large sizes means the problem is not that sumResult is not initialized.
Thanks for the insight @EricPostpischil . I did edit the code and initialized sumArray to zero but the behavior is still the same that's why I previously commented that :confused
@varinme you do not need strtok to read values.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.