Search code examples
cstrncpy

C: strncpy unexpectedly truncating string


I am reading a file line by line, where each line is of the format:

" number1 \t number2".

I am using strtok and strncpy to split and then store the two values as needed. However, I find that after strncpy, number1 is truncated by one digit.

Any ideas of why this could be and how to solve it?

For simplicity, I have hard coded a line_of_text to simulate the problem.

Thanks!

Code:

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


int main()
{
  char line_of_text[80] = "  18306000  \t 100\n"; 
  // NB: There's a \t between the two values, the rest are spaces.

  char* token;

  int digits_per_num = 9;

  char first_token[digits_per_num];
  char second_token[digits_per_num];

  token = strtok (line_of_text, "\t");

  printf("first token: %s\n", token);

  if (token != NULL)
    {
      strncpy (first_token, token, digits_per_num);
    }

    token = strtok (NULL, ",\t\n");
    if (token != NULL)
    {
      strncpy (second_token, token, digits_per_num);
    }


    printf("first token copy: %s\n", first_token);
    printf("second token copy: %s\n", second_token);

}

Output:

first token:  18306000
first token copy: 1830600<junk>
second token copy: 100

Solution

  • The first token consists of the 10 bytes: 18306000\0.

    strncpy() only writes the null character in if it fits in the destination buffer. But you've allocated one character too few so it doesn't.

    The easiest fix is to include spaces in your delimiter on both strtok calls:

    token = strtok (line_of_text, " \t\n,");
    

    I'd also recommend using snprintf() instead of strncpy so you're always guaranteed to get a null character at the end of your strings.